Changeset 47535 in vbox for trunk/src/VBox
- Timestamp:
- Aug 5, 2013 1:54:25 AM (11 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 12 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r47534 r47535 595 595 r3/win/allocex-win.cpp \ 596 596 r3/win/dir-win.cpp \ 597 r3/win/direnum-win.cpp\597 $(if-expr defined(VBOX_WITH_NT_DIRENUM),r3/nt/direnum-r3-nt.cpp,r3/win/direnum-win.cpp) \ 598 598 r3/win/errvars-win.cpp \ 599 599 r3/win/fileio-win.cpp \ -
trunk/src/VBox/Runtime/include/internal/dir.h
r44528 r47535 84 84 /** The length of the converted filename. */ 85 85 size_t cchName; 86 /** The size of this structure. */ 87 size_t cbSelf; 86 88 87 #ifdef RT_OS_WINDOWS 89 #ifndef RTDIR_AGNOSTIC 90 # ifdef RT_OS_WINDOWS 88 91 /** Handle to the opened directory search. */ 89 92 HANDLE hDir; 93 # ifndef RT_USE_NATIVE_NT 90 94 /** Find data buffer. 91 95 * fDataUnread indicates valid data. */ 92 96 WIN32_FIND_DATAW Data; 93 94 #else /* 'POSIX': */ 97 # else 98 /** The size of the name buffer pszName points to. */ 99 size_t cbNameAlloc; 100 /** NT filter string. */ 101 UNICODE_STRING NtFilterStr; 102 /** Pointer to NtFilterStr if applicable, otherwise NULL. */ 103 PUNICODE_STRING pNtFilterStr; 104 /** The information class we're using. */ 105 FILE_INFORMATION_CLASS enmInfoClass; 106 /** Object directory context data. */ 107 ULONG uObjDirCtx; 108 /** Pointer to the current data entry in the buffer. */ 109 union 110 { 111 /** Both file names, no file ID. */ 112 PFILE_BOTH_DIR_INFORMATION pBoth; 113 /** Both file names with file ID. */ 114 PFILE_ID_BOTH_DIR_INFORMATION pBothId; 115 /** Object directory info. */ 116 POBJECT_DIRECTORY_INFORMATION pObjDir; 117 /** Unsigned view. */ 118 uintptr_t u; 119 } uCurData; 120 /** The amount of valid data in the buffer. */ 121 uint32_t cbBuffer; 122 /** The allocate buffer size. */ 123 uint32_t cbBufferAlloc; 124 /** Find data buffer containing multiple directory entries. 125 * fDataUnread indicates valid data. */ 126 uint8_t *pabBuffer; 127 # endif 128 # else /* 'POSIX': */ 95 129 /** What opendir() returned. */ 96 130 DIR *pDir; 97 /** The max size of the d_name member.98 * This includes the 0 terminator of course.*/99 size_t cbMaxName;100 131 /** Find data buffer. 101 132 * fDataUnread indicates valid data. */ 102 133 struct dirent Data; 134 # endif 103 135 #endif 104 136 } RTDIR; … … 131 163 int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf); 132 164 165 /** 166 * Returns the size of the directory structure. 167 * 168 * @returns The size in bytes. 169 * @param pszPath The path to the directory we're about to open. 170 */ 171 size_t rtDirNativeGetStructSize(const char *pszPath); 172 133 173 #endif -
trunk/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp
r47533 r47535 46 46 case STATUS_USER_APC: return VERR_INTERRUPTED; 47 47 48 case STATUS_DATATYPE_MISALIGNMENT: return VERR_INVALID_POINTER; 49 case STATUS_NO_MORE_FILES: return VERR_NO_MORE_FILES; 50 case STATUS_NO_MORE_ENTRIES: return VERR_NO_MORE_FILES; 51 48 52 case STATUS_INVALID_HANDLE: return VERR_INVALID_HANDLE; 49 53 case STATUS_INVALID_PARAMETER: return VERR_INVALID_PARAMETER; 50 54 case STATUS_INVALID_DEVICE_REQUEST: return VERR_IO_BAD_COMMAND; 51 55 case STATUS_ACCESS_DENIED: return VERR_ACCESS_DENIED; 56 case STATUS_OBJECT_TYPE_MISMATCH: return VERR_UNEXPECTED_FS_OBJ_TYPE; 52 57 case STATUS_OBJECT_NAME_INVALID: return VERR_INVALID_NAME; 53 58 case STATUS_OBJECT_NAME_NOT_FOUND: return VERR_FILE_NOT_FOUND; 54 59 case STATUS_OBJECT_PATH_INVALID: return VERR_INVALID_NAME; 55 60 case STATUS_OBJECT_PATH_NOT_FOUND: return VERR_PATH_NOT_FOUND; 61 case STATUS_BAD_NETWORK_PATH: return VERR_NET_PATH_NOT_FOUND; 62 case STATUS_NOT_A_DIRECTORY: return VERR_NOT_A_DIRECTORY; 56 63 } 57 64 -
trunk/src/VBox/Runtime/r3/dir.cpp
r46014 r47535 30 30 *******************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_DIR 32 #ifdef RT_OS_WINDOWS /* PORTME: Assumes everyone else is using dir-posix.cpp */33 # include <Windows.h>34 #else35 # include <dirent.h>36 # include <unistd.h>37 # include <limits.h>38 #endif39 40 32 #include <iprt/dir.h> 41 33 #include "internal/iprt.h" … … 50 42 #include <iprt/string.h> 51 43 #include <iprt/uni.h> 44 #define RTDIR_AGNOSTIC 52 45 #include "internal/dir.h" 53 46 #include "internal/path.h" … … 571 564 * thus the horrible ugliness here. Solaris uses d_name[1] for instance. 572 565 */ 573 #ifndef RT_OS_WINDOWS 574 long cbNameMax = pathconf(szRealPath, _PC_NAME_MAX); 575 # ifdef NAME_MAX 576 if (cbNameMax < NAME_MAX) /* This is plain paranoia, but it doesn't hurt. */ 577 cbNameMax = NAME_MAX; 578 # endif 579 # ifdef _XOPEN_NAME_MAX 580 if (cbNameMax < _XOPEN_NAME_MAX) /* Ditto. */ 581 cbNameMax = _XOPEN_NAME_MAX; 582 # endif 583 size_t cbDir = RT_OFFSETOF(RTDIR, Data.d_name[cbNameMax + 1]); 584 if (cbDir < sizeof(RTDIR)) /* Ditto. */ 585 cbDir = sizeof(RTDIR); 586 cbDir = RT_ALIGN_Z(cbDir, 8); 587 #else 588 size_t cbDir = sizeof(RTDIR); 589 #endif 566 size_t cbDir = rtDirNativeGetStructSize(szRealPath); 590 567 size_t const cbAllocated = cbDir 591 568 + cucFilter0 * sizeof(RTUNICP) 592 569 + cbFilter 593 570 + cchRealPath + 1 + 4; 594 PRTDIR pDir = (PRTDIR)RTMemAlloc (cbAllocated);571 PRTDIR pDir = (PRTDIR)RTMemAllocZ(cbAllocated); 595 572 if (!pDir) 596 573 return VERR_NO_MEMORY; … … 599 576 /* initialize it */ 600 577 pDir->u32Magic = RTDIR_MAGIC; 578 pDir->cbSelf = cbDir; 601 579 if (cbFilter) 602 580 { … … 639 617 pDir->pszName = NULL; 640 618 pDir->cchName = 0; 641 #ifndef RT_OS_WINDOWS642 pDir->cbMaxName = cbDir - RT_OFFSETOF(RTDIR, Data.d_name);643 #endif644 619 645 620 /* -
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 * -
trunk/src/VBox/Runtime/r3/posix/dir-posix.cpp
r43363 r47535 193 193 194 194 195 size_t rtDirNativeGetStructSize(const char *pszPath) 196 { 197 long cbNameMax = pathconf(pszPath, _PC_NAME_MAX); 198 # ifdef NAME_MAX 199 if (cbNameMax < NAME_MAX) /* This is plain paranoia, but it doesn't hurt. */ 200 cbNameMax = NAME_MAX; 201 # endif 202 # ifdef _XOPEN_NAME_MAX 203 if (cbNameMax < _XOPEN_NAME_MAX) /* Ditto. */ 204 cbNameMax = _XOPEN_NAME_MAX; 205 # endif 206 size_t cbDir = RT_OFFSETOF(RTDIR, Data.d_name[cbNameMax + 1]); 207 if (cbDir < sizeof(RTDIR)) /* Ditto. */ 208 cbDir = sizeof(RTDIR); 209 cbDir = RT_ALIGN_Z(cbDir, 8); 210 211 return cbDir; 212 } 213 214 195 215 int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf) 196 216 { … … 208 228 { 209 229 /* 210 * Init data .230 * Init data (allocated as all zeros). 211 231 */ 212 pDir->fDataUnread = false; 213 memset(&pDir->Data, 0, RT_OFFSETOF(RTDIR, Data.d_name)); /* not strictly necessary */ 214 memset(&pDir->Data.d_name[0], 0, pDir->cbMaxName); 232 pDir->fDataUnread = false; /* spelling it out */ 215 233 } 216 234 else -
trunk/src/VBox/Runtime/r3/win/direnum-win.cpp
r47534 r47535 44 44 45 45 46 size_t rtDirNativeGetStructSize(const char *pszPath) 47 { 48 NOREF(pszPath); 49 return sizeof(RTDIR); 50 } 51 52 46 53 int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf) 47 54 { … … 78 85 if (RT_SUCCESS(rc)) 79 86 { 80 pDir->hDir 87 pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data); 81 88 if (pDir->hDir != INVALID_HANDLE_VALUE) 82 89 pDir->fDataUnread = true; -
trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.c
r47533 r47535 5 5 6 6 /* 7 * Copyright (C) 2010-201 2Oracle Corporation7 * Copyright (C) 2010-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 38 38 typedef INT PROCESSINFOCLASS; 39 39 typedef PVOID POBJECT_ATTRIBUTES; 40 typedef PVOID PIO_APC_ROUTINE; 41 typedef PVOID PUNICODE_STRING; 40 42 41 43 … … 53 55 OUT PULONG MinimumResolution, 54 56 OUT PULONG CurrentResolution) 57 { 58 return -1; 59 } 60 61 NTSYSAPI LONG NTAPI NtQueryDirectoryFile(IN HANDLE FileHandle, 62 IN HANDLE Event OPTIONAL, 63 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 64 IN PVOID ApcContext OPTIONAL, 65 OUT PIO_STATUS_BLOCK IoStatusBlock, 66 OUT PVOID FileInformation, 67 IN ULONG Length, 68 IN FILE_INFORMATION_CLASS FileInformationClass, 69 IN BOOLEAN ReturnSingleEntry, 70 IN PUNICODE_STRING FileName OPTIONAL, 71 IN BOOLEAN RestartScan) 72 { 73 return -1; 74 } 75 76 NTSYSAPI LONG NTAPI NtQueryDirectoryObject(IN HANDLE ObjectHandle, 77 OUT PVOID Buffer, 78 IN ULONG Length, 79 IN BOOLEAN ReturnSingleEntry, 80 IN BOOLEAN RestartScan, 81 IN OUT PULONG Context, 82 OUT PULONG ReturneLength) 55 83 { 56 84 return -1; … … 132 160 } 133 161 162 NTSYSAPI NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE ObjectHandle, 163 IN ACCESS_MASK DesiredAccess, 164 IN POBJECT_ATTRIBUTES ObjectAttributes) 165 { 166 return -1; 167 } 168 134 169 NTSYSAPI NTSTATUS NTAPI NtClose(IN HANDLE Handle) 135 170 { -
trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def
r47533 r47535 29 29 RtlNtStatusToDosError 30 30 NtQueryTimerResolution 31 NtQueryDirectoryFile 31 32 NtQueryInformationFile 32 33 NtQueryInformationProcess … … 37 38 NtCreateFile 38 39 NtClose 40 NtOpenDirectoryObject -
trunk/src/VBox/Runtime/testcase/tstDir.cpp
r44528 r47535 40 40 * Iterate arguments. 41 41 */ 42 bool fLong = false;42 bool fLong = false; 43 43 bool fShortName = false; 44 bool fFiltered = false; 45 bool fQuiet = false; 44 46 for (int i = 1; i < argc; i++) 45 47 { … … 56 58 fShortName = true; 57 59 break; 60 case 'f': 61 fFiltered = true; 62 break; 63 case 'q': 64 fQuiet = true; 65 break; 58 66 default: 59 67 RTPrintf("Unknown option '%c' ignored!\n", argv[i][j]); … … 66 74 /* open */ 67 75 PRTDIR pDir; 68 int rc = RTDirOpen(&pDir, argv[i]); 76 int rc; 77 if (!fFiltered) 78 rc = RTDirOpen(&pDir, argv[i]); 79 else 80 rc = RTDirOpenFiltered(&pDir, argv[i], RTDIRFILTER_WINNT, 0); 69 81 if (RT_SUCCESS(rc)) 70 82 { … … 78 90 if (RT_FAILURE(rc)) 79 91 break; 80 switch (DirEntry.enmType)92 if (!fQuiet) 81 93 { 82 case RTDIRENTRYTYPE_UNKNOWN: RTPrintf("u"); break; 83 case RTDIRENTRYTYPE_FIFO: RTPrintf("f"); break; 84 case RTDIRENTRYTYPE_DEV_CHAR: RTPrintf("c"); break; 85 case RTDIRENTRYTYPE_DIRECTORY: RTPrintf("d"); break; 86 case RTDIRENTRYTYPE_DEV_BLOCK: RTPrintf("b"); break; 87 case RTDIRENTRYTYPE_FILE: RTPrintf("-"); break; 88 case RTDIRENTRYTYPE_SYMLINK: RTPrintf("l"); break; 89 case RTDIRENTRYTYPE_SOCKET: RTPrintf("s"); break; 90 case RTDIRENTRYTYPE_WHITEOUT: RTPrintf("w"); break; 91 default: 92 rcRet = 1; 93 RTPrintf("?"); 94 break; 94 switch (DirEntry.enmType) 95 { 96 case RTDIRENTRYTYPE_UNKNOWN: RTPrintf("u"); break; 97 case RTDIRENTRYTYPE_FIFO: RTPrintf("f"); break; 98 case RTDIRENTRYTYPE_DEV_CHAR: RTPrintf("c"); break; 99 case RTDIRENTRYTYPE_DIRECTORY: RTPrintf("d"); break; 100 case RTDIRENTRYTYPE_DEV_BLOCK: RTPrintf("b"); break; 101 case RTDIRENTRYTYPE_FILE: RTPrintf("-"); break; 102 case RTDIRENTRYTYPE_SYMLINK: RTPrintf("l"); break; 103 case RTDIRENTRYTYPE_SOCKET: RTPrintf("s"); break; 104 case RTDIRENTRYTYPE_WHITEOUT: RTPrintf("w"); break; 105 default: 106 rcRet = 1; 107 RTPrintf("?"); 108 break; 109 } 110 RTPrintf(" %#18llx %3d %s\n", (uint64_t)DirEntry.INodeId, 111 DirEntry.cbName, DirEntry.szName); 95 112 } 96 RTPrintf(" %#18llx %3d %s\n", (uint64_t)DirEntry.INodeId,97 DirEntry.cbName, DirEntry.szName);98 113 } 99 114 } … … 107 122 break; 108 123 109 RTFMODE fMode = DirEntry.Info.Attr.fMode; 110 switch (fMode & RTFS_TYPE_MASK) 124 if (!fQuiet) 111 125 { 112 case RTFS_TYPE_FIFO: RTPrintf("f"); break; 113 case RTFS_TYPE_DEV_CHAR: RTPrintf("c"); break; 114 case RTFS_TYPE_DIRECTORY: RTPrintf("d"); break; 115 case RTFS_TYPE_DEV_BLOCK: RTPrintf("b"); break; 116 case RTFS_TYPE_FILE: RTPrintf("-"); break; 117 case RTFS_TYPE_SYMLINK: RTPrintf("l"); break; 118 case RTFS_TYPE_SOCKET: RTPrintf("s"); break; 119 case RTFS_TYPE_WHITEOUT: RTPrintf("w"); break; 120 default: 121 rcRet = 1; 122 RTPrintf("?"); 123 break; 126 RTFMODE fMode = DirEntry.Info.Attr.fMode; 127 switch (fMode & RTFS_TYPE_MASK) 128 { 129 case RTFS_TYPE_FIFO: RTPrintf("f"); break; 130 case RTFS_TYPE_DEV_CHAR: RTPrintf("c"); break; 131 case RTFS_TYPE_DIRECTORY: RTPrintf("d"); break; 132 case RTFS_TYPE_DEV_BLOCK: RTPrintf("b"); break; 133 case RTFS_TYPE_FILE: RTPrintf("-"); break; 134 case RTFS_TYPE_SYMLINK: RTPrintf("l"); break; 135 case RTFS_TYPE_SOCKET: RTPrintf("s"); break; 136 case RTFS_TYPE_WHITEOUT: RTPrintf("w"); break; 137 default: 138 rcRet = 1; 139 RTPrintf("?"); 140 break; 141 } 142 /** @todo sticy bits++ */ 143 RTPrintf("%c%c%c", 144 fMode & RTFS_UNIX_IRUSR ? 'r' : '-', 145 fMode & RTFS_UNIX_IWUSR ? 'w' : '-', 146 fMode & RTFS_UNIX_IXUSR ? 'x' : '-'); 147 RTPrintf("%c%c%c", 148 fMode & RTFS_UNIX_IRGRP ? 'r' : '-', 149 fMode & RTFS_UNIX_IWGRP ? 'w' : '-', 150 fMode & RTFS_UNIX_IXGRP ? 'x' : '-'); 151 RTPrintf("%c%c%c", 152 fMode & RTFS_UNIX_IROTH ? 'r' : '-', 153 fMode & RTFS_UNIX_IWOTH ? 'w' : '-', 154 fMode & RTFS_UNIX_IXOTH ? 'x' : '-'); 155 RTPrintf(" %c%c%c%c%c%c%c%c%c%c%c%c%c%c", 156 fMode & RTFS_DOS_READONLY ? 'R' : '-', 157 fMode & RTFS_DOS_HIDDEN ? 'H' : '-', 158 fMode & RTFS_DOS_SYSTEM ? 'S' : '-', 159 fMode & RTFS_DOS_DIRECTORY ? 'D' : '-', 160 fMode & RTFS_DOS_ARCHIVED ? 'A' : '-', 161 fMode & RTFS_DOS_NT_DEVICE ? 'd' : '-', 162 fMode & RTFS_DOS_NT_NORMAL ? 'N' : '-', 163 fMode & RTFS_DOS_NT_TEMPORARY ? 'T' : '-', 164 fMode & RTFS_DOS_NT_SPARSE_FILE ? 'P' : '-', 165 fMode & RTFS_DOS_NT_REPARSE_POINT ? 'J' : '-', 166 fMode & RTFS_DOS_NT_COMPRESSED ? 'C' : '-', 167 fMode & RTFS_DOS_NT_OFFLINE ? 'O' : '-', 168 fMode & RTFS_DOS_NT_NOT_CONTENT_INDEXED ? 'I' : '-', 169 fMode & RTFS_DOS_NT_ENCRYPTED ? 'E' : '-'); 170 RTPrintf(" %d %4d %4d %10lld %10lld %#llx %#llx %#llx %#llx", 171 DirEntry.Info.Attr.u.Unix.cHardlinks, 172 DirEntry.Info.Attr.u.Unix.uid, 173 DirEntry.Info.Attr.u.Unix.gid, 174 DirEntry.Info.cbObject, 175 DirEntry.Info.cbAllocated, 176 DirEntry.Info.BirthTime, 177 DirEntry.Info.ChangeTime, 178 DirEntry.Info.ModificationTime, 179 DirEntry.Info.AccessTime); 180 if (fShortName) 181 RTPrintf(" %2d %-12ls ", DirEntry.cwcShortName, DirEntry.wszShortName); 182 RTPrintf(" %2d %s\n", DirEntry.cbName, DirEntry.szName); 124 183 } 125 /** @todo sticy bits++ */126 RTPrintf("%c%c%c",127 fMode & RTFS_UNIX_IRUSR ? 'r' : '-',128 fMode & RTFS_UNIX_IWUSR ? 'w' : '-',129 fMode & RTFS_UNIX_IXUSR ? 'x' : '-');130 RTPrintf("%c%c%c",131 fMode & RTFS_UNIX_IRGRP ? 'r' : '-',132 fMode & RTFS_UNIX_IWGRP ? 'w' : '-',133 fMode & RTFS_UNIX_IXGRP ? 'x' : '-');134 RTPrintf("%c%c%c",135 fMode & RTFS_UNIX_IROTH ? 'r' : '-',136 fMode & RTFS_UNIX_IWOTH ? 'w' : '-',137 fMode & RTFS_UNIX_IXOTH ? 'x' : '-');138 RTPrintf(" %c%c%c%c%c%c%c%c%c%c%c%c%c%c",139 fMode & RTFS_DOS_READONLY ? 'R' : '-',140 fMode & RTFS_DOS_HIDDEN ? 'H' : '-',141 fMode & RTFS_DOS_SYSTEM ? 'S' : '-',142 fMode & RTFS_DOS_DIRECTORY ? 'D' : '-',143 fMode & RTFS_DOS_ARCHIVED ? 'A' : '-',144 fMode & RTFS_DOS_NT_DEVICE ? 'd' : '-',145 fMode & RTFS_DOS_NT_NORMAL ? 'N' : '-',146 fMode & RTFS_DOS_NT_TEMPORARY ? 'T' : '-',147 fMode & RTFS_DOS_NT_SPARSE_FILE ? 'P' : '-',148 fMode & RTFS_DOS_NT_REPARSE_POINT ? 'J' : '-',149 fMode & RTFS_DOS_NT_COMPRESSED ? 'C' : '-',150 fMode & RTFS_DOS_NT_OFFLINE ? 'O' : '-',151 fMode & RTFS_DOS_NT_NOT_CONTENT_INDEXED ? 'I' : '-',152 fMode & RTFS_DOS_NT_ENCRYPTED ? 'E' : '-');153 RTPrintf(" %d %4d %4d %10lld %10lld %#llx %#llx %#llx %#llx",154 DirEntry.Info.Attr.u.Unix.cHardlinks,155 DirEntry.Info.Attr.u.Unix.uid,156 DirEntry.Info.Attr.u.Unix.gid,157 DirEntry.Info.cbObject,158 DirEntry.Info.cbAllocated,159 DirEntry.Info.BirthTime,160 DirEntry.Info.ChangeTime,161 DirEntry.Info.ModificationTime,162 DirEntry.Info.AccessTime);163 if (fShortName && DirEntry.cwcShortName)164 RTPrintf(" %2d %ls\n", DirEntry.cwcShortName, DirEntry.wszShortName);165 else166 RTPrintf(" %2d %s\n", DirEntry.cbName, DirEntry.szName);167 184 if (rc != VINF_SUCCESS) 168 185 RTPrintf("^^ %Rrc\n", rc);
Note:
See TracChangeset
for help on using the changeset viewer.