vbox的更動 47535 路徑 trunk/src/VBox/Runtime/r3/nt
- 時間撮記:
- 2013-8-5 上午01:54:25 (11 年 以前)
- 位置:
- trunk/src/VBox/Runtime/r3/nt
- 檔案:
-
- 修改 3 筆資料
- 複製 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp
r47534 r47535 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Directory Enumeration, Windows.3 * IPRT - Directory Enumeration, Native NT. 4 4 */ 5 5 … … 30 30 *******************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_DIR 32 #include <Windows.h>32 #include "internal-r3-nt.h" 33 33 34 34 #include <iprt/dir.h> … … 44 44 45 45 46 /******************************************************************************* 47 * Defined Constants And Macros * 48 *******************************************************************************/ 49 /** Whether to return a single record (TRUE) or multiple (FALSE)o. */ 50 #define RTDIR_NT_SINGLE_RECORD FALSE 51 52 /** Go hard on record chaining (has slight performance impact). */ 53 #ifdef RT_STRICT 54 # define RTDIR_NT_STRICT 55 #endif 56 57 58 /* ASSUMES FileID comes after ShortName and the structus are identical up to that point. */ 59 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, NextEntryOffset, FILE_ID_BOTH_DIR_INFORMATION, NextEntryOffset); 60 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileIndex , FILE_ID_BOTH_DIR_INFORMATION, FileIndex ); 61 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, CreationTime , FILE_ID_BOTH_DIR_INFORMATION, CreationTime ); 62 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, LastAccessTime , FILE_ID_BOTH_DIR_INFORMATION, LastAccessTime ); 63 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, LastWriteTime , FILE_ID_BOTH_DIR_INFORMATION, LastWriteTime ); 64 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ChangeTime , FILE_ID_BOTH_DIR_INFORMATION, ChangeTime ); 65 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, EndOfFile , FILE_ID_BOTH_DIR_INFORMATION, EndOfFile ); 66 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, AllocationSize , FILE_ID_BOTH_DIR_INFORMATION, AllocationSize ); 67 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileAttributes , FILE_ID_BOTH_DIR_INFORMATION, FileAttributes ); 68 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileNameLength , FILE_ID_BOTH_DIR_INFORMATION, FileNameLength ); 69 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, EaSize , FILE_ID_BOTH_DIR_INFORMATION, EaSize ); 70 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ShortNameLength, FILE_ID_BOTH_DIR_INFORMATION, ShortNameLength); 71 AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ShortName , FILE_ID_BOTH_DIR_INFORMATION, ShortName ); 72 73 74 75 size_t rtDirNativeGetStructSize(const char *pszPath) 76 { 77 NOREF(pszPath); 78 return sizeof(RTDIR); 79 } 80 81 46 82 int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf) 47 83 { 48 84 /* 49 * Setup the search expression. 50 * 51 * pszPathBuf is pointing to the return 4K return buffer for the RTPathReal() 52 * call in rtDirOpenCommon(), so all we gota do is check that we don't overflow 53 * it when adding the wildcard expression. 54 */ 55 size_t cbExpr; 56 const char *pszExpr; 57 if (pDir->enmFilter == RTDIRFILTER_WINNT) 58 { 59 pszExpr = pDir->pszFilter; 60 cbExpr = pDir->cchFilter + 1; 61 } 62 else 63 { 64 pszExpr = "*"; 65 cbExpr = sizeof("*"); 66 } 67 if (pDir->cchPath + cbExpr > RTPATH_MAX) 68 return VERR_FILENAME_TOO_LONG; 69 memcpy(pszPathBuf + pDir->cchPath, pszExpr, cbExpr); 70 71 72 /* 73 * Attempt opening the search. 74 */ 75 int rc = VINF_SUCCESS; 76 PRTUTF16 pwszName; 77 rc = RTStrToUtf16(pszPathBuf, &pwszName); 85 * Convert the filter to UTF-16. 86 */ 87 int rc; 88 pDir->pNtFilterStr = NULL; 89 if ( pDir->cchFilter > 0 90 && pDir->enmFilter == RTDIRFILTER_WINNT) 91 { 92 PRTUTF16 pwszTmp; 93 rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp); 94 if (RT_FAILURE(rc)) 95 return rc; 96 pDir->NtFilterStr.Buffer = pwszTmp; 97 pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16)); 98 pDir->pNtFilterStr = &pDir->NtFilterStr; 99 } 100 101 /* 102 * Try open the directory 103 */ 104 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 105 bool fObjDir; 106 #endif 107 rc = rtNtPathOpenDir(pszPathBuf, 108 FILE_READ_DATA | SYNCHRONIZE, 109 FILE_SHARE_READ | FILE_SHARE_WRITE, 110 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, 111 OBJ_CASE_INSENSITIVE, 112 &pDir->hDir, 113 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 114 &fObjDir 115 #else 116 NULL 117 #endif 118 ); 78 119 if (RT_SUCCESS(rc)) 79 120 { 80 pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data); 81 if (pDir->hDir != INVALID_HANDLE_VALUE) 82 pDir->fDataUnread = true; 83 else 84 { 85 DWORD dwErr = GetLastError(); 86 /* Theoretical case of an empty directory or more normal case of no matches. */ 87 if ( dwErr == ERROR_FILE_NOT_FOUND 88 || dwErr == ERROR_NO_MORE_FILES /* ???*/) 89 pDir->fDataUnread = false; 90 else 91 rc = RTErrConvertFromWin32(GetLastError()); 92 } 93 RTUtf16Free(pwszName); 94 } 95 121 /* 122 * Init data. 123 */ 124 pDir->fDataUnread = false; /* spelling it out */ 125 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 126 if (fObjDir) 127 pDir->enmInfoClass = FileMaximumInformation; /* object directory. */ 128 #endif 129 } 96 130 return rc; 97 131 } … … 114 148 * Close the handle. 115 149 */ 116 pDir->u32Magic ++;117 if (pDir->hDir != INVALID_HANDLE_VALUE)118 { 119 BOOL fRc = FindClose(pDir->hDir);120 Assert (fRc);121 pDir->hDir = INVALID_HANDLE_VALUE;150 pDir->u32Magic = ~RTDIR_MAGIC; 151 if (pDir->hDir != MY_INVALID_HANDLE_VALUE) 152 { 153 int rc = rtNtPathClose(pDir->hDir); 154 AssertRC(rc); 155 pDir->hDir = MY_INVALID_HANDLE_VALUE; 122 156 } 123 157 RTStrFree(pDir->pszName); 124 158 pDir->pszName = NULL; 159 RTUtf16Free(pDir->NtFilterStr.Buffer); 160 pDir->NtFilterStr.Buffer = NULL; 161 RTMemFree(pDir->pabBuffer); 162 pDir->pabBuffer = NULL; 125 163 RTMemFree(pDir); 126 164 … … 129 167 130 168 169 /** 170 * Checks the validity of the current record. 171 * 172 * @returns IPRT status code 173 * @param pThis The directory instance data. 174 */ 175 static int rtDirNtCheckRecord(PRTDIR pThis) 176 { 177 #ifdef RTDIR_NT_STRICT 178 # ifdef IPRT_WITH_NT_PATH_PASSTHRU 179 if (pThis->enmInfoClass != FileMaximumInformation) 180 # endif 181 { 182 uintptr_t uEndAddr; 183 if (pThis->enmInfoClass == FileIdBothDirectoryInformation) 184 uEndAddr = (uintptr_t)&pThis->uCurData.pBothId->FileName[0]; 185 else 186 uEndAddr = (uintptr_t)&pThis->uCurData.pBoth->FileName[0]; 187 AssertReturn(uEndAddr < (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE); 188 189 AssertReturn(pThis->uCurData.pBoth->FileNameLength < _64K, VERR_FILENAME_TOO_LONG); 190 AssertReturn((pThis->uCurData.pBoth->FileNameLength & 1) == 0, VERR_IO_GEN_FAILURE); 191 192 uEndAddr += pThis->uCurData.pBoth->FileNameLength; 193 AssertReturn(uEndAddr <= (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE); 194 195 AssertReturn((unsigned)pThis->uCurData.pBoth->ShortNameLength <= sizeof(pThis->uCurData.pBoth->ShortName), 196 VERR_IO_GEN_FAILURE); 197 } 198 #endif 199 200 return VINF_SUCCESS; 201 } 202 203 204 /** 205 * Advances the buffer pointer. 206 * 207 * @param pThis The directory instance data. 208 */ 209 static int rtDirNtAdvanceBuffer(PRTDIR pThis) 210 { 211 int rc; 212 213 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 214 if (pThis->enmInfoClass == FileMaximumInformation) 215 { 216 pThis->uCurData.pObjDir++; 217 pThis->fDataUnread = pThis->uCurData.pObjDir->Name.Length != 0; 218 return VINF_SUCCESS; 219 } 220 #endif 221 222 pThis->fDataUnread = false; 223 224 uint32_t const offNext = pThis->uCurData.pBoth->NextEntryOffset; 225 if (offNext == 0) 226 return VINF_SUCCESS; 227 228 #ifdef RTDIR_NT_STRICT 229 /* Make sure the next-record offset is beyond the current record. */ 230 size_t cbRec; 231 if (pThis->enmInfoClass == FileIdBothDirectoryInformation) 232 cbRec = RT_UOFFSETOF(FILE_ID_BOTH_DIR_INFORMATION, FileName); 233 else 234 cbRec = RT_UOFFSETOF(FILE_BOTH_DIR_INFORMATION, FileName); 235 cbRec += pThis->uCurData.pBoth->FileNameLength; 236 AssertReturn(offNext >= cbRec, VERR_IO_GEN_FAILURE); 237 #endif 238 pThis->uCurData.u += offNext; 239 240 rc = rtDirNtCheckRecord(pThis); 241 pThis->fDataUnread = RT_SUCCESS(rc); 242 return rc; 243 } 244 245 246 /** 247 * Fetches more data from the file system. 248 * 249 * @returns IPRT status code 250 * @param pThis The directory instance data. 251 */ 252 static int rtDirNtFetchMore(PRTDIR pThis) 253 { 254 Assert(!pThis->fDataUnread); 255 256 /* 257 * Allocate the buffer the first time around. 258 * We do this in lazy fashion as some users of RTDirOpen will not actually 259 * list any files, just open it for various reasons. 260 */ 261 bool fFirst = false; 262 if (!pThis->pabBuffer) 263 { 264 fFirst = false; 265 pThis->cbBufferAlloc = _256K; 266 pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); 267 if (!pThis->pabBuffer) 268 { 269 do 270 { 271 pThis->cbBufferAlloc /= 4; 272 pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc); 273 } while (pThis->pabBuffer == NULL && pThis->cbBufferAlloc > _4K); 274 if (!pThis->pabBuffer) 275 return VERR_NO_MEMORY; 276 } 277 } 278 279 /* 280 * Read more. 281 */ 282 NTSTATUS rcNt; 283 IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER; 284 if (pThis->enmInfoClass != (FILE_INFORMATION_CLASS)0) 285 { 286 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 287 if (pThis->enmInfoClass == FileMaximumInformation) 288 { 289 Ios.Information = 0; 290 Ios.Status = rcNt = NtQueryDirectoryObject(pThis->hDir, 291 pThis->pabBuffer, 292 pThis->cbBufferAlloc, 293 RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, 294 FALSE /*RestartScan*/, 295 &pThis->uObjDirCtx, 296 (PULONG)&Ios.Information); 297 } 298 else 299 #endif 300 rcNt = NtQueryDirectoryFile(pThis->hDir, 301 NULL /* Event */, 302 NULL /* ApcRoutine */, 303 NULL /* ApcContext */, 304 &Ios, 305 pThis->pabBuffer, 306 pThis->cbBufferAlloc, 307 pThis->enmInfoClass, 308 RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, 309 pThis->pNtFilterStr, 310 FALSE /*RestartScan */); 311 } 312 else 313 { 314 /* 315 * The first time around we have figure which info class we can use. 316 * We prefer one which gives us file IDs, but we'll settle for less. 317 */ 318 pThis->enmInfoClass = FileIdBothDirectoryInformation; 319 rcNt = NtQueryDirectoryFile(pThis->hDir, 320 NULL /* Event */, 321 NULL /* ApcRoutine */, 322 NULL /* ApcContext */, 323 &Ios, 324 pThis->pabBuffer, 325 pThis->cbBufferAlloc, 326 pThis->enmInfoClass, 327 RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, 328 pThis->pNtFilterStr, 329 FALSE /*RestartScan */); 330 if (!NT_SUCCESS(rcNt)) 331 { 332 pThis->enmInfoClass = FileBothDirectoryInformation; 333 rcNt = NtQueryDirectoryFile(pThis->hDir, 334 NULL /* Event */, 335 NULL /* ApcRoutine */, 336 NULL /* ApcContext */, 337 &Ios, 338 pThis->pabBuffer, 339 pThis->cbBufferAlloc, 340 pThis->enmInfoClass, 341 RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */, 342 pThis->pNtFilterStr, 343 FALSE /*RestartScan */); 344 } 345 } 346 if (!NT_SUCCESS(rcNt)) 347 { 348 if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES) 349 return VERR_NO_MORE_FILES; 350 return RTErrConvertFromNtStatus(rcNt); 351 } 352 Assert(Ios.Information > sizeof(*pThis->uCurData.pBoth)); 353 354 /* 355 * Set up the data members. 356 */ 357 pThis->uCurData.u = (uintptr_t)pThis->pabBuffer; 358 pThis->cbBuffer = Ios.Information; 359 360 int rc = rtDirNtCheckRecord(pThis); 361 pThis->fDataUnread = RT_SUCCESS(rc); 362 363 return rc; 364 } 365 366 367 /** 368 * Converts the name from UTF-16 to UTF-8. 369 * 370 * Fortunately, the names are relative to the directory, so we won't have to do 371 * any sweaty path style coversion. :-) 372 * 373 * @returns IPRT status code 374 * @param pThis The directory instance data. 375 * @param cbName The file name length in bytes. 376 * @param pwsName The file name, not terminated. 377 */ 378 static int rtDirNtConvertName(PRTDIR pThis, uint32_t cbName, PCRTUTF16 pwsName) 379 { 380 int rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName); 381 if (RT_SUCCESS(rc)) 382 { 383 if (!pThis->cbNameAlloc) 384 pThis->cbNameAlloc = pThis->cchName + 1; 385 } 386 else if (rc == VERR_BUFFER_OVERFLOW) 387 { 388 RTStrFree(pThis->pszName); 389 pThis->pszName = NULL; 390 pThis->cbNameAlloc = 0; 391 392 rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName); 393 if (RT_SUCCESS(rc)) 394 pThis->cbNameAlloc = pThis->cchName + 1; 395 } 396 Assert(RT_SUCCESS(rc) ? pThis->pszName != NULL : pThis->pszName == NULL); 397 return rc; 398 } 399 400 401 /** 402 * Converts the name of the current record. 403 * 404 * @returns IPRT status code. 405 * @param pThis The directory instance data. 406 */ 407 static int rtDirNtConvertCurName(PRTDIR pThis) 408 { 409 switch (pThis->enmInfoClass) 410 { 411 case FileIdBothDirectoryInformation: 412 return rtDirNtConvertName(pThis, pThis->uCurData.pBothId->FileNameLength, pThis->uCurData.pBothId->FileName); 413 case FileBothDirectoryInformation: 414 return rtDirNtConvertName(pThis, pThis->uCurData.pBoth->FileNameLength, pThis->uCurData.pBoth->FileName); 415 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 416 case FileMaximumInformation: 417 return rtDirNtConvertName(pThis, pThis->uCurData.pObjDir->Name.Length, pThis->uCurData.pObjDir->Name.Buffer); 418 #endif 419 420 default: 421 AssertFailedReturn(VERR_INTERNAL_ERROR_3); 422 } 423 } 424 425 131 426 RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry) 132 427 { 428 int rc; 429 133 430 /* 134 431 * Validate input. 135 432 */ 136 if (!pDir || pDir->u32Magic != RTDIR_MAGIC) 137 { 138 AssertMsgFailed(("Invalid pDir=%p\n", pDir)); 139 return VERR_INVALID_PARAMETER; 140 } 141 if (!pDirEntry) 142 { 143 AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry)); 144 return VERR_INVALID_PARAMETER; 145 } 433 AssertPtrReturn(pDir, VERR_INVALID_POINTER); 434 AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE); 435 AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER); 146 436 size_t cbDirEntry = sizeof(*pDirEntry); 147 437 if (pcbDirEntry) 148 438 { 149 439 cbDirEntry = *pcbDirEntry; 150 if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2])) 151 { 152 AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2]))); 153 return VERR_INVALID_PARAMETER; 154 } 440 AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRY, szName[2]), 441 ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])), 442 VERR_INVALID_PARAMETER); 155 443 } 156 444 … … 160 448 if (!pDir->fDataUnread) 161 449 { 162 RTStrFree(pDir->pszName); 163 pDir->pszName = NULL; 164 165 BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data); 166 if (!fRc) 167 { 168 int iErr = GetLastError(); 169 if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES) 170 return VERR_NO_MORE_FILES; 171 return RTErrConvertFromWin32(iErr); 172 } 450 rc = rtDirNtFetchMore(pDir); 451 if (RT_FAILURE(rc)) 452 return rc; 173 453 } 174 454 … … 176 456 * Convert the filename to UTF-8. 177 457 */ 178 if (!pDir->pszName) 179 { 180 int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName); 181 if (RT_FAILURE(rc)) 182 { 183 pDir->pszName = NULL; 184 return rc; 185 } 186 pDir->cchName = strlen(pDir->pszName); 187 } 458 rc = rtDirNtConvertCurName(pDir); 459 if (RT_FAILURE(rc)) 460 return rc; 188 461 189 462 /* … … 201 474 * Setup the returned data. 202 475 */ 203 pDir->fDataUnread = false; 204 pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */ 205 pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY 206 ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE; 207 pDirEntry->cbName = (uint16_t)cchName; 208 Assert(pDirEntry->cbName == cchName); 476 pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); 209 477 memcpy(pDirEntry->szName, pszName, cchName + 1); 210 478 211 return VINF_SUCCESS; 212 } 213 214 215 RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags) 216 { 217 /** @todo Symlinks: Find[First|Next]FileW will return info about 218 the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */ 479 pDirEntry->INodeId = pDir->enmInfoClass == FileIdBothDirectoryInformation 480 ? pDir->uCurData.pBothId->FileId.QuadPart : 0; 481 482 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 483 if (pDir->enmInfoClass != FileMaximumInformation) 484 #endif 485 { 486 switch ( pDir->uCurData.pBoth->FileAttributes 487 & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY)) 488 { 489 default: 490 AssertFailed(); 491 case 0: 492 pDirEntry->enmType = RTDIRENTRYTYPE_FILE; 493 break; 494 495 case FILE_ATTRIBUTE_DIRECTORY: 496 pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY; 497 break; 498 499 case FILE_ATTRIBUTE_REPARSE_POINT: 500 case FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY: 501 pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK; 502 break; 503 } 504 } 505 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 506 else 507 { 508 pDirEntry->enmType = RTDIRENTRYTYPE_UNKNOWN; 509 if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, 510 RT_STR_TUPLE("Directory"))) 511 pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY; 512 else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, 513 RT_STR_TUPLE("SymbolicLink"))) 514 pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK; 515 } 516 #endif 517 518 return rtDirNtAdvanceBuffer(pDir); 519 } 520 521 522 RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, 523 RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags) 524 { 525 int rc; 526 219 527 /* 220 528 * Validate input. 221 529 */ 222 if (!pDir || pDir->u32Magic != RTDIR_MAGIC) 223 { 224 AssertMsgFailed(("Invalid pDir=%p\n", pDir)); 225 return VERR_INVALID_PARAMETER; 226 } 227 if (!pDirEntry) 228 { 229 AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry)); 230 return VERR_INVALID_PARAMETER; 231 } 232 if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING 233 || enmAdditionalAttribs > RTFSOBJATTRADD_LAST) 234 { 235 AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs)); 236 return VERR_INVALID_PARAMETER; 237 } 530 AssertPtrReturn(pDir, VERR_INVALID_POINTER); 531 AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE); 532 AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER); 533 534 AssertReturn(enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST, 535 VERR_INVALID_PARAMETER); 238 536 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); 537 239 538 size_t cbDirEntry = sizeof(*pDirEntry); 240 539 if (pcbDirEntry) 241 540 { 242 541 cbDirEntry = *pcbDirEntry; 243 if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2])) 244 { 245 AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2]))); 246 return VERR_INVALID_PARAMETER; 247 } 542 AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRYEX, szName[2]), 543 ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])), 544 VERR_INVALID_PARAMETER); 248 545 } 249 546 … … 253 550 if (!pDir->fDataUnread) 254 551 { 255 RTStrFree(pDir->pszName); 256 pDir->pszName = NULL; 257 258 BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data); 259 if (!fRc) 260 { 261 int iErr = GetLastError(); 262 if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES) 263 return VERR_NO_MORE_FILES; 264 return RTErrConvertFromWin32(iErr); 265 } 552 rc = rtDirNtFetchMore(pDir); 553 if (RT_FAILURE(rc)) 554 return rc; 266 555 } 267 556 … … 269 558 * Convert the filename to UTF-8. 270 559 */ 271 if (!pDir->pszName) 272 { 273 int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName); 274 if (RT_FAILURE(rc)) 275 { 276 pDir->pszName = NULL; 277 return rc; 278 } 279 pDir->cchName = strlen(pDir->pszName); 280 } 560 rc = rtDirNtConvertCurName(pDir); 561 if (RT_FAILURE(rc)) 562 return rc; 281 563 282 564 /* … … 294 576 * Setup the returned data. 295 577 */ 296 pDir->fDataUnread = false;297 pDirEntry->cbName = (uint16_t)cchName; 298 Assert(pDirEntry->cbName == cchName);578 PFILE_BOTH_DIR_INFORMATION pBoth = pDir->uCurData.pBoth; 579 580 pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); 299 581 memcpy(pDirEntry->szName, pszName, cchName + 1); 300 if (pDir->Data.cAlternateFileName[0])301 { 302 /* copy and calc length */303 PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName; 304 PRTUTF16 pwszDst = pDirEntry->wszShortName;305 uint 32_t off = 0;306 while (pwszSrc[off] && off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U)582 memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName)); 583 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 584 if (pDir->enmInfoClass != FileMaximumInformation) 585 #endif 586 { 587 uint8_t cbShort = pBoth->ShortNameLength; 588 if (cbShort > 0) 307 589 { 308 pwszDst[off] = pwszSrc[off]; 309 off++; 590 AssertStmt(cbShort < sizeof(pDirEntry->wszShortName), cbShort = sizeof(pDirEntry->wszShortName) - 2); 591 memcpy(pDirEntry->wszShortName, pBoth->ShortName, cbShort); 592 pDirEntry->cwcShortName = cbShort / 2; 310 593 } 311 pDirEntry->cwcShortName = (uint16_t)off; 312 313 /* zero the rest */ 314 do 315 pwszDst[off++] = '\0'; 316 while (off < RT_ELEMENTS(pDirEntry->wszShortName)); 317 } 594 else 595 pDirEntry->cwcShortName = 0; 596 597 pDirEntry->Info.cbObject = pBoth->EndOfFile.QuadPart; 598 pDirEntry->Info.cbAllocated = pBoth->AllocationSize.QuadPart; 599 600 Assert(sizeof(uint64_t) == sizeof(pBoth->CreationTime)); 601 RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, pBoth->CreationTime.QuadPart); 602 RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, pBoth->LastAccessTime.QuadPart); 603 RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, pBoth->LastWriteTime.QuadPart); 604 RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, pBoth->ChangeTime.QuadPart); 605 606 pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pBoth->FileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, 607 pszName, cchName); 608 } 609 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 318 610 else 319 611 { 320 memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));321 612 pDirEntry->cwcShortName = 0; 322 } 323 324 pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32) 325 | (uint64_t)pDir->Data.nFileSizeLow; 326 pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject; 327 328 Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime)); 329 RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime); 330 RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime); 331 RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime); 332 pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime; 333 334 pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, 335 pszName, cchName); 613 pDirEntry->Info.cbObject = 0; 614 pDirEntry->Info.cbAllocated = 0; 615 RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, 0); 616 RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, 0); 617 RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, 0); 618 RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, 0); 619 620 if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, 621 RT_STR_TUPLE("Directory"))) 622 pDirEntry->Info.Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777; 623 else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, 624 RT_STR_TUPLE("SymbolicLink"))) 625 pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_REPARSE_POINT | RTFS_TYPE_SYMLINK | 0777; 626 else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length, 627 RT_STR_TUPLE("Device"))) 628 pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_DEVICE | RTFS_TYPE_DEV_CHAR | 0666; 629 else 630 pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE | 0666; 631 } 632 #endif 336 633 337 634 /* … … 342 639 case RTFSOBJATTRADD_EASIZE: 343 640 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE; 344 pDirEntry->Info.Attr.u.EASize.cb = 0; 641 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 642 if (pDir->enmInfoClass == FileMaximumInformation) 643 pDirEntry->Info.Attr.u.EASize.cb = 0; 644 else 645 #endif 646 pDirEntry->Info.Attr.u.EASize.cb = pBoth->EaSize; 345 647 break; 346 648 … … 378 680 } 379 681 380 return VINF_SUCCESS; 381 } 382 682 /* 683 * Follow links if requested. 684 */ 685 if ( (fFlags & RTPATH_F_FOLLOW_LINK) 686 && RTFS_IS_SYMLINK(fFlags)) 687 { 688 /** @todo Symlinks: Find[First|Next]FileW will return info about 689 the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */ 690 } 691 692 /* 693 * Finally advance the buffer. 694 */ 695 return rtDirNtAdvanceBuffer(pDir); 696 } 697 -
trunk/src/VBox/Runtime/r3/nt/fs-nt.cpp
r47533 r47535 226 226 227 227 228 /**229 * Internal helper for comparing a WCHAR string with a char string.230 *231 * @returns @c true if equal, @c false if not.232 * @param pwsz1 The first string.233 * @param cb1 The length of the first string, in bytes.234 * @param psz2 The second string.235 * @param cch2 The length of the second string.236 */237 static bool rtFsCompWideStrAndAscii(WCHAR const *pwsz1, size_t cch1, const char *psz2, size_t cch2)238 {239 if (cch1 != cch2 * 2)240 return false;241 while (cch2-- > 0)242 {243 unsigned ch1 = *pwsz1++;244 unsigned ch2 = (unsigned char)*psz2++;245 if (ch1 != ch2)246 return false;247 }248 return true;249 }250 251 228 252 229 RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType) … … 287 264 { 288 265 #define IS_FS(a_szName) \ 289 rtFsCompWideStrAndAscii(u.FsAttrInfo.FileSystemName, u.FsAttrInfo.FileSystemNameLength, RT_STR_TUPLE(a_szName))266 rtNtCompWideStrAndAscii(u.FsAttrInfo.FileSystemName, u.FsAttrInfo.FileSystemNameLength, RT_STR_TUPLE(a_szName)) 290 267 if (IS_FS("NTFS")) 291 268 *penmType = RTFSTYPE_NTFS; -
trunk/src/VBox/Runtime/r3/nt/internal-r3-nt.h
r47533 r47535 48 48 # include <ntifs.h> 49 49 #endif 50 #include "internal/iprt.h" 50 51 51 52 … … 53 54 * Defined Constants And Macros * 54 55 *******************************************************************************/ 56 /** Indicates that we're targetting native NT in the current source. */ 57 #define RT_USE_NATIVE_NT 1 55 58 /** Initializes a IO_STATUS_BLOCK. */ 56 59 #define MY_IO_STATUS_BLOCK_INITIALIZER { STATUS_FAILED_DRIVER_ENTRY, ~(uintptr_t)42 } 57 60 /** Similar to INVALID_HANDLE_VALUE in the Windows environment. */ 58 61 #define MY_INVALID_HANDLE_VALUE ( (HANDLE)~(uintptr_t)0 ) 62 63 #ifdef DEBUG_bird 64 /** Enables the "\\!\" NT path pass thru as well as hacks for listing NT object 65 * directories. */ 66 # define IPRT_WITH_NT_PATH_PASSTHRU 1 67 #endif 59 68 60 69 … … 65 74 ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs, 66 75 PHANDLE phHandle, PULONG_PTR puDisposition); 76 int rtNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions, 77 ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir); 67 78 int rtNtPathClose(HANDLE hHandle); 79 80 81 /** 82 * Internal helper for comparing a WCHAR string with a char string. 83 * 84 * @returns @c true if equal, @c false if not. 85 * @param pwsz1 The first string. 86 * @param cb1 The length of the first string, in bytes. 87 * @param psz2 The second string. 88 * @param cch2 The length of the second string. 89 */ 90 DECLINLINE(bool) rtNtCompWideStrAndAscii(WCHAR const *pwsz1, size_t cch1, const char *psz2, size_t cch2) 91 { 92 if (cch1 != cch2 * 2) 93 return false; 94 while (cch2-- > 0) 95 { 96 unsigned ch1 = *pwsz1++; 97 unsigned ch2 = (unsigned char)*psz2++; 98 if (ch1 != ch2) 99 return false; 100 } 101 return true; 102 } 68 103 69 104 … … 71 106 * NT APIs * 72 107 *******************************************************************************/ 108 109 RT_C_DECLS_BEGIN 73 110 74 111 #ifdef IPRT_NT_NEED_API_GROUP_1 … … 86 123 #endif 87 124 125 NTSTATUS NTAPI NtOpenDirectoryObject(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); 126 127 typedef struct _OBJECT_DIRECTORY_INFORMATION 128 { 129 UNICODE_STRING Name; 130 UNICODE_STRING TypeName; 131 } OBJECT_DIRECTORY_INFORMATION; 132 typedef OBJECT_DIRECTORY_INFORMATION *POBJECT_DIRECTORY_INFORMATION; 133 134 NTSTATUS NTAPI NtQueryDirectoryObject(HANDLE, PVOID, ULONG, BOOLEAN, BOOLEAN, PULONG, PULONG); 135 136 137 RT_C_DECLS_END 88 138 89 139 #endif -
trunk/src/VBox/Runtime/r3/nt/pathint-nt.cpp
r47533 r47535 47 47 * @param pszPath The UTF-8 path. 48 48 */ 49 static int rtNtPathToNativePassThru(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath) 50 { 51 PRTUTF16 pwszPath; 52 int rc = RTStrToUtf16(pszPath + 1, &pwszPath); 49 static int rtNtPathToNativePassThruWin(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath) 50 { 51 PRTUTF16 pwszPath = NULL; 52 size_t cwcLen; 53 int rc = RTStrToUtf16Ex(pszPath + 1, RTSTR_MAX, &pwszPath, 0, &cwcLen); 53 54 if (RT_SUCCESS(rc)) 54 55 { 55 pwszPath[0] = '\\';56 pwszPath[1] = '.';57 pwszPath[2] = '\\';58 59 size_t cwcLen = RTUtf16Len(pwszPath);60 56 if (cwcLen < _32K - 1) 61 57 { 58 pwszPath[0] = '\\'; 59 pwszPath[1] = '.'; 60 pwszPath[2] = '\\'; 61 62 62 pNtName->Buffer = pwszPath; 63 pNtName->MaximumLength = pNtName->Length = (uint16_t)((cwcLen + 0) * 2); 63 pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2); 64 *phRootDir = NULL; 65 return VINF_SUCCESS; 66 } 67 68 RTUtf16Free(pwszPath); 69 rc = VERR_FILENAME_TOO_LONG; 70 } 71 return rc; 72 } 73 74 75 /** 76 * Converts the path to UTF-16 and sets all the return values. 77 * 78 * @returns IPRT status code. 79 * @param pNtName Where to return the NT name. 80 * @param phRootDir Where to return the root handle, if applicable. 81 * @param pszPath The UTF-8 path. 82 */ 83 static int rtNtPathToNativeToUtf16(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath) 84 { 85 PRTUTF16 pwszPath = NULL; 86 size_t cwcLen; 87 int rc = RTStrToUtf16Ex(pszPath, RTSTR_MAX, &pwszPath, 0, &cwcLen); 88 if (RT_SUCCESS(rc)) 89 { 90 if (cwcLen < _32K - 1) 91 { 92 pNtName->Buffer = pwszPath; 93 pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2); 64 94 *phRootDir = NULL; 65 95 return VINF_SUCCESS; … … 100 130 if ( pszPath[2] == '?' 101 131 && RTPATH_IS_SLASH(pszPath[3])) 102 return rtNtPathToNativePassThru(pNtName, phRootDir, pszPath); 132 return rtNtPathToNativePassThruWin(pNtName, phRootDir, pszPath); 133 134 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 135 /* Special hack: The path starts with "\\\\!\\", we will skip past the bang and pass it thru. */ 136 if ( pszPath[2] == '!' 137 && RTPATH_IS_SLASH(pszPath[3])) 138 return rtNtPathToNativeToUtf16(pNtName, phRootDir, pszPath + 3); 139 #endif 103 140 104 141 if ( pszPath[2] == '.' … … 132 169 */ 133 170 memcpy(szPath, pszPrefix, cchPrefix); 134 PRTUTF16 pwszPath; 135 rc = RTStrToUtf16(szPath, &pwszPath); 136 if (RT_FAILURE(rc)) 137 return rc; 138 139 size_t cwcLen = RTUtf16Len(pwszPath); 140 if (cwcLen >= _32K - 1) 141 { 142 RTUtf16Free(pwszPath); 143 return VERR_FILENAME_TOO_LONG; 144 } 145 146 /* 147 * Success. 148 */ 149 pNtName->Buffer = pwszPath; 150 pNtName->MaximumLength = pNtName->Length = (uint16_t)((cwcLen + 0) * 2); 151 *phRootDir = NULL; 152 return VINF_SUCCESS; 171 return rtNtPathToNativeToUtf16(pNtName, phRootDir, szPath); 153 172 } 154 173 … … 227 246 228 247 /** 248 * Wrapper around NtCreateFile. 249 * 250 * @returns IPRT status code. 251 * @param pszPath The UTF-8 path. 252 * @param fDesiredAccess See NtCreateFile. 253 * @param fFileAttribs See NtCreateFile. 254 * @param fShareAccess See NtCreateFile. 255 * @param fCreateDisposition See NtCreateFile. 256 * @param fCreateOptions See NtCreateFile. 257 * @param fObjAttribs The OBJECT_ATTRIBUTES::Attributes value, see 258 * NtCreateFile and InitializeObjectAttributes. 259 * @param phHandle Where to return the handle. 260 * @param pfObjDir If not NULL, the variable pointed to will be set 261 * to @c true if we opened an object directory and 262 * @c false if we opened an directory file (normal 263 * directory). 264 */ 265 int rtNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions, 266 ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir) 267 { 268 *phHandle = MY_INVALID_HANDLE_VALUE; 269 270 HANDLE hRootDir; 271 UNICODE_STRING NtName; 272 int rc = rtNtPathToNative(&NtName, &hRootDir, pszPath); 273 if (RT_SUCCESS(rc)) 274 { 275 HANDLE hFile = MY_INVALID_HANDLE_VALUE; 276 IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER; 277 OBJECT_ATTRIBUTES ObjAttr; 278 InitializeObjectAttributes(&ObjAttr, &NtName, fObjAttribs, hRootDir, NULL); 279 280 NTSTATUS rcNt = NtCreateFile(&hFile, 281 fDesiredAccess, 282 &ObjAttr, 283 &Ios, 284 NULL /* AllocationSize*/, 285 FILE_ATTRIBUTE_NORMAL, 286 fShareAccess, 287 FILE_OPEN, 288 fCreateOptions, 289 NULL /*EaBuffer*/, 290 0 /*EaLength*/); 291 if (NT_SUCCESS(rcNt)) 292 { 293 if (pfObjDir) 294 *pfObjDir = false; 295 *phHandle = hFile; 296 rc = VINF_SUCCESS; 297 } 298 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 299 else if ( pfObjDir 300 && (rcNt == STATUS_OBJECT_NAME_INVALID || rcNt == STATUS_OBJECT_TYPE_MISMATCH) 301 && RTPATH_IS_SLASH(pszPath[0]) 302 && RTPATH_IS_SLASH(pszPath[1]) 303 && pszPath[2] == '!' 304 && RTPATH_IS_SLASH(pszPath[3])) 305 { 306 /* Strip trailing slash. */ 307 if ( NtName.Length > 2 308 && RTPATH_IS_SLASH(NtName.Buffer[(NtName.Length / 2) - 1])) 309 NtName.Length -= 2; 310 311 /* Rought conversion of the access flags. */ 312 ULONG fObjDesiredAccess = 0; 313 if (fDesiredAccess & (GENERIC_ALL | STANDARD_RIGHTS_ALL)) 314 fObjDesiredAccess = DIRECTORY_ALL_ACCESS; 315 else 316 { 317 if (fDesiredAccess & (FILE_GENERIC_WRITE | GENERIC_WRITE | STANDARD_RIGHTS_WRITE)) 318 fObjDesiredAccess |= DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_OBJECT; 319 if ( (fDesiredAccess & (FILE_LIST_DIRECTORY | FILE_GENERIC_READ | GENERIC_READ | STANDARD_RIGHTS_READ)) 320 || !fObjDesiredAccess) 321 fObjDesiredAccess |= DIRECTORY_QUERY | FILE_LIST_DIRECTORY; 322 } 323 324 rcNt = NtOpenDirectoryObject(&hFile, fObjDesiredAccess, &ObjAttr); 325 if (NT_SUCCESS(rcNt)) 326 { 327 *pfObjDir = true; 328 *phHandle = hFile; 329 rc = VINF_SUCCESS; 330 } 331 else 332 rc = RTErrConvertFromNtStatus(rcNt); 333 } 334 #endif 335 else 336 rc = RTErrConvertFromNtStatus(rcNt); 337 rtNtPathFreeNative(&NtName, &hRootDir); 338 } 339 return rc; 340 } 341 342 343 /** 229 344 * Closes an handled open by rtNtPathOpen. 230 345 *
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器