@@ -403,4 +403,160 @@ strmode(mode_t mode, char *p)
403
403
* p ++ = ' ' ; /* will be a '+' if ACL's implemented */
404
404
* p = '\0' ;
405
405
}
406
+
407
+ #include <winioctl.h>
408
+ // Maximum reparse buffer info size. The max user defined reparse
409
+ // data is 16KB, plus there's a header.
410
+ //
411
+ #define MAX_REPARSE_SIZE 17000
412
+
413
+ #define IO_REPARSE_TAG_SYMBOLIC_LINK IO_REPARSE_TAG_RESERVED_ZERO
414
+ #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) // winnt ntifs
415
+ #define IO_REPARSE_TAG_HSM (0xC0000004L) // winnt ntifs
416
+ #define IO_REPARSE_TAG_SIS (0x80000007L) // winnt ntifs
417
+
418
+
419
+ //
420
+ // Undocumented FSCTL_SET_REPARSE_POINT structure definition
421
+ //
422
+ #define REPARSE_MOUNTPOINT_HEADER_SIZE 8
423
+ typedef struct {
424
+ DWORD ReparseTag ;
425
+ DWORD ReparseDataLength ;
426
+ WORD Reserved ;
427
+ WORD ReparseTargetLength ;
428
+ WORD ReparseTargetMaximumLength ;
429
+ WORD Reserved1 ;
430
+ WCHAR ReparseTarget [1 ];
431
+ } REPARSE_MOUNTPOINT_DATA_BUFFER , * PREPARSE_MOUNTPOINT_DATA_BUFFER ;
432
+
433
+
434
+ typedef struct _REPARSE_DATA_BUFFER {
435
+ ULONG ReparseTag ;
436
+ USHORT ReparseDataLength ;
437
+ USHORT Reserved ;
438
+ union {
439
+ struct {
440
+ USHORT SubstituteNameOffset ;
441
+ USHORT SubstituteNameLength ;
442
+ USHORT PrintNameOffset ;
443
+ USHORT PrintNameLength ;
444
+ WCHAR PathBuffer [1 ];
445
+ } SymbolicLinkReparseBuffer ;
446
+ struct {
447
+ USHORT SubstituteNameOffset ;
448
+ USHORT SubstituteNameLength ;
449
+ USHORT PrintNameOffset ;
450
+ USHORT PrintNameLength ;
451
+ WCHAR PathBuffer [1 ];
452
+ } MountPointReparseBuffer ;
453
+ struct {
454
+ UCHAR DataBuffer [1 ];
455
+ } GenericReparseBuffer ;
456
+ };
457
+ } REPARSE_DATA_BUFFER , * PREPARSE_DATA_BUFFER ;
458
+
459
+ BOOL ResolveLink (char * tLink , char * ret , DWORD * plen , DWORD Flags )
460
+ {
461
+ HANDLE fileHandle ;
462
+ BYTE reparseBuffer [MAX_REPARSE_SIZE ];
463
+ PBYTE reparseData ;
464
+ PREPARSE_GUID_DATA_BUFFER reparseInfo = (PREPARSE_GUID_DATA_BUFFER )reparseBuffer ;
465
+ PREPARSE_DATA_BUFFER msReparseInfo = (PREPARSE_DATA_BUFFER )reparseBuffer ;
466
+ DWORD returnedLength ;
467
+
468
+ if (Flags & FILE_ATTRIBUTE_DIRECTORY )
469
+ {
470
+ fileHandle = CreateFile (tLink , 0 ,
471
+ FILE_SHARE_READ | FILE_SHARE_WRITE , NULL ,
472
+ OPEN_EXISTING ,
473
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT , 0 );
474
+
475
+ }
476
+ else {
477
+
478
+ //
479
+ // Open the file
480
+ //
481
+ fileHandle = CreateFile (tLink , 0 ,
482
+ FILE_SHARE_READ | FILE_SHARE_WRITE , NULL ,
483
+ OPEN_EXISTING ,
484
+ FILE_FLAG_OPEN_REPARSE_POINT , 0 );
485
+ }
486
+ if (fileHandle == INVALID_HANDLE_VALUE )
487
+ {
488
+ sprintf_s (ret , * plen , "%s" , tLink );
489
+ return TRUE;
490
+ }
491
+
492
+ if (GetFileAttributes (tLink ) & FILE_ATTRIBUTE_REPARSE_POINT ) {
493
+
494
+ if (DeviceIoControl (fileHandle , FSCTL_GET_REPARSE_POINT ,
495
+ NULL , 0 , reparseInfo , sizeof (reparseBuffer ),
496
+ & returnedLength , NULL )) {
497
+
498
+ if (IsReparseTagMicrosoft (reparseInfo -> ReparseTag )) {
499
+
500
+ switch (reparseInfo -> ReparseTag ) {
501
+ case 0x80000000 | IO_REPARSE_TAG_SYMBOLIC_LINK :
502
+ case IO_REPARSE_TAG_MOUNT_POINT :
503
+ if (* plen >= msReparseInfo -> MountPointReparseBuffer .SubstituteNameLength )
504
+ {
505
+ reparseData = (PBYTE )& msReparseInfo -> SymbolicLinkReparseBuffer .PathBuffer ;
506
+ WCHAR temp [1024 ];
507
+ wcsncpy_s (temp , 1024 ,
508
+ (PWCHAR )(reparseData + msReparseInfo -> MountPointReparseBuffer .SubstituteNameOffset ),
509
+ (size_t )msReparseInfo -> MountPointReparseBuffer .SubstituteNameLength );
510
+ temp [msReparseInfo -> MountPointReparseBuffer .SubstituteNameLength ] = 0 ;
511
+ sprintf_s (ret , * plen , "%S" , & temp [4 ]);
512
+ }
513
+ else
514
+ {
515
+ sprintf_s (ret , * plen , "%s" , tLink );
516
+ return FALSE;
517
+ }
518
+
519
+ break ;
520
+ default :
521
+ break ;
522
+ }
523
+ }
524
+ }
525
+ }
526
+ else {
527
+ sprintf_s (ret , * plen , "%s" , tLink );
528
+ }
529
+
530
+ CloseHandle (fileHandle );
531
+ return TRUE;
532
+ }
533
+
534
+ char * get_inside_path (char * opath , BOOL bResolve , BOOL bMustExist )
535
+ {
536
+ BOOL ResolveLink (char * tLink , char * ret , DWORD * plen , DWORD Flags );
537
+
538
+ char * ipath ;
539
+ char * temp_name ;
540
+ char temp [1024 ];
541
+ DWORD templen = sizeof (temp );
542
+ WIN32_FILE_ATTRIBUTE_DATA FileInfo ;
543
+
544
+
545
+ if (!GetFileAttributesEx (opath , GetFileExInfoStandard , & FileInfo ) && bMustExist )
546
+ {
547
+ return NULL ;
548
+ }
549
+
550
+ if (bResolve )
551
+ {
552
+ ResolveLink (opath , temp , & templen , FileInfo .dwFileAttributes );
553
+ ipath = xstrdup (temp );
554
+ }
555
+ else
556
+ {
557
+ ipath = xstrdup (opath );
558
+ }
559
+
560
+ return ipath ;
561
+ }
406
562
#endif
0 commit comments