bool CreateReparsePoint(const string& Target, const string& Object,ReparsePointTypes Type) { bool Result=false; { switch (Type) { case RP_HARDLINK: break; case RP_EXACTCOPY: Result=DuplicateReparsePoint(Target,Object); break; case RP_SYMLINK: case RP_SYMLINKFILE: case RP_SYMLINKDIR: { os::fs::file_status ObjectStatus(Object); if(Type == RP_SYMLINK) { Type = os::fs::is_directory(Target)? RP_SYMLINKDIR : RP_SYMLINKFILE; } if (imports.CreateSymbolicLinkW && !os::fs::exists(ObjectStatus)) { Result=os::fs::CreateSymbolicLink(Object,Target,Type==RP_SYMLINKDIR?SYMBOLIC_LINK_FLAG_DIRECTORY:0); } else { const auto ObjectCreated = Type==RP_SYMLINKDIR? os::fs::is_directory(ObjectStatus) || os::fs::create_directory(Object) : os::fs::is_file(ObjectStatus) || os::fs::file(Object, 0, 0, nullptr, CREATE_NEW); if (ObjectCreated) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); rdb->ReparseTag=IO_REPARSE_TAG_SYMLINK; const auto& strPrintName = Target; auto strSubstituteName = Target; if (IsAbsolutePath(Target)) { strSubstituteName = KernelPath(NTPath(strSubstituteName)); rdb->SymbolicLinkReparseBuffer.Flags=0; } else { rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE; } if (FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { Result=SetREPARSE_DATA_BUFFER(Object,rdb.get()); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } } } break; case RP_JUNCTION: case RP_VOLMOUNT: { const auto strPrintName = ConvertNameToFull(Target); auto strSubstituteName = KernelPath(NTPath(strPrintName)); block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT; if (FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { Result=SetREPARSE_DATA_BUFFER(Object,rdb.get()); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } break; } } return Result; }
bool WINAPI CreateReparsePoint(const wchar_t *Target, const wchar_t *Object,DWORD Type) { bool Result=false; if (Object && *Object && Target && *Target) { switch (Type) { case RP_EXACTCOPY: Result=DuplicateReparsePoint(Target,Object); break; case RP_SYMLINK: case RP_SYMLINKFILE: case RP_SYMLINKDIR: if(Type == RP_SYMLINK) { DWORD Attr = apiGetFileAttributes(Target); Type = ((Attr != INVALID_FILE_ATTRIBUTES) && (Attr&FILE_ATTRIBUTE_DIRECTORY)? RP_SYMLINKDIR : RP_SYMLINKFILE); } if (ifn.pfnCreateSymbolicLink) { Result=apiCreateSymbolicLink(Object,Target,Type==RP_SYMLINKDIR?SYMBOLIC_LINK_FLAG_DIRECTORY:0); } else { bool ObjectCreated=false; if (Type==RP_SYMLINKDIR) { ObjectCreated=apiCreateDirectory(Object,nullptr)!=FALSE; } else { File file; if(file.Open(Object,0,0,nullptr,CREATE_NEW)) { ObjectCreated=true; file.Close(); } } if (ObjectCreated) { LPBYTE szBuff=new BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if(szBuff) { PREPARSE_DATA_BUFFER rdb=reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff); rdb->ReparseTag=IO_REPARSE_TAG_SYMLINK; string strPrintName=Target,strSubstituteName=Target; if (IsAbsolutePath(Target)) { strSubstituteName=L"\\??\\"; strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0)); rdb->SymbolicLinkReparseBuffer.Flags=0; } else { rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE; } if (FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength())) { Result=SetREPARSE_DATA_BUFFER(Object,rdb); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } delete[] szBuff; } } } break; case RP_JUNCTION: case RP_VOLMOUNT: { string strPrintName,strSubstituteName; ConvertNameToFull(Target,strPrintName); strSubstituteName=L"\\??\\"; strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0)); BYTE szBuff[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; PREPARSE_DATA_BUFFER rdb=reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff); rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT; if (FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength())) { Result=SetREPARSE_DATA_BUFFER(Object,rdb); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } break; } } return Result; }