您要求使用CopyFileEx
API複製目錄。它是一個符號鏈接的事實直到檢查到它是一個目錄之後纔會得到解決,這意味着您不能使用此API來複制目錄符號鏈接。
目錄符號鏈接的處理方式與文件符號鏈接略有不同 - 當您創建它們時,必須將其他參數傳遞給CreateSymbolicLink
API。
有一個微妙的暗示,以這種行爲的API文檔,它指出在:
要刪除符號鏈接,刪除文件(使用DeleteFile
或類似的API)或刪除目錄(使用RemoveDirectory
或類似的API)取決於使用什麼類型的符號鏈接。
這強烈地表明工作在文件上的API在目錄符號鏈接上不起作用。
現在至於如何複製它,我強烈希望你必須再次創建符號鏈接,這個過程是讀取符號鏈接目標,然後在目標中第二次創建鏈接;一個類似於(沒有錯誤處理可言,轉換相對鏈接絕對鏈接):
HANDLE h = CreateFile(srcFile, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
TCHAR outbuffer[2048];
DWORD written = GetFinalPathNameByHandle(h, outbuffer, 2048, 0);
CreateSymbolicLink(targetFile, outbuffer, SYMBOLIC_LINK_FLAG_DIRECTORY);
CloseHandle(h);
我們創建一個使用底層的重分析點數據事情變得更加複雜的符號鏈接。如果你沒有ntifs.h
做,那麼你需要定義微軟重新分析點的數據結構(從the MSDN page for REPARSE_DATA_STRUCTURE複製):
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
我們改變常規:
HANDLE h = CreateFile(srcFile, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
if (h != INVALID_HANDLE_VALUE) {
char tmpBuffer[32 * 1024];
REPARSE_DATA_BUFFER *repBuffer = reinterpret_cast<REPARSE_DATA_BUFFER *>(tmpBuffer);
DWORD retBytes;
if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, 0, 0, (void *)tmpBuffer,
sizeof tmpBuffer, &retBytes, 0)) {
if (repBuffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
wchar_t dest[2048];
memcpy(dest, repBuffer->SymbolicLinkReparseBuffer.PathBuffer +
repBuffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t),
repBuffer->SymbolicLinkReparseBuffer.PrintNameLength);
dest[repBuffer->SymbolicLinkReparseBuffer.PrintNameLength/sizeof(wchar_t)] = 0;
if (!CreateSymbolicLink(targetFile, dest, SYMBOLIC_LINK_FLAG_DIRECTORY)) {
// Error Handling
}
}
}
CloseHandle(h);
} else {
// Open Error Handling
}
這是顯著更復雜,但它保留其底層表單中的符號鏈接,即,如果它是相對鏈接,則創建的鏈接也將是相對鏈接。另外,如果目標不存在,鏈接仍然被創建。
這仍然不能刪除(a)管理員,或(b)將組策略編輯爲permit non-admin users to create symbolic links。
根據需要測試您是否具有讀取和寫入權限,並且該文件具有適當的所有權/模式。無論是鏈接,文件,目錄還是其他目錄,它都被認爲是用於linux/gcc計算目的的'文件'。所以先檢查基礎知識。 –
@ DavidC.Rankin:我問這是用於Windows操作系統。是的,我有適當的文件所有權。 – c00000fd