Reactos
at master 464 lines 17 kB view raw
1/* 2 * PROJECT: ReactOS api tests 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: Tests for GetFinalPathNameByHandleW 5 * COPYRIGHT: Copyright 2025 Timo Kreuzer <timo.kreuzer@reactos.org> 6 */ 7 8#include "precomp.h" 9#include <lm.h> 10#include <ndk/obfuncs.h> 11#include <ndk/iofuncs.h> 12 13typedef 14DWORD 15WINAPI 16FN_GetFinalPathNameByHandleW( 17 _In_ HANDLE hFile, 18 _Out_writes_(cchFilePath) LPWSTR lpszFilePath, 19 _In_ DWORD cchFilePath, 20 _In_ DWORD dwFlags); 21FN_GetFinalPathNameByHandleW* pGetFinalPathNameByHandleW = NULL; 22 23#define VOLUME_NAME_DOS 0x0 24#define VOLUME_NAME_GUID 0x1 25#define VOLUME_NAME_NT 0x2 26#define VOLUME_NAME_NONE 0x4 27#define FILE_NAME_NORMALIZED 0x0 28#define FILE_NAME_OPENED 0x8 29 30static void Test_File(void) 31{ 32 WCHAR FilePath[MAX_PATH]; 33 WCHAR Buffer[MAX_PATH]; 34 WCHAR VolumeBuffer[4]; 35 PWSTR VolumeRelativePath; 36 WCHAR ExpectedString[MAX_PATH]; 37 DWORD Result; 38 SIZE_T ExpectedStringLength; 39 HANDLE hFile; 40 BOOL Success; 41 42 /* Get the full path name of the current executable */ 43 Result = GetModuleFileNameW(NULL, FilePath, ARRAYSIZE(FilePath)); 44 ok(Result != 0, "GetModuleFileNameW failed: %ld\n", GetLastError()); 45 if (Result == 0) 46 { 47 skip("GetModuleFileNameW failed\n"); 48 return; 49 } 50 51 /* Open the executable file */ 52 hFile = CreateFileW(FilePath, 53 GENERIC_READ, 54 FILE_SHARE_READ | FILE_SHARE_WRITE, 55 NULL, 56 OPEN_EXISTING, 57 FILE_ATTRIBUTE_NORMAL, 58 NULL); 59 ok(hFile != INVALID_HANDLE_VALUE, "File '%S': Opening failed\n", FilePath); 60 if (hFile == INVALID_HANDLE_VALUE) 61 { 62 skip("File '%S': Opening failed\n", FilePath); 63 return; 64 } 65 66 /* Expected string for VOLUME_NAME_DOS: 67 L"\\\\?\\C:\\ReactOS\\bin\\kernel32_apitest.exe" */ 68 wcscpy(ExpectedString, L"\\\\?\\"); 69 wcscat(ExpectedString, FilePath); 70 ExpectedStringLength = wcslen(ExpectedString); 71 72 SetLastError(0xdeadbeef); 73 StartSeh() 74 Result = pGetFinalPathNameByHandleW(hFile, NULL, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); 75 EndSeh(STATUS_ACCESS_VIOLATION) 76 77 SetLastError(0xdeadbeef); 78 memset(Buffer, 0xCC, sizeof(Buffer)); 79 Result = pGetFinalPathNameByHandleW(hFile, Buffer, 0, VOLUME_NAME_DOS); 80 ok_eq_ulong(Result, ExpectedStringLength + 1); 81 ok_eq_wchar(Buffer[0], 0xCCCC); 82 ok_err(ERROR_NOT_ENOUGH_MEMORY); 83 84 SetLastError(0xdeadbeef); 85 memset(Buffer, 0xCC, sizeof(Buffer)); 86 Result = pGetFinalPathNameByHandleW(hFile, Buffer, 9, VOLUME_NAME_DOS); 87 ok_eq_ulong(Result, ExpectedStringLength + 1); 88 ok_eq_wchar(Buffer[0], 0xCCCC); 89 ok_err(ERROR_NOT_ENOUGH_MEMORY); 90 91 SetLastError(0xdeadbeef); 92 memset(Buffer, 0xCC, sizeof(Buffer)); 93 Result = pGetFinalPathNameByHandleW(hFile, NULL, 0, VOLUME_NAME_DOS); 94 ok_eq_ulong(Result, ExpectedStringLength + 1); 95 ok_err(ERROR_NOT_ENOUGH_MEMORY); 96 97 SetLastError(0xdeadbeef); 98 memset(Buffer, 0xCC, sizeof(Buffer)); 99 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), 0x1000); 100 ok_eq_ulong(Result, ExpectedStringLength); 101 ok_eq_wstr(Buffer, ExpectedString); 102 ok_err(0); 103 104 SetLastError(0xdeadbeef); 105 memset(Buffer, 0xCC, sizeof(Buffer)); 106 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), 7); 107 ok_eq_ulong(Result, 0ul); 108 ok_eq_wchar(Buffer[0], 0xCCCC); 109 ok_err(ERROR_INVALID_PARAMETER); 110 111 SetLastError(0xdeadbeef); 112 memset(Buffer, 0xCC, sizeof(Buffer)); 113 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); 114 ok_eq_ulong(Result, ExpectedStringLength); 115 ok_eq_wstr(Buffer, ExpectedString); 116 ok_err(0); 117 118 SetLastError(0xdeadbeef); 119 memset(Buffer, 0xCC, sizeof(Buffer)); 120 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS | FILE_NAME_OPENED); 121 ok_eq_ulong(Result, ExpectedStringLength); 122 ok_eq_wstr(Buffer, ExpectedString); 123 ok_err(0); 124 125 /* Query the GUID based volume name */ 126 memcpy(VolumeBuffer, FilePath, 3 * sizeof(WCHAR)); 127 VolumeBuffer[3] = UNICODE_NULL; 128 Success = GetVolumeNameForVolumeMountPointW(VolumeBuffer, 129 ExpectedString, 130 ARRAYSIZE(ExpectedString)); 131 if (!Success) 132 { 133 skip("GetVolumeNameForVolumeMountPointW failed: %ld\n", GetLastError()); 134 return; 135 } 136 137 /* Expected string for VOLUME_NAME_GUID: 138 L"\\\\?\\Volume{cd4317d4-A62f-53d7-b36c-73f935c37280}\\ReactOS\\bin\\kernel32_apitest.exe" */ 139 VolumeRelativePath = &FilePath[wcslen(L"C:\\")]; 140 wcscat(ExpectedString, VolumeRelativePath); 141 ExpectedStringLength = wcslen(ExpectedString); 142 143 SetLastError(0xdeadbeef); 144 memset(Buffer, 0xCC, sizeof(Buffer)); 145 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID); 146 ok_eq_ulong(Result, ExpectedStringLength); 147 ok_eq_wstr(Buffer, ExpectedString); 148 ok_err(0); 149 150 SetLastError(0xdeadbeef); 151 memset(Buffer, 0xCC, sizeof(Buffer)); 152 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID | FILE_NAME_OPENED); 153 ok_eq_ulong(Result, ExpectedStringLength); 154 ok_eq_wstr(Buffer, ExpectedString); 155 ok_err(0); 156 157 /* Expected string for VOLUME_NAME_NT (2): 158 L"\\Device\\HarddiskVolume1\\ReactOS\\bin\\kernel32_apitest.exe" */ 159 ExpectedStringLength = wcslen(L"\\Device\\HarddiskVolume*\\") + 160 wcslen(VolumeRelativePath); 161 162 SetLastError(0xdeadbeef); 163 memset(Buffer, 0xCC, sizeof(Buffer)); 164 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); 165 ok_eq_ulong(Result, ExpectedStringLength); 166 ok_int(wcsncmp(Buffer, L"\\Device\\HarddiskVolume", 22), 0); 167 ok_int(wcscmp(Buffer + 24, VolumeRelativePath), 0); 168 ok_err(0xdeadbeef); 169 170 SetLastError(0xdeadbeef); 171 memset(Buffer, 0xCC, sizeof(Buffer)); 172 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT | FILE_NAME_OPENED); 173 ok_eq_ulong(Result, ExpectedStringLength); 174 ok_int(wcsncmp(Buffer, L"\\Device\\HarddiskVolume", 22), 0); 175 ok_int(wcscmp(Buffer + 24, VolumeRelativePath), 0); 176 ok_err(0xdeadbeef); 177 178 /* Expected string for VOLUME_NAME_NONE: 179 L"\\ReactOS\\bin\\kernel32_apitest.exe" */ 180 ExpectedStringLength = wcslen(VolumeRelativePath - 1); 181 182 SetLastError(0xdeadbeef); 183 memset(Buffer, 0xCC, sizeof(Buffer)); 184 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE); 185 ok_eq_ulong(Result, ExpectedStringLength); 186 ok_eq_wstr(Buffer, VolumeRelativePath - 1); 187 ok_err(0xdeadbeef); 188 189 SetLastError(0xdeadbeef); 190 memset(Buffer, 0xCC, sizeof(Buffer)); 191 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE | FILE_NAME_OPENED); 192 ok_eq_ulong(Result, ExpectedStringLength); 193 ok_eq_wstr(Buffer, VolumeRelativePath - 1); 194 ok_err(0xdeadbeef); 195 196 SetLastError(0xdeadbeef); 197 memset(Buffer, 0xCC, sizeof(Buffer)); 198 Result = pGetFinalPathNameByHandleW(hFile, Buffer, 1, VOLUME_NAME_NONE | FILE_NAME_OPENED); 199 ok_eq_ulong(Result, ExpectedStringLength + 1); 200 ok_eq_wchar(Buffer[0], 0xCCCC); 201 ok_err(ERROR_NOT_ENOUGH_MEMORY); 202 203 CloseHandle(hFile); 204} 205 206static void Test_NetworkShare(void) 207{ 208 WCHAR PathBuffer[MAX_PATH]; 209 WCHAR RemotePathBuffer[MAX_PATH]; 210 WCHAR Buffer[MAX_PATH]; 211 WCHAR ExpectedString[MAX_PATH]; 212 PWSTR FileName; 213 DWORD Result; 214 SIZE_T ExpectedStringLength; 215 DWORD dwError = 0; 216 HANDLE hFile; 217 NET_API_STATUS Status; 218 219 /* Get the full path name of the current executable */ 220 Result = GetModuleFileNameW(NULL, PathBuffer, ARRAYSIZE(PathBuffer)); 221 ok(Result != 0, "GetModuleFileNameW failed: %ld\n", GetLastError()); 222 if (Result == 0) 223 { 224 skip("GetModuleFileNameW failed: %ld\n", GetLastError()); 225 return; 226 } 227 228 /* Reduce to the containing folder */ 229 FileName = wcsrchr(PathBuffer, L'\\'); 230 *FileName = L'\0'; 231 FileName++; 232 233 // Define the share parameters 234 static WCHAR ShareName[] = L"TestShare"; // Name of the share 235 236 NetShareDel(L"", ShareName, 0); 237 238 // Set up the SHARE_INFO_2 structure 239 SHARE_INFO_2 shareInfo = { 0 }; 240 shareInfo.shi2_netname = ShareName; 241 shareInfo.shi2_type = STYPE_DISKTREE; // Disk directory share 242 shareInfo.shi2_remark = L""; 243 shareInfo.shi2_permissions = ACCESS_ALL; // Full access (adjust as needed) 244 shareInfo.shi2_max_uses = -1; // Unlimited connections 245 shareInfo.shi2_current_uses = 0; // 0 for new share 246 shareInfo.shi2_path = PathBuffer; 247 shareInfo.shi2_passwd = NULL; // No password 248 249 // Call NetShareAdd to create the share 250 Status = NetShareAdd(L"", // Empty string for local machine 251 2, // Level 2 for SHARE_INFO_2 252 (LPBYTE)&shareInfo, // Share info structure 253 &dwError); // Error code if applicable 254 if (Status != NERR_Success) 255 { 256 skip("Failed to create share. Error code: %ld\n", Status); 257 if (Status == ERROR_ACCESS_DENIED) 258 { 259 wprintf(L"Error: Access denied. Ensure you have administrative privileges.\n"); 260 } 261 262 return; 263 } 264 265 swprintf(RemotePathBuffer, L"\\\\localhost\\%s\\%s", ShareName, FileName); 266 hFile = CreateFileW(RemotePathBuffer, 267 GENERIC_READ, 268 FILE_SHARE_READ | FILE_SHARE_WRITE, 269 NULL, 270 OPEN_EXISTING, 271 FILE_ATTRIBUTE_NORMAL, 272 NULL); 273 ok(hFile != INVALID_HANDLE_VALUE, "Failed to open file '%S'. Error: %ld\n", 274 RemotePathBuffer, GetLastError()); 275 if (hFile == INVALID_HANDLE_VALUE) 276 { 277 skip("Failed to open file '%S'. Error: %ld\n", RemotePathBuffer, GetLastError()); 278 /* Clean up by deleting the share */ 279 NetShareDel(L"", ShareName, 0); 280 return; 281 } 282 283 /* Expected string for VOLUME_NAME_DOS: 284 L"\\\\?\\UNC\\localhost\\TestShare\\kernel32_apitest.exe" */ 285 swprintf(ExpectedString, L"\\\\?\\UNC\\localhost\\%s\\%s", ShareName, FileName); 286 ExpectedStringLength = wcslen(ExpectedString); 287 SetLastError(0xdeadbeef); 288 memset(Buffer, 0xCC, sizeof(Buffer)); 289 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); 290 ok_eq_ulong(Result, ExpectedStringLength); 291 ok_eq_wstr(Buffer, ExpectedString); 292 ok_err(0xdeadbeef); 293 294 SetLastError(0xdeadbeef); 295 memset(Buffer, 0xCC, sizeof(Buffer)); 296 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS | FILE_NAME_OPENED); 297 ok_eq_ulong(Result, ExpectedStringLength); 298 ok_eq_wstr(Buffer, ExpectedString); 299 ok_err(0xdeadbeef); 300 301 // VOLUME_NAME_GUID doesn't work for network shares 302 SetLastError(0xdeadbeef); 303 memset(Buffer, 0xCC, sizeof(Buffer)); 304 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID); 305 ok_eq_ulong(Result, 0ul); 306 ok_eq_wchar(Buffer[0], 0xCCCC); 307 ok_err(ERROR_PATH_NOT_FOUND); 308 309 SetLastError(0xdeadbeef); 310 memset(Buffer, 0xCC, sizeof(Buffer)); 311 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_GUID | FILE_NAME_OPENED); 312 ok_eq_ulong(Result, 0ul); 313 ok_eq_wchar(Buffer[0], 0xCCCC); 314 ok_err(ERROR_PATH_NOT_FOUND); 315 316 /* Expected string for VOLUME_NAME_NT (2): 317 L"\\Device\\Mup\\localhost\\TestShare\\kernel32_apitest.exe" */ 318 swprintf(ExpectedString, L"\\Device\\Mup\\localhost\\%s\\%s", ShareName, FileName); 319 ExpectedStringLength = wcslen(ExpectedString); 320 SetLastError(0xdeadbeef); 321 memset(Buffer, 0xCC, sizeof(Buffer)); 322 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); 323 ok_eq_ulong(Result, ExpectedStringLength); 324 ok_eq_wstr(Buffer, ExpectedString); 325 ok_err(0xdeadbeef); 326 327 SetLastError(0xdeadbeef); 328 memset(Buffer, 0xCC, sizeof(Buffer)); 329 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT | FILE_NAME_OPENED); 330 ok_eq_ulong(Result, ExpectedStringLength); 331 ok_eq_wstr(Buffer, ExpectedString); 332 ok_err(0xdeadbeef); 333 334 /* Expected string for VOLUME_NAME_NONE: 335 L"\\localhost\\TestShare\\kernel32_apitest.exe" */ 336 swprintf(ExpectedString, L"\\localhost\\%s\\%s", ShareName, FileName); 337 ExpectedStringLength = wcslen(ExpectedString); 338 SetLastError(0xdeadbeef); 339 memset(Buffer, 0xCC, sizeof(Buffer)); 340 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE); 341 ok_eq_ulong(Result, ExpectedStringLength); 342 ok_eq_wstr(Buffer, ExpectedString); 343 ok_err(0xdeadbeef); 344 345 SetLastError(0xdeadbeef); 346 memset(Buffer, 0xCC, sizeof(Buffer)); 347 Result = pGetFinalPathNameByHandleW(hFile, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NONE | FILE_NAME_OPENED); 348 ok_eq_ulong(Result, ExpectedStringLength); 349 ok_eq_wstr(Buffer, ExpectedString); 350 ok_err(0xdeadbeef); 351 352 /* Clean up */ 353 CloseHandle(hFile); 354 Status = NetShareDel(L"", ShareName, 0); 355 ok_ntstatus(Status, NERR_Success); 356} 357 358static void Test_Other(void) 359{ 360 WCHAR Buffer[MAX_PATH]; 361 DWORD Result; 362 HANDLE Handle; 363 UNICODE_STRING DeviceName; 364 OBJECT_ATTRIBUTES ObjectAttributes; 365 IO_STATUS_BLOCK IoStatusBlock; 366 NTSTATUS Status; 367 368 /* Test NULL handle */ 369 SetLastError(0xdeadbeef); 370 Result = pGetFinalPathNameByHandleW(NULL, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); 371 ok_eq_ulong(Result, 0ul); 372 ok_err(ERROR_INVALID_HANDLE); 373 374 /* Test NULL handle and NULL buffer */ 375 SetLastError(0xdeadbeef); 376 Result = pGetFinalPathNameByHandleW(NULL, NULL, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); 377 ok_eq_ulong(Result, 0ul); 378 ok_err(ERROR_INVALID_HANDLE); 379 380 /* Test NULL handle and invalid volume type */ 381 SetLastError(0xdeadbeef); 382 Result = pGetFinalPathNameByHandleW(NULL, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT | VOLUME_NAME_GUID); 383 ok_eq_ulong(Result, 0ul); 384 ok_err(ERROR_INVALID_PARAMETER); 385 386 /* Test INVALID_HANDLE_VALUE */ 387 SetLastError(0xdeadbeef); 388 memset(Buffer, 0xCC, sizeof(Buffer)); 389 Result = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_DOS); 390 ok_eq_ulong(Result, 0ul); 391 ok_eq_wchar(Buffer[0], 0xCCCC); 392 ok_err(ERROR_INVALID_HANDLE); 393 394 /* Test NtCurrentProcess */ 395 SetLastError(0xdeadbeef); 396 memset(Buffer, 0xCC, sizeof(Buffer)); 397 Result = pGetFinalPathNameByHandleW(NtCurrentProcess(), Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); 398 ok_eq_ulong(Result, 0ul); 399 ok_eq_wchar(Buffer[0], 0xCCCC); 400 ok_err(ERROR_INVALID_HANDLE); 401 402 /* Open a handle to the Beep device */ 403 RtlInitUnicodeString(&DeviceName, L"\\Device\\Beep"); 404 InitializeObjectAttributes(&ObjectAttributes, &DeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); 405 Status = NtOpenFile(&Handle, FILE_READ_ATTRIBUTES, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, 0); 406 ok_ntstatus(Status, STATUS_SUCCESS); 407 if (!NT_SUCCESS(Status)) 408 { 409 skip("Opening Beep device failed\n"); 410 } 411 else 412 { 413 SetLastError(0xdeadbeef); 414 memset(Buffer, 0xCC, sizeof(Buffer)); 415 Result = pGetFinalPathNameByHandleW(Handle, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); 416 ok_eq_ulong(Result, 0ul); 417 ok_eq_wchar(Buffer[0], 0xCCCC); 418 ok_err(ERROR_INVALID_FUNCTION); 419 NtClose(Handle); 420 } 421 422 /* Open a handle to the Null device */ 423 RtlInitUnicodeString(&DeviceName, L"\\Device\\Null"); 424 InitializeObjectAttributes(&ObjectAttributes, &DeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); 425 Status = NtOpenFile(&Handle, FILE_READ_ATTRIBUTES, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, 0); 426 ok_ntstatus(Status, STATUS_SUCCESS); 427 if (!NT_SUCCESS(Status)) 428 { 429 skip("Opening Null device failed\n"); 430 } 431 else 432 { 433 SetLastError(0xdeadbeef); 434 memset(Buffer, 0xCC, sizeof(Buffer)); 435 Result = pGetFinalPathNameByHandleW(Handle, Buffer, ARRAYSIZE(Buffer), VOLUME_NAME_NT); 436 ok_eq_ulong(Result, 0ul); 437 ok_eq_wchar(Buffer[0], 0xCCCC); 438 ok_err(ERROR_INVALID_PARAMETER); 439 NtClose(Handle); 440 } 441} 442 443 444START_TEST(GetFinalPathNameByHandle) 445{ 446 HMODULE hmodKernel32 = GetModuleHandleW(L"kernel32.dll"); 447 pGetFinalPathNameByHandleW = (FN_GetFinalPathNameByHandleW*) 448 GetProcAddress(hmodKernel32, "GetFinalPathNameByHandleW"); 449 if (pGetFinalPathNameByHandleW == NULL) 450 { 451 hmodKernel32 = GetModuleHandleW(L"kernel32_vista.dll"); 452 pGetFinalPathNameByHandleW = (FN_GetFinalPathNameByHandleW*) 453 GetProcAddress(hmodKernel32, "GetFinalPathNameByHandleW"); 454 if (pGetFinalPathNameByHandleW == NULL) 455 { 456 skip("GetFinalPathNameByHandleW not available\n"); 457 return; 458 } 459 } 460 461 Test_File(); 462 Test_NetworkShare(); 463 Test_Other(); 464}