47 #ifndef FSCTL_GET_REPARSE_POINT // ntifs.h and winioctl.h 50 #define CTL_CODE( DeviceType, Function, Method, Access ) ( \ 51 ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ 54 #ifndef FILE_DEVICE_FILE_SYSTEM 55 #define FILE_DEVICE_FILE_SYSTEM 0x00000009 57 #ifndef METHOD_BUFFERED 58 #define METHOD_BUFFERED 0 60 #ifndef FILE_ANY_ACCESS 61 #define FILE_ANY_ACCESS 0 66 #define FSCTL_GET_REPARSE_POINT \ 67 CTL_CODE( FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS ) 69 #define FSCTL_SET_REPARSE_POINT \ 70 CTL_CODE( FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ) 72 #define FSCTL_DELETE_REPARSE_POINT \ 73 CTL_CODE( FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ) 75 #endif//ndef FSCTL_GET_REPARSE_POINT 76 #ifndef _NTIFS_ // Copy REPARSE_DATA_BUFFER from the DDK.. 78 typedef struct _REPARSE_DATA_BUFFER {
84 USHORT SubstituteNameOffset;
85 USHORT SubstituteNameLength;
86 USHORT PrintNameOffset;
87 USHORT PrintNameLength;
90 } SymbolicLinkReparseBuffer;
92 USHORT SubstituteNameOffset;
93 USHORT SubstituteNameLength;
94 USHORT PrintNameOffset;
95 USHORT PrintNameLength;
97 } MountPointReparseBuffer;
100 } GenericReparseBuffer;
104 #define REPARSE_DATA_BUFFER_HEADER_SIZE \ 105 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer ) 107 #ifndef SYMLINK_FLAG_RELATIVE 108 #define SYMLINK_FLAG_RELATIVE 0x00000001 110 #ifndef IO_REPARSE_TAG_IIS_CACHE 111 #define IO_REPARSE_TAG_IIS_CACHE 0xA0000010 // I don't know the data struct of this.. 113 #define IO_REPARSE_TAG_VALID_VALUES 0xF000FFFF 115 #define IsReparseTagValid(_tag) ( \ 116 !((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) \ 117 && ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE) \ 122 #define MAX_REPARSE_BUFFER \ 123 MAXIMUM_REPARSE_DATA_BUFFER_SIZE // 16 kB 129 #define SET_WRPD_PRIVILEGE 1 131 #if 0 // Memo - These are declared in WinNT.h 132 typedef struct _REPARSE_GUID_DATA_BUFFER
135 USHORT ReparseDataLength;
140 } GenericReparseBuffer;
142 REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;
144 #define REPARSE_GUID_DATA_BUFFER_HEADER_SIZE \ 145 FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer ) 158 LinkName, Access, Share, NULL, OPEN_EXISTING,
159 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
164 static bool _IsNameSurrogateTag(
DWORD Tag )
168 if (!ok) SetLastError( ERROR_INVALID_DATA );
171 #if 0 // Flaw: This doesn't exclude future unknown surrogates. 172 ok = IsReparseTagMicrosoft( Tag );
173 if (ok ) ok = IsReparseTagNameSurrogate( Tag );
174 #else // So, be specific: We know symlinks and mount points. 175 ok = (Tag == IO_REPARSE_TAG_SYMLINK);
176 if (!ok) ok = (Tag == IO_REPARSE_TAG_MOUNT_POINT);
178 if (!ok) SetLastError( ERROR_NOT_SUPPORTED );
183 static CSTR _AbsTargetPrefixPath(
CSTR TargetPath )
186 static __thread_local TCHAR PfxPath[ MAX_PATH ] = _T(
"\\??\\");
194 if (_tcsncmp( TargetPath, PfxPath, 4 ) != 0)
196 _tcsncpyz( &PfxPath[4], TargetPath, MAX_PATH-4 );
197 TargetPath = PfxPath;
202 #if 0 // Absolute symlink targets need to be preceeded by the "nonparsed" (\??\) prefix. 203 #define ABS_TARGET_PREFIX_PATH( TargetPath ) \ 204 TCHAR _PfxPath[ MAX_PATH ] = _T("\\??\\"); \ 205 if (_tcsncmp( TargetPath, _PfxPath, 4 ) != 0) { \ 206 _tcsncpyz( &_PfxPath[4], TargetPath, MAX_PATH-4 ); \ 207 TargetPath = _PfxPath; \ 215 bool ok =
BITS_SET( FILE_SUPPORTS_REPARSE_POINTS, volFlg );
216 if (!ok) SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
220 static bool _CanSetReparseData(
CSTR PathName )
231 bool alreadySet =
BITS_SET( FILE_ATTRIBUTE_REPARSE_POINT, attr.LowPart );
236 if (!objExist) SetLastError( ERROR_FILE_NOT_FOUND );
237 else if (alreadySet) SetLastError( ERROR_ALREADY_INITIALIZED );
238 ok = objExist && !alreadySet;
243 static void _ShNfyDirOf(
CSTR Path, LONG evId )
246 TCHAR szDir[ MAX_PATH ];
248 PathRemoveFileSpec( szDir );
249 SHChangeNotify( evId, SHCNF_PATH, szDir, NULL );
265 DWORD cbRtn, headerSize;
266 REPARSE_GUID_DATA_BUFFER rpd, *pd;
267 ULARGE_INTEGER info = {{0,0}};
269 if (!hObj) SetLastError( ERROR_INVALID_HANDLE );
274 IF_DEBUG( memset( &rpd, 0,
sizeof(rpd) ));
276 cbBuffer =
sizeof(rpd);
278 BOOL ok = DeviceIoControl(
280 Buffer, cbBuffer, &cbRtn, NULL
282 pd = (PREPARSE_GUID_DATA_BUFFER) Buffer;
285 info.HighPart = pd->ReparseTag;
286 info.LowPart = cbRtn;
288 else if (GetLastError() == ERROR_MORE_DATA)
293 if (IsReparseTagNameSurrogate( pd->ReparseTag )
294 && IsReparseTagMicrosoft( pd->ReparseTag ))
296 else headerSize = REPARSE_GUID_DATA_BUFFER_HEADER_SIZE;
298 info.HighPart = pd->ReparseTag;
299 info.LowPart = pd->ReparseDataLength + headerSize;
311 #if SET_WRPD_PRIVILEGE // AFAIK, SE_RESTORE_NAME is required.. 312 HANDLE hToken; TOKEN_PRIVILEGES tp = { 1, { 0,0,0 }};
316 DWORD cbRtn, error = 0;
323 #if SET_WRPD_PRIVILEGE 325 if (hToken) CloseHandle( hToken );
327 if (!ok && error) SetLastError( error );
334 static bool _GetNameSurrogates( PREPARSE_DATA_BUFFER pRpd,
WSTR wzSubst,
WSTR wzPrint )
336 bool isMountPoint = (pRpd->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
337 bool isSymLink = (pRpd->ReparseTag == IO_REPARSE_TAG_SYMLINK);
338 bool ok = isMountPoint || isSymLink;
344 USHORT ccSubst = pRpd->MountPointReparseBuffer.SubstituteNameLength /
WCHAR_SIZE;
345 USHORT ccPrint = pRpd->MountPointReparseBuffer.PrintNameLength /
WCHAR_SIZE;
346 USHORT ccSubstOffs = pRpd->MountPointReparseBuffer.SubstituteNameOffset /
WCHAR_SIZE;
347 USHORT ccPrintOffs = pRpd->MountPointReparseBuffer.PrintNameOffset /
WCHAR_SIZE;
349 WSTR rpdPath = isMountPoint
350 ? pRpd->MountPointReparseBuffer.PathBuffer
351 : pRpd->SymbolicLinkReparseBuffer.PathBuffer;
353 if (wzSubst)
wcsncpyz( wzSubst, &rpdPath[ccSubstOffs], ccSubst+1 );
354 if (wzPrint)
wcsncpyz( wzPrint, &rpdPath[ccPrintOffs], ccPrint+1 );
372 CNSF_MOUNTPOINT = 0x0002,
373 CNSF_SYMLINK = 0x0000,
374 CNSF_DIRECTORY = 0x0004,
375 CNSF_NOPARSE = 0x0008
379 #if 1 // V2 - TODO: Verify it still works.. 380 static bool _CreateNameSurrogate(
CSTR LinkName,
CSTR TargetName,
CSTR PrintName,
WORD Flags )
383 #if 0 // No longer required (since Win6.0 ?) 384 if (ok && (Flags & CNSF_DIRECTORY)) ok = (TargetName[ _tcslen(TargetName) - 1 ] !=
BSLASH);
394 WORD cbSubstName, cbPrintName, cbPrintOffs, ccPrintOffs, cbPathBufOffs, cbBuf;
396 if (!PrintName) PrintName = TargetName;
398 #define wzTargetName TargetName 399 #define wszPrintName PrintName 401 WCHAR wzTargetName[ MAX_PATH ], wszPrintName[ MAX_PATH ];
402 MultiByteToWideChar( CP_ACP, 0, TargetName,-1, wzTargetName, MAX_PATH );
403 MultiByteToWideChar( CP_ACP, 0, PrintName,-1, wszPrintName, MAX_PATH );
408 cbSubstName = (
WORD) wcslen( wzTargetName ) *
sizeof(WCHAR);
409 cbPrintName = (
WORD) wcslen( wzPrintName ) *
sizeof(WCHAR);
410 cbPrintOffs = cbSubstName +
sizeof(WCHAR);
411 ccPrintOffs = cbPrintOffs /
sizeof(WCHAR);
415 cbPathBufOffs = (Flags & CNSF_MOUNTPOINT)
419 cbBuf = cbPathBufOffs + cbSubstName + cbPrintName + 2*
sizeof(WCHAR);
421 PREPARSE_DATA_BUFFER prdb = (PREPARSE_DATA_BUFFER)
mem_Alloc( cbBuf );
425 if (Flags & CNSF_MOUNTPOINT)
426 prdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
429 prdb->ReparseTag = IO_REPARSE_TAG_SYMLINK;
430 prdb->SymbolicLinkReparseBuffer.Flags = (Flags & CNSF_RELATIVE);
438 prdb->MountPointReparseBuffer.SubstituteNameLength = cbSubstName;
439 prdb->MountPointReparseBuffer.PrintNameLength = cbPrintName;
440 prdb->MountPointReparseBuffer.PrintNameOffset = cbPrintOffs;
443 memcpy( pwzPathBuf, wzTargetName, cbSubstName );
444 memcpy( pwzPathBuf + ccPrintOffs, wzPrintName, cbPrintName );
450 CloseHandle( hLink );
452 if (!ok && error) SetLastError( error );
457 static bool _CreateNameSurrogate(
CSTR LinkName,
CSTR TargetName,
CSTR PrintName,
WORD Flags )
460 #if 0 // No longer required (since Win6.0 ?) 461 if (ok && (Flags & CNSF_DIRECTORY)) ok = (TargetName[ _tcslen(TargetName) - 1 ] !=
BSLASH);
466 #if SET_WRPD_PRIVILEGE 467 HANDLE hToken; TOKEN_PRIVILEGES tp = { 1, { 0,0 }};
477 WORD cbSubstName, cbPrintName, cbPrintOffs, ccPrintOffs, cbPathBufOffs, cbBuf;
479 if (!PrintName) PrintName = TargetName;
481 #define wzTargetName TargetName 482 #define wszPrintName PrintName 484 WCHAR wzTargetName[ MAX_PATH ], wszPrintName[ MAX_PATH ];
485 MultiByteToWideChar( CP_ACP, 0, TargetName,-1, wzTargetName, MAX_PATH );
486 MultiByteToWideChar( CP_ACP, 0, PrintName,-1, wszPrintName, MAX_PATH );
491 cbSubstName = (
WORD) wcslen( wzTargetName ) *
sizeof(WCHAR);
492 cbPrintName = (
WORD) wcslen( wzPrintName ) *
sizeof(WCHAR);
493 cbPrintOffs = cbSubstName +
sizeof(WCHAR);
494 ccPrintOffs = cbPrintOffs /
sizeof(WCHAR);
498 cbPathBufOffs = (Flags & CNSF_MOUNTPOINT)
502 cbBuf = cbPathBufOffs + cbSubstName + cbPrintName + 2*
sizeof(WCHAR);
504 PREPARSE_DATA_BUFFER prdb = (PREPARSE_DATA_BUFFER)
mem_Alloc( cbBuf );
508 if (Flags & CNSF_MOUNTPOINT)
509 prdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
512 prdb->ReparseTag = IO_REPARSE_TAG_SYMLINK;
513 prdb->SymbolicLinkReparseBuffer.Flags = (Flags & CNSF_RELATIVE);
521 prdb->MountPointReparseBuffer.SubstituteNameLength = cbSubstName;
522 prdb->MountPointReparseBuffer.PrintNameLength = cbPrintName;
523 prdb->MountPointReparseBuffer.PrintNameOffset = cbPrintOffs;
526 memcpy( pwzPathBuf, wzTargetName, cbSubstName );
527 memcpy( pwzPathBuf + ccPrintOffs, wzPrintName, cbPrintName );
535 CloseHandle( hLink );
537 #if SET_WRPD_PRIVILEGE 539 if (hToken) CloseHandle( hToken );
541 if (!ok && error) SetLastError( error );
545 #endif //_CreateNameSurrogate 552 #if 1 // Faster execution in the typcal case.. 557 ULARGE_INTEGER info = {{0,0}};
562 info.LowPart = GetFileAttributes( PathName );
563 if (info.LowPart == INVALID_FILE_ATTRIBUTES)
568 else if (
BITS_SET( FILE_ATTRIBUTE_REPARSE_POINT, info.LowPart ))
570 if (
BITS_SET( FILE_ATTRIBUTE_DIRECTORY, info.LowPart ))
573 HANDLE hf = FindFirstFile( PathName, &fd );
574 if (hf != INVALID_HANDLE_VALUE)
576 info.HighPart = fd.dwReserved0;
583 #else // Naive approach, wasteful of CPU cycles.. 587 ULARGE_INTEGER info = {{0,0}};
589 if (hf != INVALID_HANDLE_VALUE) {
590 info.LowPart = fd.dwFileAttributes;
591 info.HighPart = fd.dwReserved0;
600 #define FA_REPARSE_DIR \ 601 (FILE_ATTRIBUTE_DIRECTORY| FILE_ATTRIBUTE_REPARSE_POINT) 627 bool ok =
BITS_SET( FILE_ATTRIBUTE_REPARSE_POINT, tag.LowPart );
628 if (ok) ok = (tag.HighPart == IO_REPARSE_TAG_SYMLINK);
636 if (ok) ok = (tag.HighPart == IO_REPARSE_TAG_SYMLINK);
646 if (ok) ok = (tag.HighPart == IO_REPARSE_TAG_MOUNT_POINT);
661 if (!VolNameBuf || !ccBuf)
663 VolNameBuf = volname;
664 ccBuf =
dimof(volname);
675 GetVolumeNameForVolumeMountPoint(
676 PathName, VolNameBuf, ccBuf
691 BOOL ok = (attr.LowPart & FILE_ATTRIBUTE_REPARSE_POINT);
692 if (!ok) error = ERROR_NOT_A_REPARSE_POINT;
697 ZeroMemory( &rpd,
sizeof(rpd) );
712 if (!ok && error) SetLastError( error );
719 CSTR PathName, ULONG Tag, REFGUID Guid, PVOID pData,
WORD cbData
728 BOOL ok = _CanSetReparseData( PathName );
737 cbBuf = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer[ cbData ] );
738 PREPARSE_GUID_DATA_BUFFER prdb = (PREPARSE_GUID_DATA_BUFFER)
mem_Alloc( cbBuf );
740 prdb->ReparseTag = Tag;
741 prdb->ReparseGuid = Guid;
742 prdb->ReparseDataLength = cbData;
743 memcpy( prdb->GenericReparseBuffer.DataBuffer, pData, cbData );
753 if (!ok && error) SetLastError( error );
769 if (ok) ok =
__ChkOkSetErr( !PathIsRelative( TargetName ), ERROR_INVALID_PARAMETER );
773 ok =
__ChkOkGetErr( CreateDirectory( LinkName, NULL ), &error );
776 WORD Flags = CNSF_MOUNTPOINT| CNSF_DIRECTORY;
778 if (!PrintName) PrintName = TargetName;
780 TargetName = _AbsTargetPrefixPath( TargetName );
783 LinkName, TargetName, PrintName, Flags
786 if (ok) _ShNfyDirOf( LinkName, SHCNE_MKDIR );
787 else RemoveDirectory( LinkName );
789 if (!ok && error) SetLastError( error );
812 if ( ok ) RemoveDirectory( DirName );
814 if ( ok ) _ShNfyDirOf( DirName, SHCNE_RMDIR );
816 if (!ok && error) SetLastError( error );
824 DWORD LnkAttr = GetFileAttributes( LinkName );
828 BOOL TrgRelative = PathIsRelative( TargetName );
829 if (!PrintName) PrintName = TargetName;
836 else TargetName = _AbsTargetPrefixPath( TargetName );
841 DWORD TrgAttr = GetFileAttributes( TargetName );
845 WORD Flags = CNSF_SYMLINK;
846 if (TrgRelative) Flags |= CNSF_RELATIVE;
848 BOOL ObjCreated, TrgIsDir = (TrgAttr & FILE_ATTRIBUTE_DIRECTORY);
849 LPSECURITY_ATTRIBUTES pSec = NULL;
852 ok = ObjCreated = CreateDirectory( LinkName, pSec );
853 Flags |= CNSF_DIRECTORY;
857 HANDLE hFile = CreateFile( LinkName, GENERIC_WRITE, 0, pSec, CREATE_NEW, 0, NULL );
859 if (ok) CloseHandle( hFile );
862 if (ok) ok = _CreateNameSurrogate( LinkName, TargetName, PrintName, Flags );
864 if (!ok && ObjCreated)
866 if (TrgIsDir) RemoveDirectory( LinkName );
867 else DeleteFile( LinkName );
878 #pragma warning( disable: 4996 ) 879 #if 1 // version 2 - so far, so good 881 static const WCHAR _BSLASH = L
'\\';
890 CSTR LinkName,
TSTR SubstPath, UINT cchSubst,
TSTR PrintName, UINT cchPrint,
891 PULARGE_INTEGER AttrTag
897 if (AttrTag) *AttrTag = attr;
898 if (!SubstPath || !cchSubst) SetLastError( ERROR_INVALID_PARAMETER );
899 else if (_IsNameSurrogateTag( attr.HighPart ))
910 PVOID pvBuf =
mem_Alloc( info.LowPart + cbSubst + cbPrint + 2*cbTemp );
913 PREPARSE_DATA_BUFFER prpd = (PREPARSE_DATA_BUFFER) pvBuf;
915 WSTR pwPrint = pwSubst + ccSubst;
916 WSTR pwTemp = pwPrint + ccPrint;
922 if (_GetNameSurrogates( prpd, pwSubst, pwPrint ))
926 if ((prpd->ReparseTag == IO_REPARSE_TAG_SYMLINK)
950 #if 1 // This is beset by the above dilemma.. 955 int ccXlate = MultiByteToWideChar( CP_ACP, 0, LinkName,-1, pwTemp, ccTemp );
956 WSTR pwCat = ccXlate ? pwTemp + ccXlate - 1 : pwTemp;
960 if (
BITS_SET( FILE_ATTRIBUTE_DIRECTORY, attr.LowPart )
961 && (*--pwCat == _BSLASH)) *pwCat = 0;
967 pwCat = 1 + wcsrchr( pwTemp, _BSLASH );
968 wcscpy( pwCat, pwSubst );
978 ok = PathCanonicalizeW( pwSubst, pwTemp );
979 if (ok) ccTarget = 1 + (UINT) wcslen( pwSubst );
980 else SetLastError( ERROR_INVALID_REPARSE_DATA );
984 DWORD linkAttr = GetFileAttributesW( pwSubst );
986 SetLastError( ERROR_INVALID_REPARSE_DATA );
993 ccTarget = INT( wzEnd - SubstPath + 1);
994 if (PrintName)
wcsnecpy( PrintName, pwPrint, cchPrint );
996 ccTarget = WideCharToMultiByte(
997 CP_ACP, 0, pwSubst,-1, SubstPath, cchSubst, NULL, NULL );
998 if (PrintName) WideCharToMultiByte(
999 CP_ACP, 0, pwPrint,-1, PrintName, cchPrint, NULL, NULL );
1008 CloseHandle( hLink );
1013 #else // version 1 - R&D 1015 IN
CSTR LinkName, OUT
TSTR TargetBuf, IN UINT BufLen,
1016 OPTOUT PULARGE_INTEGER AttrTag
1022 if (AttrTag) *AttrTag = attr;
1023 if (!TargetBuf || !BufLen) SetLastError( ERROR_INVALID_PARAMETER );
1027 SetLastError( ERROR_INVALID_DATA );
1028 else if (!IsReparseTagNameSurrogate( attr.HighPart ))
1029 SetLastError( ERROR_NOT_SUPPORTED );
1037 HANDLE hLink =
_OpenReparsePoint( LinkName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ );
1042 DWORD cbRd, ccTrans;
1047 if (rpdBuf && DeviceIoControl(
1050 if (!IsReparseTagMicrosoft( attr.HighPart ))
1055 PREPARSE_GUID_DATA_BUFFER pIsv = (PREPARSE_GUID_DATA_BUFFER) rpdBuf;
1056 ccTarget = pIsv->ReparseDataLength;
1057 #if 1 // Nothing known to resolve.. Probably can't do anything with it.. 1058 memcpy( TargetBuf, pIsv->GenericReparseBuffer.DataBuffer,
min( (
int)BufLen, ccTarget ));
1061 ccTarget = -ccTarget;
1062 SetLastError( ERROR_NOT_SUPPORTED );
1066 PREPARSE_DATA_BUFFER rpd = (PREPARSE_DATA_BUFFER) rpdBuf;
1067 #define _wchLen(_wcb) (_wcb / WCHAR_SIZE) 1068 #define _prnStr(_rps) (_rps.PathBuffer + _wchLen(_rps.PrintNameOffset)) 1069 static const WCHAR _BSLASH = L
'\\';
1073 PWSTR pwTarget = PWSTR( rpdBuf ) + _wchLen( bufSize ) - 512;
1074 PWSTR pwComposite = pwTarget - 1024;
1075 IF_DEBUG( PWSTR pwRelative = pwComposite - 512; )
1078 switch( attr.HighPart )
1082 SetLastError( ERROR_NOINTERFACE );
1085 case IO_REPARSE_TAG_MOUNT_POINT:
1086 pwPrint = _prnStr( rpd-> MountPointReparseBuffer );
1087 ccTarget = 1 + _wchLen( rpd-> MountPointReparseBuffer.PrintNameLength );
1088 wcsncpyz( pwTarget, pwPrint, ccTarget );
1091 case IO_REPARSE_TAG_SYMLINK:
1094 pwPrint = _prnStr( rpd-> SymbolicLinkReparseBuffer );
1095 ccTarget = 1 + _wchLen( rpd-> SymbolicLinkReparseBuffer.PrintNameLength );
1096 wcsncpyz( pwTarget, pwPrint, ccTarget );
1099 WCHAR _wzSubst[ MAX_PATH ], _wzPrint[ MAX_PATH ];
1100 memset( _wzSubst, 0,
sizeof(_wzSubst) );
1101 memset( _wzPrint, 0,
sizeof(_wzPrint) );
1103 &rpd->SymbolicLinkReparseBuffer.PathBuffer[ rpd->SymbolicLinkReparseBuffer.SubstituteNameOffset /
WCHAR_SIZE ],
1104 (rpd->SymbolicLinkReparseBuffer.SubstituteNameLength /
WCHAR_SIZE ) + 1
1107 &rpd->SymbolicLinkReparseBuffer.PathBuffer[ rpd->SymbolicLinkReparseBuffer.PrintNameOffset /
WCHAR_SIZE ],
1108 (rpd->SymbolicLinkReparseBuffer.PrintNameLength /
WCHAR_SIZE) + 1
1119 PWSTR pwCat =
wcsecpy( pwComposite, LinkName );
1121 PWSTR pwCat = pwComposite - 1
1122 + MultiByteToWideChar( CP_ACP, 0, LinkName,-1, pwComposite,1024 );
1129 if (
BITS_SET( FILE_ATTRIBUTE_DIRECTORY, attr.LowPart )
1130 && (*--pwCat == _BSLASH)) *pwCat = 0;
1132 pwCat = 1 + wcsrchr( pwComposite, _BSLASH );
1133 wcscpy( pwCat, pwTarget );
1134 IF_DEBUG( wcscpy( pwRelative, pwTarget ); )
1136 if (PathCanonicalizeW( pwTarget, pwComposite ))
1137 ccTarget = 1 + (UINT) wcslen( pwTarget );
1138 else ccTarget = -ccTarget;
1144 if ((
int)BufLen < ccTarget)
1146 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1147 ccTarget = -ccTarget;
1152 wcsncpyz( TargetBuf, pwTarget, BufLen );
1154 ccTrans = WideCharToMultiByte( CP_ACP, 0, pwTarget,-1, TargetBuf, BufLen, NULL, NULL );
1155 if (!ccTrans) ccTarget = -ccTarget;
1160 DWORD trgAttr = GetFileAttributes( TargetBuf );
1164 SetLastError( ERROR_INVALID_REPARSE_DATA );
1197 TRACE(
DP_DEBUG,
_F(
"Tag=0x%08X: '%s', Target unknown.\n"), attr.HighPart, LinkName );
1205 CloseHandle( hLink );
1212 #pragma warning( default: 4996 )
bool IsVolumeMountPoint(CSTR PathName, TSTR VolNameBuf, UINT ccBuf)
bool RemoveReparseData(CSTR PathName)
HANDLE CheckHandle(HANDLE Hnd)
#define IsReparseTagValid(_tag)
INT GetReparseTarget(CSTR LinkName, TSTR SubstPath, UINT cchSubst, TSTR PrintName, UINT cchPrint, PULARGE_INTEGER AttrTag)
CSTR WithoutBackslash(CSTR PathName)
CSTR WithBackslash(CSTR PathName)
bool DeleteJunctionDir(CSTR DirName)
#define IO_REPARSE_TAG_IIS_CACHE
void * mem_Alloc(size_t Bytes)
#define FILE_WRITE_ATTRIB_EA
ULARGE_INTEGER GetAttributeAndReparseTag(CSTR PathName)
#define MAX_REPARSE_BUFFER
void __cdecl DPrint(int Level, CSTR Fmt,...)
CSTR DoneDirectory(CSTR prevDir)
wchar_t *__fastcall wcsncpyz(register wchar_t *Dst, register const wchar_t *Src, size_t Count)
bool IsSymLinkDir(CSTR PathName)
bool _SetReparseData(HANDLE hObj, PREPARSE_DATA_BUFFER pRpd, OPTIN DWORD cbRpd=0)
#define FSCTL_SET_REPARSE_POINT
DWORD __GetVolumeFlags(CSTR PathName)
#define TRACE_IF(cond,...)
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
bool IsSymLink(CSTR PathName)
void * mem_Free(void *pBlk)
CSTR SysErrorMsg(DWORD Err=0, TSTR Buf=NULL, UINT Length=0)
#define FILE_READ_ATTRIB_EA
bool CreateJunctionDir(CSTR LinkName, CSTR TargetName, CSTR PrintName)
__inline bool __ChkOkSetErr(BOOL Ok, DWORD Err)
bool RestorePrivilege(HANDLE hToken, PTOKEN_PRIVILEGES pSaved)
See EnablePrivilege(()
bool __forceinline bool_cast(BOOL B52)
ULARGE_INTEGER _GetReparseData(HANDLE hObj, PVOID Buffer, DWORD cbBuffer)
#define BITS_SET(bits, x)
bool DirExist(CSTR PathName)
HANDLE _OpenReparsePoint(CSTR LinkName, ACCESS_MASK Access, DWORD Share)
wchar_t *__fastcall wcsnecpy(register wchar_t *Dst, register const wchar_t *Src, size_t N)
bool _CanReparse(CSTR PathName)
bool IsJunctionDir(CSTR PathName)
Debug and error handling support.
#define SYMLINK_FLAG_RELATIVE
__inline bool __ChkOkGetErr(BOOL Ok, PDWORD pErr)
#define REPARSE_DATA_BUFFER_HEADER_SIZE
wchar_t *__fastcall wcsecpy(register wchar_t *Dst, register const wchar_t *Src)
#define FSCTL_GET_REPARSE_POINT
CSTR __ChangeToDirOf(CSTR PathName)
bool __EnableProcPrivilege(IN CSTR Privilege, OUT LUID_AND_ATTRIBUTES *pPrv, OUT HANDLE *pToken)
bool SetCustomReparseData(CSTR PathName, ULONG Tag, REFGUID Guid, PVOID pData, WORD cbData)
#define FSCTL_DELETE_REPARSE_POINT
bool CreateSymLink(CSTR LinkName, CSTR TargetName, CSTR PrintName)
WCSTR SkipPathPrefixW(WCSTR PathName)