Changeset 57196 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Aug 5, 2015 2:33:52 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 101948
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/HBDMgmt-win.cpp
r57190 r57196 47 47 /** The block device name. */ 48 48 char *pszDevice; 49 /** Number of mountpoint handles in the array below. */50 unsigned c MountpointHandles;51 /** Array of mountpoint handles for a particular volume or disk, variable size. */52 HANDLE a MountpointHandles[1];49 /** Number of volumes for this block device. */ 50 unsigned cVolumes; 51 /** Array of handle to the volumes for unmounting and taking it offline. */ 52 HANDLE ahVolumes[1]; 53 53 } HBDMGRDEV; 54 54 /** Pointer to a claimed block device. */ … … 87 87 static void hbdMgrDevUnclaim(PHBDMGRDEV pDev) 88 88 { 89 for (unsigned i = 0; i < pDev->cMountpointHandles; i++) 89 LogFlowFunc(("pDev=%p{%s} cVolumes=%u\n", pDev, pDev->pszDevice, pDev->cVolumes)); 90 91 for (unsigned i = 0; i < pDev->cVolumes; i++) 90 92 { 91 93 DWORD dwReturned = 0; 92 BOOL bRet = DeviceIoControl(pDev->aMountpointHandles[i], IOCTL_VOLUME_ONLINE, NULL, 0, NULL, 0, &dwReturned, NULL); 94 95 LogFlowFunc(("Taking volume %u online\n", i)); 96 BOOL bRet = DeviceIoControl(pDev->ahVolumes[i], IOCTL_VOLUME_ONLINE, NULL, 0, NULL, 0, &dwReturned, NULL); 93 97 if (!bRet) 94 98 LogRel(("HBDMgmt: Failed to take claimed volume online during cleanup: %s{%Rrc}\n", 95 99 pDev->pszDevice, RTErrConvertFromWin32(GetLastError()))); 100 101 CloseHandle(pDev->ahVolumes[i]); 96 102 } 97 103 … … 205 211 } 206 212 207 /** 208 * Splits the given mount point buffer into individual entries. 209 * 210 * @returns VBox status code. 211 * @param pwszMountpoints The buffer holding the list of mountpoints separated by a null terminator, 212 * the end of the list is marked with an extra null terminator. 213 * @param ppapwszMountpoints Where to store the array of mount points on success. 214 * @param pcMountpoints Where to store the returned number of mount points on success. 215 */ 216 static int hbdMgrSplitMountpointBuffer(PRTUTF16 pwszMountpoints, PRTUTF16 **ppapwszMountpoints, unsigned *pcMountpoints) 217 { 218 int rc = VINF_SUCCESS; 219 unsigned cMountpoints = 0; 220 221 *pcMountpoints = 0; 222 *ppapwszMountpoints = NULL; 223 224 /* First round, count the number of mountpoints. */ 225 PRTUTF16 pwszMountpointCur = pwszMountpoints; 226 while (*pwszMountpointCur != L'\0') 227 { 228 pwszMountpointCur = (PRTUTF16)RTUtf16End(pwszMountpointCur, RTSTR_MAX); 229 pwszMountpointCur++; 230 cMountpoints++; 231 } 232 233 PRTUTF16 *papwszMountpoints = (PRTUTF16 *)RTMemAllocZ(cMountpoints * sizeof(PRTUTF16)); 234 if (RT_LIKELY(papwszMountpoints)) 235 { 236 unsigned idxMountpoint = 0; 237 238 pwszMountpointCur = pwszMountpoints; 239 240 /* Split the buffer now. */ 241 while ( *pwszMountpointCur != L'\0' 242 && RT_SUCCESS(rc) 243 && idxMountpoint < cMountpoints) 244 { 245 papwszMountpoints[idxMountpoint] = RTUtf16Dup(pwszMountpointCur); 246 if (!papwszMountpoints[idxMountpoint]) 247 { 248 rc = VERR_NO_STR_MEMORY; 249 break; 250 } 251 252 pwszMountpointCur = (PRTUTF16)RTUtf16End(pwszMountpointCur, RTSTR_MAX); 253 pwszMountpointCur++; 254 idxMountpoint++; 255 } 256 257 if (RT_SUCCESS(rc)) 258 { 259 *pcMountpoints = cMountpoints; 260 *ppapwszMountpoints = papwszMountpoints; 261 } 262 else 263 { 264 /* Undo everything. */ 265 while (idxMountpoint-- > 0) 266 RTUtf16Free(papwszMountpoints[idxMountpoint]); 267 RTMemFree(papwszMountpoints); 268 } 269 } 270 else 271 rc = VERR_NO_MEMORY; 272 273 return rc; 274 } 275 276 /** 277 * Queries all available mount points for a given volume. 278 * 279 * @returns VBox status code. 280 * @param pwszVolNt The volume to query the mount points for (NT namespace). 281 * @param ppapwszMountpoints Where to store the array of mount points on success. 282 * @param pcMountpoints Where to store the returned number of mount points on success. 283 */ 284 static int hbdMgrQueryMountpointsForVolume(PRTUTF16 pwszVolNt, PRTUTF16 **ppapwszMountpoints, unsigned *pcMountpoints) 285 { 286 int rc = VINF_SUCCESS; 287 RTUTF16 awszVolume[64]; 288 289 /* 290 * Volume names returned by FindFirstVolume/FindNextVolume have a very strict format looking 291 * like \\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}, so the buffer for the name can be static. 292 */ 293 RT_ZERO(awszVolume); 294 295 HANDLE hVol = FindFirstVolumeW(&awszVolume[0], RT_ELEMENTS(awszVolume)); 296 if (hVol != INVALID_HANDLE_VALUE) 297 { 298 do 299 { 300 PRTUTF16 pwszVolNtCur = NULL; 301 rc = hbdMgrQueryNtName(awszVolume, &pwszVolNtCur); 302 if (RT_SUCCESS(rc)) 303 { 304 /* If both volume names match we found the right one. */ 305 if (!RTUtf16Cmp(pwszVolNtCur, pwszVolNt)) 306 { 307 DWORD cchBufferLength = 100; 308 DWORD cchBufRequired = 0; 309 PRTUTF16 pwszVolumeMountpoints = RTUtf16Alloc(cchBufferLength * sizeof(RTUTF16)); 310 if (pwszVolumeMountpoints) 311 { 312 BOOL bRet = GetVolumePathNamesForVolumeNameW(awszVolume, pwszVolumeMountpoints, 313 cchBufferLength, &cchBufRequired); 314 if ( !bRet 315 && GetLastError() == ERROR_MORE_DATA) 316 { 317 /* Realloc and try again. */ 318 RTUtf16Free(pwszVolumeMountpoints); 319 pwszVolumeMountpoints = RTUtf16Alloc(cchBufRequired * sizeof(RTUTF16)); 320 if (pwszVolumeMountpoints) 321 { 322 cchBufferLength = cchBufRequired; 323 bRet = GetVolumePathNamesForVolumeNameW(awszVolume, pwszVolumeMountpoints, 324 cchBufferLength, &cchBufRequired); 325 } 326 else 327 rc = VERR_NO_STR_MEMORY; 328 } 329 330 if ( RT_SUCCESS(rc) 331 && bRet) 332 rc = hbdMgrSplitMountpointBuffer(pwszVolumeMountpoints, ppapwszMountpoints, 333 pcMountpoints); 334 else if (RT_SUCCESS(rc)) 335 rc = RTErrConvertFromWin32(GetLastError()); 336 337 RTUtf16Free(pwszVolumeMountpoints); 338 } 339 else 340 rc = VERR_NO_STR_MEMORY; 341 342 break; 343 } 344 else 345 { 346 RTUtf16Free(pwszVolNtCur); 347 RT_ZERO(awszVolume); 348 BOOL bRet = FindNextVolumeW(hVol, &awszVolume[0], RT_ELEMENTS(awszVolume)); 349 if (!bRet) 350 { 351 DWORD dwRet = GetLastError(); 352 if (dwRet == ERROR_NO_MORE_FILES) 353 rc = VERR_NOT_FOUND; 354 else 355 rc = RTErrConvertFromWin32(dwRet); 356 break; 357 } 358 } 359 } 360 } while (RT_SUCCESS(rc)); 361 362 FindVolumeClose(hVol); 363 } 364 else 365 rc = RTErrConvertFromWin32(GetLastError()); 366 367 return rc; 368 } 369 370 static int hbdMgrQueryAllMountpointsForDisk(PRTUTF16 pwszDiskNt, PRTUTF16 **ppapwszMountpoints, 371 unsigned *pcMountpoints) 213 static int hbdMgrQueryAllMountpointsForDisk(PRTUTF16 pwszDiskNt, PRTUTF16 **ppapwszVolumes, 214 unsigned *pcVolumes) 372 215 { 373 216 /* … … 381 224 int rc = VINF_SUCCESS; 382 225 char *pszDiskNt = NULL; 383 unsigned cMountpoints = 0; 384 PRTUTF16 *papwszMountpoints = NULL; 226 unsigned cVolumes = 0; 227 unsigned cVolumesMax = 10; 228 PRTUTF16 *papwszVolumes = (PRTUTF16 *)RTMemAllocZ(cVolumesMax * sizeof(PRTUTF16)); 229 230 if (!papwszVolumes) 231 return VERR_NO_MEMORY; 385 232 386 233 rc = RTUtf16ToUtf8(pwszDiskNt, &pszDiskNt); … … 415 262 if (RT_SUCCESS(rc)) 416 263 { 417 unsigned cMountpointsCur = 0; 418 PRTUTF16 *papwszMountpointsCur = NULL; 419 420 rc = hbdMgrQueryMountpointsForVolume(pwszTargetNt, &papwszMountpointsCur, 421 &cMountpointsCur); 422 if (RT_SUCCESS(rc)) 264 if (cVolumes == cVolumesMax) 423 265 { 424 if (!papwszMountpoints) 266 /* Increase array of volumes. */ 267 PRTUTF16 *papwszVolumesNew = (PRTUTF16 *)RTMemAllocZ((cVolumesMax + 10) * sizeof(PRTUTF16)); 268 if (papwszVolumesNew) 425 269 { 426 papwszMountpoints = papwszMountpointsCur;427 cMountpoints = cMountpointsCur;270 cVolumesMax += 10; 271 papwszVolumes = papwszVolumesNew; 428 272 } 429 273 else 430 274 { 431 PRTUTF16 *papwszMountpointsNew = (PRTUTF16 *)RTMemRealloc(papwszMountpoints, 432 (cMountpoints + cMountpointsCur) * sizeof(PRTUTF16)); 433 if (papwszMountpointsNew) 434 { 435 for (unsigned i = cMountpoints; i < cMountpoints + cMountpointsCur; i++) 436 papwszMountpointsNew[i] = papwszMountpointsCur[i - cMountpoints]; 437 438 papwszMountpoints = papwszMountpointsNew; 439 } 440 else 441 { 442 for (unsigned i = 0; i < cMountpointsCur; i++) 443 RTUtf16Free(papwszMountpointsCur[i]); 444 445 rc = VERR_NO_MEMORY; 446 } 275 RTUtf16Free(pwszTargetNt); 276 rc = VERR_NO_MEMORY; 447 277 } 448 449 RTMemFree(papwszMountpointsCur);450 278 } 451 279 452 iPart++; 453 RTUtf16Free(pwszTargetNt); 280 if (RT_SUCCESS(rc)) 281 { 282 Assert(cVolumes < cVolumesMax); 283 papwszVolumes[cVolumes++] = pwszTargetNt; 284 iPart++; 285 } 454 286 } 455 287 else if (rc == VERR_FILE_NOT_FOUND) … … 477 309 if (RT_SUCCESS(rc)) 478 310 { 479 *pcMountpoints = cMountpoints; 480 *ppapwszMountpoints = papwszMountpoints; 311 *pcVolumes = cVolumes; 312 *ppapwszVolumes = papwszVolumes; 313 LogFlowFunc(("rc=%Rrc cVolumes=%u ppapwszVolumes=%p\n", rc, cVolumes, papwszVolumes)); 481 314 } 482 315 else 483 316 { 484 for (unsigned i = 0; i < c Mountpoints; i++)485 RTUtf16Free(papwsz Mountpoints[i]);486 487 RTMemFree(papwsz Mountpoints);317 for (unsigned i = 0; i < cVolumes; i++) 318 RTUtf16Free(papwszVolumes[i]); 319 320 RTMemFree(papwszVolumes); 488 321 } 489 322 490 323 return rc; 324 } 325 326 static NTSTATUS hbdMgrNtCreateFileWrapper(PRTUTF16 pwszVolume, HANDLE *phVolume) 327 { 328 HANDLE hVolume = RTNT_INVALID_HANDLE_VALUE; 329 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 330 UNICODE_STRING NtName; 331 332 NtName.Buffer = (PWSTR)pwszVolume; 333 NtName.Length = (USHORT)(RTUtf16Len(pwszVolume) * sizeof(RTUTF16)); 334 NtName.MaximumLength = NtName.Length + sizeof(WCHAR); 335 336 OBJECT_ATTRIBUTES ObjAttr; 337 InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/); 338 339 NTSTATUS rcNt = NtCreateFile(&hVolume, 340 FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE, 341 &ObjAttr, 342 &Ios, 343 NULL /* Allocation Size*/, 344 FILE_ATTRIBUTE_NORMAL, 345 FILE_SHARE_READ | FILE_SHARE_WRITE, 346 FILE_OPEN, 347 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, 348 NULL /*EaBuffer*/, 349 0 /*EaLength*/); 350 if (NT_SUCCESS(rcNt)) 351 rcNt = Ios.Status; 352 353 if (NT_SUCCESS(rcNt)) 354 *phVolume = hVolume; 355 356 return rcNt; 491 357 } 492 358 … … 536 402 if (!fIsBlockDevice) 537 403 fIsBlockDevice = RTStrNICmp(pszFilename, "\\\\.\\Harddisk", sizeof("\\\\.\\Harddisk") - 1) == 0 ? true : false; 404 405 LogFlowFunc(("returns %s -> %RTbool\n", pszFilename, fIsBlockDevice)); 538 406 return fIsBlockDevice; 539 407 } … … 559 427 if (RT_SUCCESS(rc)) 560 428 { 561 PRTUTF16 *papwsz Mountpoints = NULL;562 unsigned c Mountpoints = 0;429 PRTUTF16 *papwszVolumes = NULL; 430 unsigned cVolumes = 0; 563 431 564 432 /* Complete disks need to be handled differently. */ 565 433 if (!RTStrNCmp(pszFilename, "\\\\.\\PhysicalDrive", sizeof("\\\\.\\PhysicalDrive") - 1)) 566 rc = hbdMgrQueryAllMountpointsForDisk(pwszVolNt, &papwszMountpoints, &cMountpoints); 434 { 435 rc = hbdMgrQueryAllMountpointsForDisk(pwszVolNt, &papwszVolumes, &cVolumes); 436 RTUtf16Free(pwszVolNt); 437 } 567 438 else 568 rc = hbdMgrQueryMountpointsForVolume(pwszVolNt, &papwszMountpoints, &cMountpoints); 439 { 440 papwszVolumes = &pwszVolNt; 441 cVolumes = 1; 442 } 569 443 570 444 if (RT_SUCCESS(rc)) 571 445 { 572 /** @todo: Unmount everything and take volume offline. */ 573 574 for (unsigned i = 0; i < cMountpoints; i++) 575 RTUtf16Free(papwszMountpoints[i]); 576 577 RTMemFree(papwszMountpoints); 446 #ifdef LOG_ENABLED 447 for (unsigned i = 0; i < cVolumes; i++) 448 LogFlowFunc(("Volume %u: %ls\n", i, papwszVolumes[i])); 449 #endif 450 pDev = (PHBDMGRDEV)RTMemAllocZ(RT_OFFSETOF(HBDMGRDEV, ahVolumes[cVolumes])); 451 if (pDev) 452 { 453 pDev->cVolumes = 0; 454 pDev->pszDevice = RTStrDup(pszFilename); 455 if (pDev->pszDevice) 456 { 457 for (unsigned i = 0; i < cVolumes; i++) 458 { 459 HANDLE hVolume; 460 461 NTSTATUS rcNt = hbdMgrNtCreateFileWrapper(papwszVolumes[i], &hVolume); 462 if (NT_SUCCESS(rcNt)) 463 { 464 DWORD dwReturned = 0; 465 466 Assert(hVolume != INVALID_HANDLE_VALUE); 467 BOOL bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwReturned, NULL); 468 if (bRet) 469 { 470 bRet = DeviceIoControl(hVolume, IOCTL_VOLUME_OFFLINE, NULL, 0, NULL, 0, &dwReturned, NULL); 471 if (bRet) 472 pDev->ahVolumes[pDev->cVolumes++] = hVolume; 473 else 474 rc = RTErrConvertFromWin32(GetLastError()); 475 } 476 else 477 rc = RTErrConvertFromWin32(GetLastError()); 478 479 if (RT_FAILURE(rc)) 480 CloseHandle(hVolume); 481 } 482 else 483 rc = RTErrConvertFromNtStatus(rcNt); 484 } 485 } 486 else 487 rc = VERR_NO_STR_MEMORY; 488 489 if (RT_SUCCESS(rc)) 490 { 491 RTSemFastMutexRequest(pThis->hMtxList); 492 RTListAppend(&pThis->ListClaimed, &pDev->ListNode); 493 RTSemFastMutexRelease(pThis->hMtxList); 494 } 495 else 496 { 497 /* Close all open handles and take the volumes online again. */ 498 for (unsigned i = 0; i < pDev->cVolumes; i++) 499 { 500 DWORD dwReturned = 0; 501 BOOL bRet = DeviceIoControl(pDev->ahVolumes[i], IOCTL_VOLUME_ONLINE, NULL, 0, NULL, 0, &dwReturned, NULL); 502 if (!bRet) 503 LogRel(("HBDMgmt: Failed to take claimed volume online during cleanup: %s{%Rrc}\n", 504 pDev->pszDevice, RTErrConvertFromWin32(GetLastError()))); 505 506 CloseHandle(pDev->ahVolumes[i]); 507 } 508 if (pDev->pszDevice) 509 RTStrFree(pDev->pszDevice); 510 RTMemFree(pDev); 511 } 512 } 513 else 514 rc = VERR_NO_MEMORY; 515 516 for (unsigned i = 0; i < cVolumes; i++) 517 RTUtf16Free(papwszVolumes[i]); 518 519 RTMemFree(papwszVolumes); 578 520 } 579 580 RTUtf16Free(pwszVolNt);581 521 } 582 522
Note:
See TracChangeset
for help on using the changeset viewer.