bool ModifyReparsePoint(const wchar_t *Object,const wchar_t *NewData) { bool Result=false; LPBYTE szBuff=new BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if(szBuff) { PREPARSE_DATA_BUFFER rdb=reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff); if (GetREPARSE_DATA_BUFFER(Object,rdb)) { bool FillResult=false; switch (rdb->ReparseTag) { case IO_REPARSE_TAG_MOUNT_POINT: { string strPrintName,strSubstituteName; ConvertNameToFull(NewData,strPrintName); strSubstituteName=L"\\??\\"; strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0)); FillResult=FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength()); } break; case IO_REPARSE_TAG_SYMLINK: { string strPrintName=NewData,strSubstituteName=NewData; if (IsAbsolutePath(NewData)) { strSubstituteName=L"\\??\\"; strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0)); rdb->SymbolicLinkReparseBuffer.Flags=0; } else { rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE; } FillResult=FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength()); } break; } if (FillResult) { Result=SetREPARSE_DATA_BUFFER(Object,rdb); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } delete[] szBuff; } return Result; }
DWORD WINAPI GetReparsePointInfo(const wchar_t *Object, string &strDestBuff,LPDWORD lpReparseTag) { WORD NameLength=0; LPBYTE szBuff=new BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if(szBuff) { PREPARSE_DATA_BUFFER rdb = reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff); if (GetREPARSE_DATA_BUFFER(Object,rdb)) { const wchar_t *PathBuffer; if (lpReparseTag) *lpReparseTag=rdb->ReparseTag; if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { NameLength = rdb->SymbolicLinkReparseBuffer.PrintNameLength/sizeof(wchar_t); if (NameLength) { PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t)]; } else { NameLength = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength/sizeof(wchar_t); PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(wchar_t)]; } } else { NameLength = rdb->MountPointReparseBuffer.PrintNameLength/sizeof(wchar_t); if (NameLength) { PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[rdb->MountPointReparseBuffer.PrintNameOffset/sizeof(wchar_t)]; } else { NameLength = rdb->MountPointReparseBuffer.SubstituteNameLength/sizeof(wchar_t); PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[rdb->MountPointReparseBuffer.SubstituteNameOffset/sizeof(wchar_t)]; } } wchar_t *lpwszDestBuff=strDestBuff.GetBuffer(NameLength+1); wcsncpy(lpwszDestBuff,PathBuffer,NameLength); strDestBuff.ReleaseBuffer(NameLength); } delete[] szBuff; } return NameLength; }
bool DeleteReparsePoint(const string& Object) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!GetREPARSE_DATA_BUFFER(Object, rdb.get())) return false; const os::fs::file fObject(Object, GetDesiredAccessForReparsePointChange(), 0, nullptr, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT); if (!fObject) return false; DWORD dwBytes; REPARSE_GUID_DATA_BUFFER rgdb{rdb->ReparseTag}; return fObject.IoControl(FSCTL_DELETE_REPARSE_POINT,&rgdb,REPARSE_GUID_DATA_BUFFER_HEADER_SIZE,nullptr,0,&dwBytes); }
bool ModifyReparsePoint(const string& Object,const string& NewData) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!GetREPARSE_DATA_BUFFER(Object, rdb.get())) return false; switch (rdb->ReparseTag) { case IO_REPARSE_TAG_MOUNT_POINT: { const auto strPrintName = ConvertNameToFull(NewData); const auto strSubstituteName = KernelPath(NTPath(strPrintName)); if (!FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } } break; case IO_REPARSE_TAG_SYMLINK: { const auto& strPrintName = NewData; auto strSubstituteName = NewData; if (IsAbsolutePath(NewData)) { strSubstituteName = KernelPath(NTPath(strSubstituteName)); rdb->SymbolicLinkReparseBuffer.Flags=0; } else { rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE; } if (!FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } } break; default: return false; } return SetREPARSE_DATA_BUFFER(Object,rdb.get()); }
bool DuplicateReparsePoint(const wchar_t *Src,const wchar_t *Dst) { bool Result=false; LPBYTE szBuff=new BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if(szBuff) { PREPARSE_DATA_BUFFER rdb=reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff); if (GetREPARSE_DATA_BUFFER(Src,rdb) && SetREPARSE_DATA_BUFFER(Dst,rdb)) { Result=true; } delete[] szBuff; } return Result; }
bool GetReparsePointInfo(const string& Object, string &strDestBuff,LPDWORD ReparseTag) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!GetREPARSE_DATA_BUFFER(Object, rdb.get())) return false; if (ReparseTag) *ReparseTag=rdb->ReparseTag; const auto& Extract = [&](const auto& Buffer) { const wchar_t *PathBuffer = nullptr; auto NameLength = Buffer.PrintNameLength / sizeof(wchar_t); if (NameLength) { PathBuffer = &Buffer.PathBuffer[Buffer.PrintNameOffset / sizeof(wchar_t)]; } else { NameLength = Buffer.SubstituteNameLength / sizeof(wchar_t); PathBuffer = &Buffer.PathBuffer[Buffer.SubstituteNameOffset / sizeof(wchar_t)]; } if (!NameLength) return false; strDestBuff.assign(PathBuffer, NameLength); return true; }; switch (rdb->ReparseTag) { case IO_REPARSE_TAG_SYMLINK: return Extract(rdb->SymbolicLinkReparseBuffer); case IO_REPARSE_TAG_MOUNT_POINT: return Extract(rdb->MountPointReparseBuffer); default: return false; } }
bool DeleteReparsePoint(const string& Object) { bool Result=false; LPBYTE Buff=new BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if(Buff) { PREPARSE_DATA_BUFFER rdb = reinterpret_cast<PREPARSE_DATA_BUFFER>(Buff); if (GetREPARSE_DATA_BUFFER(Object,rdb)) { File fObject; if (fObject.Open(Object, FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT)) { DWORD dwBytes; REPARSE_GUID_DATA_BUFFER rgdb = {rdb->ReparseTag}; Result=fObject.IoControl(FSCTL_DELETE_REPARSE_POINT,&rgdb,REPARSE_GUID_DATA_BUFFER_HEADER_SIZE,nullptr,0,&dwBytes); fObject.Close(); } } } return Result; }
bool DuplicateReparsePoint(const string& Src,const string& Dst) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); return GetREPARSE_DATA_BUFFER(Src, rdb.get()) && SetREPARSE_DATA_BUFFER(Dst, rdb.get()); }