Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465/* * PROJECT: ReactOS api tests * LICENSE: MIT (https://spdx.org/licenses/MIT) * PURPOSE: Tests for GetFinalPathNameByHandleW * COPYRIGHT: Copyright 2025 Timo Kreuzer <timo.kreuzer@reactos.org> */
#include "precomp.h"#include <lm.h>#include <ndk/obfuncs.h>#include <ndk/iofuncs.h>
typedefDWORDWINAPIFN_GetFinalPathNameByHandleW( _In_ HANDLE hFile, _Out_writes_(cchFilePath) LPWSTR lpszFilePath, _In_ DWORD cchFilePath, _In_ DWORD dwFlags);FN_GetFinalPathNameByHandleW* pGetFinalPathNameByHandleW = NULL;
#define VOLUME_NAME_DOS 0x0#define VOLUME_NAME_GUID 0x1#define VOLUME_NAME_NT 0x2#define VOLUME_NAME_NONE 0x4#define FILE_NAME_NORMALIZED 0x0#define FILE_NAME_OPENED 0x8
static void Test_File(void){ WCHAR FilePath[MAX_PATH]; WCHAR Buffer[MAX_PATH]; WCHAR VolumeBuffer[4]; PWSTR VolumeRelativePath; WCHAR ExpectedString[MAX_PATH]; DWORD Result; SIZE_T ExpectedStringLength; HANDLE hFile; BOOL Success;
/* Get the full path name of the current executable */ Result = GetModuleFileNameW(NULL, FilePath, ARRAYSIZE(FilePath)); ok(Result != 0, "GetModuleFileNameW failed: %ld\n", GetLastError()); if (Result == 0) { skip("GetModuleFileNameW failed\n"); return; }
/* Open the executable file */ hFile = CreateFileW(FilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ok(hFile != INVALID_HANDLE_VALUE, "File '%S': Opening failed\n", FilePath); if (hFile == INVALID_HANDLE_VALUE) { skip("File '%S': Opening failed\n", FilePath); return; }
/* Expected string for VOLUME_NAME_DOS: L"\\\\?\\C:\\ReactOS\\bin\\kernel32_apitest.exe" */ wcscpy(ExpectedString, L"\\\\?\\"); wcscat(ExpectedString, FilePath); ExpectedStringLength = wcslen(ExpectedString);
SetLastError(0xdeadbeef); StartSeh() Result = pGetFinalPathNameByHandleW(hFile, NULL, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); EndSeh(STATUS_ACCESS_VIOLATION)
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, 0, VOLUME_NAME_DOS); ok_eq_ulong(Result, ExpectedStringLength + 1); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_NOT_ENOUGH_MEMORY);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, 9, VOLUME_NAME_DOS); ok_eq_ulong(Result, ExpectedStringLength + 1); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_NOT_ENOUGH_MEMORY);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, NULL, 0, VOLUME_NAME_DOS); ok_eq_ulong(Result, ExpectedStringLength + 1); ok_err(ERROR_NOT_ENOUGH_MEMORY);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), 0x1000); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), 7); ok_eq_ulong(Result, 0ul); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0);
/* Query the GUID based volume name */ memcpy(VolumeBuffer, FilePath, 3 * sizeof(WCHAR)); VolumeBuffer[3] = UNICODE_NULL; Success = GetVolumeNameForVolumeMountPointW(VolumeBuffer, ExpectedString, ARRAYSIZE(ExpectedString)); if (!Success) { skip("GetVolumeNameForVolumeMountPointW failed: %ld\n", GetLastError()); return; }
/* Expected string for VOLUME_NAME_GUID: L"\\\\?\\Volume{cd4317d4-A62f-53d7-b36c-73f935c37280}\\ReactOS\\bin\\kernel32_apitest.exe" */ VolumeRelativePath = &FilePath[wcslen(L"C:\\")]; wcscat(ExpectedString, VolumeRelativePath); ExpectedStringLength = wcslen(ExpectedString);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0);
/* Expected string for VOLUME_NAME_NT (2): L"\\Device\\HarddiskVolume1\\ReactOS\\bin\\kernel32_apitest.exe" */ ExpectedStringLength = wcslen(L"\\Device\\HarddiskVolume*\\") + wcslen(VolumeRelativePath);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); ok_eq_ulong(Result, ExpectedStringLength); ok_int(wcsncmp(Buffer, L"\\Device\\HarddiskVolume", 22), 0); ok_int(wcscmp(Buffer + 24, VolumeRelativePath), 0); ok_err(0xdeadbeef);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength); ok_int(wcsncmp(Buffer, L"\\Device\\HarddiskVolume", 22), 0); ok_int(wcscmp(Buffer + 24, VolumeRelativePath), 0); ok_err(0xdeadbeef);
/* Expected string for VOLUME_NAME_NONE: L"\\ReactOS\\bin\\kernel32_apitest.exe" */ ExpectedStringLength = wcslen(VolumeRelativePath - 1);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, VolumeRelativePath - 1); ok_err(0xdeadbeef);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, VolumeRelativePath - 1); ok_err(0xdeadbeef);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, 1, VOLUME_NAME_NONE | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength + 1); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_NOT_ENOUGH_MEMORY);
CloseHandle(hFile);}
static void Test_NetworkShare(void){ WCHAR PathBuffer[MAX_PATH]; WCHAR RemotePathBuffer[MAX_PATH]; WCHAR Buffer[MAX_PATH]; WCHAR ExpectedString[MAX_PATH]; PWSTR FileName; DWORD Result; SIZE_T ExpectedStringLength; DWORD dwError = 0; HANDLE hFile; NET_API_STATUS Status;
/* Get the full path name of the current executable */ Result = GetModuleFileNameW(NULL, PathBuffer, ARRAYSIZE(PathBuffer)); ok(Result != 0, "GetModuleFileNameW failed: %ld\n", GetLastError()); if (Result == 0) { skip("GetModuleFileNameW failed: %ld\n", GetLastError()); return; }
/* Reduce to the containing folder */ FileName = wcsrchr(PathBuffer, L'\\'); *FileName = L'\0'; FileName++;
// Define the share parameters static WCHAR ShareName[] = L"TestShare"; // Name of the share
NetShareDel(L"", ShareName, 0);
// Set up the SHARE_INFO_2 structure SHARE_INFO_2 shareInfo = { 0 }; shareInfo.shi2_netname = ShareName; shareInfo.shi2_type = STYPE_DISKTREE; // Disk directory share shareInfo.shi2_remark = L""; shareInfo.shi2_permissions = ACCESS_ALL; // Full access (adjust as needed) shareInfo.shi2_max_uses = -1; // Unlimited connections shareInfo.shi2_current_uses = 0; // 0 for new share shareInfo.shi2_path = PathBuffer; shareInfo.shi2_passwd = NULL; // No password
// Call NetShareAdd to create the share Status = NetShareAdd(L"", // Empty string for local machine 2, // Level 2 for SHARE_INFO_2 (LPBYTE)&shareInfo, // Share info structure &dwError); // Error code if applicable if (Status != NERR_Success) { skip("Failed to create share. Error code: %ld\n", Status); if (Status == ERROR_ACCESS_DENIED) { wprintf(L"Error: Access denied. Ensure you have administrative privileges.\n"); }
return; }
swprintf(RemotePathBuffer, L"\\\\localhost\\%s\\%s", ShareName, FileName); hFile = CreateFileW(RemotePathBuffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ok(hFile != INVALID_HANDLE_VALUE, "Failed to open file '%S'. Error: %ld\n", RemotePathBuffer, GetLastError()); if (hFile == INVALID_HANDLE_VALUE) { skip("Failed to open file '%S'. Error: %ld\n", RemotePathBuffer, GetLastError()); /* Clean up by deleting the share */ NetShareDel(L"", ShareName, 0); return; }
/* Expected string for VOLUME_NAME_DOS: L"\\\\?\\UNC\\localhost\\TestShare\\kernel32_apitest.exe" */ swprintf(ExpectedString, L"\\\\?\\UNC\\localhost\\%s\\%s", ShareName, FileName); ExpectedStringLength = wcslen(ExpectedString); SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0xdeadbeef);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0xdeadbeef);
// VOLUME_NAME_GUID doesn't work for network shares SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID); ok_eq_ulong(Result, 0ul); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_PATH_NOT_FOUND);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID | FILE_NAME_OPENED); ok_eq_ulong(Result, 0ul); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_PATH_NOT_FOUND);
/* Expected string for VOLUME_NAME_NT (2): L"\\Device\\Mup\\localhost\\TestShare\\kernel32_apitest.exe" */ swprintf(ExpectedString, L"\\Device\\Mup\\localhost\\%s\\%s", ShareName, FileName); ExpectedStringLength = wcslen(ExpectedString); SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0xdeadbeef);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0xdeadbeef);
/* Expected string for VOLUME_NAME_NONE: L"\\localhost\\TestShare\\kernel32_apitest.exe" */ swprintf(ExpectedString, L"\\localhost\\%s\\%s", ShareName, FileName); ExpectedStringLength = wcslen(ExpectedString); SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0xdeadbeef);
SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE | FILE_NAME_OPENED); ok_eq_ulong(Result, ExpectedStringLength); ok_eq_wstr(Buffer, ExpectedString); ok_err(0xdeadbeef);
/* Clean up */ CloseHandle(hFile); Status = NetShareDel(L"", ShareName, 0); ok_ntstatus(Status, NERR_Success);}
static void Test_Other(void){ WCHAR Buffer[MAX_PATH]; DWORD Result; HANDLE Handle; UNICODE_STRING DeviceName; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status;
/* Test NULL handle */ SetLastError(0xdeadbeef); Result = pGetFinalPathNameByHandleW(NULL, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); ok_eq_ulong(Result, 0ul); ok_err(ERROR_INVALID_HANDLE);
/* Test NULL handle and NULL buffer */ SetLastError(0xdeadbeef); Result = pGetFinalPathNameByHandleW(NULL, NULL, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); ok_eq_ulong(Result, 0ul); ok_err(ERROR_INVALID_HANDLE);
/* Test NULL handle and invalid volume type */ SetLastError(0xdeadbeef); Result = pGetFinalPathNameByHandleW(NULL, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT | VOLUME_NAME_GUID); ok_eq_ulong(Result, 0ul); ok_err(ERROR_INVALID_PARAMETER);
/* Test INVALID_HANDLE_VALUE */ SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); ok_eq_ulong(Result, 0ul); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_INVALID_HANDLE);
/* Test NtCurrentProcess */ SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(NtCurrentProcess(), Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); ok_eq_ulong(Result, 0ul); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_INVALID_HANDLE);
/* Open a handle to the Beep device */ RtlInitUnicodeString(&DeviceName, L"\\Device\\Beep"); InitializeObjectAttributes(&ObjectAttributes, &DeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&Handle, FILE_READ_ATTRIBUTES, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, 0); ok_ntstatus(Status, STATUS_SUCCESS); if (!NT_SUCCESS(Status)) { skip("Opening Beep device failed\n"); } else { SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(Handle, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); ok_eq_ulong(Result, 0ul); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_INVALID_FUNCTION); NtClose(Handle); }
/* Open a handle to the Null device */ RtlInitUnicodeString(&DeviceName, L"\\Device\\Null"); InitializeObjectAttributes(&ObjectAttributes, &DeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&Handle, FILE_READ_ATTRIBUTES, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, 0); ok_ntstatus(Status, STATUS_SUCCESS); if (!NT_SUCCESS(Status)) { skip("Opening Null device failed\n"); } else { SetLastError(0xdeadbeef); memset(Buffer, 0xCC, sizeof(Buffer)); Result = pGetFinalPathNameByHandleW(Handle, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); ok_eq_ulong(Result, 0ul); ok_eq_wchar(Buffer[0], 0xCCCC); ok_err(ERROR_INVALID_PARAMETER); NtClose(Handle); }}
START_TEST(GetFinalPathNameByHandle){ HMODULE hmodKernel32 = GetModuleHandleW(L"kernel32.dll"); pGetFinalPathNameByHandleW = (FN_GetFinalPathNameByHandleW*) GetProcAddress(hmodKernel32, "GetFinalPathNameByHandleW"); if (pGetFinalPathNameByHandleW == NULL) { hmodKernel32 = GetModuleHandleW(L"kernel32_vista.dll"); pGetFinalPathNameByHandleW = (FN_GetFinalPathNameByHandleW*) GetProcAddress(hmodKernel32, "GetFinalPathNameByHandleW"); if (pGetFinalPathNameByHandleW == NULL) { skip("GetFinalPathNameByHandleW not available\n"); return; } }
Test_File(); Test_NetworkShare(); Test_Other();}