Changeset 2985 in kBuild for trunk/src/lib/nt/nthlpfs.c
- Timestamp:
- Nov 1, 2016 6:26:35 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/nt/nthlpfs.c
r2713 r2985 34 34 *******************************************************************************/ 35 35 #include "nthlp.h" 36 #include <stddef.h> 37 #include <string.h> 38 #include <wchar.h> 39 #include <errno.h> 36 40 37 41 … … 61 65 62 66 67 static int birdHasTrailingSlashW(const wchar_t *pwszPath) 68 { 69 wchar_t wc, wc2; 70 71 /* Skip leading slashes. */ 72 while ((wc = *pwszPath) == '/' || wc == '\\') 73 pwszPath++; 74 if (wc == '\0') 75 return 0; 76 77 /* Find the last char. */ 78 while ((wc2 = *++pwszPath) != '\0') 79 wc = wc2; 80 81 return wc == '/' || wc == '\\' || wc == ':'; 82 } 83 84 63 85 static int birdIsPathDirSpec(const char *pszPath) 64 86 { … … 75 97 76 98 return ch == '/' || ch == '\\' || ch == ':'; 99 } 100 101 102 static int birdIsPathDirSpecW(const wchar_t *pwszPath) 103 { 104 wchar_t wc, wc2; 105 106 /* Check for empty string. */ 107 wc = *pwszPath; 108 if (wc == '\0') 109 return 0; 110 111 /* Find the last char. */ 112 while ((wc2 = *++pwszPath) != '\0') 113 wc = wc2; 114 115 return wc == '/' || wc == '\\' || wc == ':'; 77 116 } 78 117 … … 119 158 120 159 160 int birdDosToNtPathW(const wchar_t *pwszPath, MY_UNICODE_STRING *pNtPath) 161 { 162 birdResolveImports(); 163 164 pNtPath->Length = pNtPath->MaximumLength = 0; 165 pNtPath->Buffer = NULL; 166 167 /* 168 * Convert the wide DOS path to an NT path. 169 */ 170 if (g_pfnRtlDosPathNameToNtPathName_U(pwszPath, pNtPath, NULL, FALSE)) 171 return 0; 172 return birdSetErrnoFromNt(STATUS_NO_MEMORY); 173 } 174 175 176 /** 177 * Converts UNIX slashes to DOS ones and trims trailing ones. 178 * 179 * @returns 0 180 * @param pNtPath The relative NT path to fix up. 181 */ 182 static int birdFixRelativeNtPathSlashesAndReturn0(MY_UNICODE_STRING *pNtPath) 183 { 184 size_t cwcLeft = pNtPath->Length / sizeof(wchar_t); 185 wchar_t *pwcStart = pNtPath->Buffer; 186 wchar_t *pwcHit; 187 188 /* Convert slashes. */ 189 while ((pwcHit = wmemchr(pwcStart, '/', cwcLeft)) != NULL) 190 { 191 *pwcHit = '\\'; 192 cwcLeft -= pwcHit - pwcStart; 193 pwcHit = pwcStart; 194 } 195 196 /* Strip trailing slashes (NT doesn't like them). */ 197 while ( pNtPath->Length >= sizeof(wchar_t) 198 && pNtPath->Buffer[(pNtPath->Length - sizeof(wchar_t)) / sizeof(wchar_t)] == '\\') 199 { 200 pNtPath->Length -= sizeof(wchar_t); 201 pNtPath->Buffer[pNtPath->Length / sizeof(wchar_t)] = '\0'; 202 } 203 204 /* If it was all trailing slashes we convert it to a dot path. */ 205 if ( pNtPath->Length == 0 206 && pNtPath->MaximumLength >= sizeof(wchar_t) * 2) 207 { 208 pNtPath->Length = sizeof(wchar_t); 209 pNtPath->Buffer[0] = '.'; 210 pNtPath->Buffer[1] = '\0'; 211 } 212 213 return 0; 214 } 215 216 217 /** 218 * Similar to birdDosToNtPath, but it does call RtlDosPathNameToNtPathName_U. 219 * 220 * @returns 0 on success, -1 + errno on failure. 221 * @param pszPath The relative path. 222 * @param pNtPath Where to return the NT path. Call birdFreeNtPath when done. 223 */ 224 int birdDosToRelativeNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath) 225 { 226 MY_NTSTATUS rcNt; 227 MY_ANSI_STRING Src; 228 229 birdResolveImports(); 230 231 /* 232 * Just convert to wide char. 233 */ 234 pNtPath->Length = pNtPath->MaximumLength = 0; 235 pNtPath->Buffer = NULL; 236 237 Src.Buffer = (PCHAR)pszPath; 238 Src.MaximumLength = Src.Length = (USHORT)strlen(pszPath); 239 240 rcNt = g_pfnRtlAnsiStringToUnicodeString(pNtPath, &Src, TRUE /* Allocate */); 241 if (MY_NT_SUCCESS(rcNt)) 242 return birdFixRelativeNtPathSlashesAndReturn0(pNtPath); 243 return birdSetErrnoFromNt(rcNt); 244 } 245 246 247 /** 248 * Similar to birdDosToNtPathW, but it does call RtlDosPathNameToNtPathName_U. 249 * 250 * @returns 0 on success, -1 + errno on failure. 251 * @param pwszPath The relative path. 252 * @param pNtPath Where to return the NT path. Call birdFreeNtPath when done. 253 */ 254 int birdDosToRelativeNtPathW(const wchar_t *pwszPath, MY_UNICODE_STRING *pNtPath) 255 { 256 size_t cwcPath = wcslen(pwszPath); 257 if (cwcPath < 0xfffe) 258 { 259 pNtPath->Length = (USHORT)(cwcPath * sizeof(wchar_t)); 260 pNtPath->MaximumLength = pNtPath->Length + sizeof(wchar_t); 261 pNtPath->Buffer = HeapAlloc(GetProcessHeap(), 0, pNtPath->MaximumLength); 262 if (pNtPath->Buffer) 263 { 264 memcpy(pNtPath->Buffer, pwszPath, pNtPath->MaximumLength); 265 return birdFixRelativeNtPathSlashesAndReturn0(pNtPath); 266 } 267 errno = ENOMEM; 268 } 269 else 270 errno = ENAMETOOLONG; 271 return -1; 272 } 273 274 275 /** 276 * Frees a string returned by birdDosToNtPath, birdDosToNtPathW or 277 * birdDosToRelativeNtPath. 278 * 279 * @param pNtPath The the NT path to free. 280 */ 121 281 void birdFreeNtPath(MY_UNICODE_STRING *pNtPath) 122 282 { … … 128 288 129 289 130 MY_NTSTATUS birdOpenFileUniStr( MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,290 MY_NTSTATUS birdOpenFileUniStr(HANDLE hRoot, MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 131 291 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs, 132 292 HANDLE *phFile) … … 144 304 Ios.Information = -1; 145 305 Ios.u.Status = 0; 146 MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, NULL /*hRoot*/, NULL /*pSecAttr*/);306 MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, hRoot, NULL /*pSecAttr*/); 147 307 148 308 rcNt = g_pfnNtCreateFile(phFile, … … 185 345 186 346 187 HANDLE birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,188 ULONG f CreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)347 HANDLE birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 348 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs) 189 349 { 190 350 MY_UNICODE_STRING NtPath; … … 198 358 199 359 /* 200 * C all the NT API directly.360 * Convert the path and call birdOpenFileUniStr to do the real work. 201 361 */ 202 362 if (birdDosToNtPath(pszPath, &NtPath) == 0) 203 363 { 204 364 HANDLE hFile; 205 rcNt = birdOpenFileUniStr( &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,365 rcNt = birdOpenFileUniStr(NULL /*hRoot*/, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess, 206 366 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile); 367 birdFreeNtPath(&NtPath); 368 if (MY_NT_SUCCESS(rcNt)) 369 return hFile; 370 birdSetErrnoFromNt(rcNt); 371 } 372 373 return INVALID_HANDLE_VALUE; 374 } 375 376 377 HANDLE birdOpenFileW(const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 378 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs) 379 { 380 MY_UNICODE_STRING NtPath; 381 MY_NTSTATUS rcNt; 382 383 /* 384 * Adjust inputs. 385 */ 386 if (birdIsPathDirSpecW(pwszPath)) 387 fCreateOptions |= FILE_DIRECTORY_FILE; 388 389 /* 390 * Convert the path and call birdOpenFileUniStr to do the real work. 391 */ 392 if (birdDosToNtPathW(pwszPath, &NtPath) == 0) 393 { 394 HANDLE hFile; 395 rcNt = birdOpenFileUniStr(NULL /*hRoot*/, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess, 396 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile); 397 birdFreeNtPath(&NtPath); 398 if (MY_NT_SUCCESS(rcNt)) 399 return hFile; 400 birdSetErrnoFromNt(rcNt); 401 } 402 403 return INVALID_HANDLE_VALUE; 404 } 405 406 407 HANDLE birdOpenFileEx(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 408 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs) 409 { 410 MY_UNICODE_STRING NtPath; 411 MY_NTSTATUS rcNt; 412 413 /* 414 * Adjust inputs. 415 */ 416 if (birdIsPathDirSpec(pszPath)) 417 fCreateOptions |= FILE_DIRECTORY_FILE; 418 419 /* 420 * Convert the path and call birdOpenFileUniStr to do the real work. 421 */ 422 if (hRoot == INVALID_HANDLE_VALUE) 423 hRoot = NULL; 424 if ((hRoot != NULL ? birdDosToRelativeNtPath(pszPath, &NtPath) : birdDosToNtPath(pszPath, &NtPath)) == 0) 425 { 426 HANDLE hFile; 427 rcNt = birdOpenFileUniStr(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess, 428 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile); 429 birdFreeNtPath(&NtPath); 430 if (MY_NT_SUCCESS(rcNt)) 431 return hFile; 432 birdSetErrnoFromNt(rcNt); 433 } 434 435 return INVALID_HANDLE_VALUE; 436 } 437 438 439 HANDLE birdOpenFileExW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 440 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs) 441 { 442 MY_UNICODE_STRING NtPath; 443 MY_NTSTATUS rcNt; 444 445 /* 446 * Adjust inputs. 447 */ 448 if (birdIsPathDirSpecW(pwszPath)) 449 fCreateOptions |= FILE_DIRECTORY_FILE; 450 451 /* 452 * Convert the path (could save ourselves this if pwszPath is perfect) and 453 * call birdOpenFileUniStr to do the real work. 454 */ 455 if (hRoot == INVALID_HANDLE_VALUE) 456 hRoot = NULL; 457 if ((hRoot != NULL ? birdDosToRelativeNtPathW(pwszPath, &NtPath) : birdDosToNtPathW(pwszPath, &NtPath)) == 0) 458 { 459 HANDLE hFile; 460 rcNt = birdOpenFileUniStr(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess, 461 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile); 462 birdFreeNtPath(&NtPath); 463 if (MY_NT_SUCCESS(rcNt)) 464 return hFile; 465 birdSetErrnoFromNt(rcNt); 466 } 467 468 return INVALID_HANDLE_VALUE; 469 } 470 471 472 static HANDLE birdOpenParentDirCommon(HANDLE hRoot, MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 473 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs, 474 MY_UNICODE_STRING *pNameUniStr) 475 { 476 MY_NTSTATUS rcNt; 477 478 /* 479 * Strip the path down to the directory. 480 */ 481 USHORT offName = pNtPath->Length / sizeof(WCHAR); 482 USHORT cwcName = offName; 483 WCHAR wc = 0; 484 while ( offName > 0 485 && (wc = pNtPath->Buffer[offName - 1]) != '\\' 486 && wc != '/' 487 && wc != ':') 488 offName--; 489 if ( offName > 0 490 || (hRoot != NULL && cwcName > 0)) 491 { 492 cwcName -= offName; 493 494 /* Make a copy of the file name, if requested. */ 495 rcNt = STATUS_SUCCESS; 496 if (pNameUniStr) 497 { 498 pNameUniStr->Length = cwcName * sizeof(WCHAR); 499 pNameUniStr->MaximumLength = pNameUniStr->Length + sizeof(WCHAR); 500 pNameUniStr->Buffer = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, pNameUniStr->MaximumLength); 501 if (pNameUniStr->Buffer) 502 { 503 memcpy(pNameUniStr->Buffer, &pNtPath->Buffer[offName], pNameUniStr->Length); 504 pNameUniStr->Buffer[cwcName] = '\0'; 505 } 506 else 507 rcNt = STATUS_NO_MEMORY; 508 } 509 510 /* Chop, chop. */ 511 // Bad idea, breaks \\?\c:\pagefile.sys. //while ( offName > 0 512 // Bad idea, breaks \\?\c:\pagefile.sys. // && ( (wc = pNtPath->Buffer[offName - 1]) == '\\' 513 // Bad idea, breaks \\?\c:\pagefile.sys. // || wc == '/')) 514 // Bad idea, breaks \\?\c:\pagefile.sys. // offName--; 515 if (offName == 0) 516 pNtPath->Buffer[offName++] = '.'; /* Hack for dir handle + dir entry name. */ 517 pNtPath->Length = offName * sizeof(WCHAR); 518 pNtPath->Buffer[offName] = '\0'; 207 519 if (MY_NT_SUCCESS(rcNt)) 208 520 { 209 birdFreeNtPath(&NtPath); 210 return hFile; 211 } 212 213 birdFreeNtPath(&NtPath); 214 birdSetErrnoFromNt(rcNt); 215 } 216 217 return INVALID_HANDLE_VALUE; 218 } 219 220 221 HANDLE birdOpenParentDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess, 222 ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs, 223 MY_UNICODE_STRING *pNameUniStr) 224 { 225 MY_UNICODE_STRING NtPath; 226 MY_NTSTATUS rcNt; 227 228 /* 229 * Adjust inputs. 230 */ 231 fCreateOptions |= FILE_DIRECTORY_FILE; 232 233 /* 234 * Convert the path and split off the filename. 235 */ 236 if (birdDosToNtPath(pszPath, &NtPath) == 0) 237 { 238 USHORT offName = NtPath.Length / sizeof(WCHAR); 239 USHORT cwcName = offName; 240 WCHAR wc = 0; 241 242 while ( offName > 0 243 && (wc = NtPath.Buffer[offName - 1]) != '\\' 244 && wc != '/' 245 && wc != ':') 246 offName--; 247 if (offName > 0) 248 { 249 cwcName -= offName; 250 251 /* Make a copy of the file name, if requested. */ 252 rcNt = STATUS_SUCCESS; 253 if (pNameUniStr) 254 { 255 pNameUniStr->Length = cwcName * sizeof(WCHAR); 256 pNameUniStr->MaximumLength = pNameUniStr->Length + sizeof(WCHAR); 257 pNameUniStr->Buffer = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, pNameUniStr->MaximumLength); 258 if (pNameUniStr->Buffer) 259 { 260 memcpy(pNameUniStr->Buffer, &NtPath.Buffer[offName],pNameUniStr->Length); 261 pNameUniStr->Buffer[cwcName] = '\0'; 262 } 263 else 264 rcNt = STATUS_NO_MEMORY; 265 } 266 267 /* Chop, chop. */ 268 // Bad idea, breaks \\?\c:\pagefile.sys. //while ( offName > 0 269 // Bad idea, breaks \\?\c:\pagefile.sys. // && ( (wc = NtPath.Buffer[offName - 1]) == '\\' 270 // Bad idea, breaks \\?\c:\pagefile.sys. // || wc == '/')) 271 // Bad idea, breaks \\?\c:\pagefile.sys. // offName--; 272 NtPath.Length = offName * sizeof(WCHAR); 273 NtPath.Buffer[offName] = '\0'; 521 /* 522 * Finally, try open the directory. 523 */ 524 HANDLE hFile; 525 fCreateOptions |= FILE_DIRECTORY_FILE; 526 rcNt = birdOpenFileUniStr(hRoot, pNtPath, fDesiredAccess, fFileAttribs, fShareAccess, 527 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile); 274 528 if (MY_NT_SUCCESS(rcNt)) 275 529 { 276 /* 277 * Finally, try open the directory. 278 */ 279 HANDLE hFile; 280 rcNt = birdOpenFileUniStr(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess, 281 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile); 282 if (MY_NT_SUCCESS(rcNt)) 283 { 284 birdFreeNtPath(&NtPath); 285 return hFile; 286 } 530 birdFreeNtPath(pNtPath); 531 return hFile; 287 532 } 288 289 if (pNameUniStr)290 birdFreeNtPath(pNameUniStr);291 533 } 292 534 293 birdFreeNtPath(&NtPath); 294 birdSetErrnoFromNt(rcNt); 295 } 296 535 if (pNameUniStr) 536 birdFreeNtPath(pNameUniStr); 537 } 538 else 539 rcNt = STATUS_INVALID_PARAMETER; 540 541 birdFreeNtPath(pNtPath); 542 birdSetErrnoFromNt(rcNt); 297 543 return INVALID_HANDLE_VALUE; 544 } 545 546 547 HANDLE birdOpenParentDir(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 548 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs, 549 MY_UNICODE_STRING *pNameUniStr) 550 { 551 /* 552 * Convert the path and join up with the UTF-16 version (it'll free NtPath). 553 */ 554 MY_UNICODE_STRING NtPath; 555 if (hRoot == INVALID_HANDLE_VALUE) 556 hRoot = NULL; 557 if ( hRoot == NULL 558 ? birdDosToNtPath(pszPath, &NtPath) == 0 559 : birdDosToRelativeNtPath(pszPath, &NtPath) == 0) 560 return birdOpenParentDirCommon(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess, 561 fCreateDisposition, fCreateOptions, fObjAttribs, pNameUniStr); 562 return INVALID_HANDLE_VALUE; 563 } 564 565 566 HANDLE birdOpenParentDirW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, 567 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs, 568 MY_UNICODE_STRING *pNameUniStr) 569 { 570 /* 571 * Convert the path and join up with the ansi version (it'll free NtPath). 572 */ 573 MY_UNICODE_STRING NtPath; 574 if (hRoot == INVALID_HANDLE_VALUE) 575 hRoot = NULL; 576 if ( hRoot == NULL 577 ? birdDosToNtPathW(pwszPath, &NtPath) == 0 578 : birdDosToRelativeNtPathW(pwszPath, &NtPath) == 0) 579 return birdOpenParentDirCommon(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess, 580 fCreateDisposition, fCreateOptions, fObjAttribs, pNameUniStr); 581 return INVALID_HANDLE_VALUE; 582 } 583 584 585 /** 586 * Returns a handle to the current working directory of the process. 587 * 588 * @returns CWD handle with FILE_TRAVERSE and SYNCHRONIZE access. May return 589 * INVALID_HANDLE_VALUE w/ errno for invalid CWD. 590 */ 591 HANDLE birdOpenCurrentDirectory(void) 592 { 593 PMY_RTL_USER_PROCESS_PARAMETERS pProcParams; 594 MY_NTSTATUS rcNt; 595 HANDLE hRet = INVALID_HANDLE_VALUE; 596 597 birdResolveImports(); 598 599 /* 600 * We'll try get this from the PEB. 601 */ 602 g_pfnRtlAcquirePebLock(); 603 pProcParams = (PMY_RTL_USER_PROCESS_PARAMETERS)MY_NT_CURRENT_PEB()->ProcessParameters; 604 if (pProcParams != NULL) 605 rcNt = g_pfnNtDuplicateObject(MY_NT_CURRENT_PROCESS, pProcParams->CurrentDirectory.Handle, 606 MY_NT_CURRENT_PROCESS, &hRet, 607 FILE_TRAVERSE | SYNCHRONIZE, 608 0 /*fAttribs*/, 609 0 /*fOptions*/); 610 else 611 rcNt = STATUS_INVALID_PARAMETER; 612 g_pfnRtlReleasePebLock(); 613 if (MY_NT_SUCCESS(rcNt)) 614 return hRet; 615 616 /* 617 * Fallback goes thru birdOpenFileW. 618 */ 619 return birdOpenFileW(L".", 620 FILE_TRAVERSE | SYNCHRONIZE, 621 FILE_ATTRIBUTE_NORMAL, 622 FILE_SHARE_READ | FILE_SHARE_WRITE, 623 FILE_OPEN, 624 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, 625 OBJ_CASE_INSENSITIVE); 298 626 } 299 627
Note:
See TracChangeset
for help on using the changeset viewer.