Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

728 lines
20 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. uninstall.c
  5. Abstract:
  6. General uninstall-related functions.
  7. Author:
  8. Aghajanyan Souren 27-Mar-2001
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "uninstall.h"
  13. #define PARTITIONS_DEFAULT_NUMBER 128
  14. BOOL
  15. GetDiskInfo(
  16. IN UINT Drive,
  17. IN OUT DISKINFO * pInfo
  18. )
  19. {
  20. HANDLE hDisk = NULL;
  21. DWORD dwBytesReturned;
  22. DWORD dwLastError;
  23. UINT uiBufferSize;
  24. BOOL bResult;
  25. TCHAR diskPath[MAX_PATH];
  26. DRIVE_LAYOUT_INFORMATION_EX * pinfoLayoutEx = NULL;
  27. if(!pInfo){
  28. SetLastError(ERROR_INVALID_PARAMETER);
  29. MYASSERT(FALSE);
  30. return FALSE;
  31. }
  32. __try{
  33. StringCbPrintf(diskPath, sizeof(diskPath), TEXT("\\\\.\\PHYSICALDRIVE%d"), Drive);
  34. hDisk = CreateFile(diskPath,
  35. GENERIC_READ,
  36. FILE_SHARE_READ | FILE_SHARE_WRITE,
  37. NULL,
  38. OPEN_EXISTING,
  39. 0,
  40. NULL);
  41. if(INVALID_HANDLE_VALUE == hDisk){
  42. dwLastError = GetLastError();
  43. __leave;
  44. }
  45. StringCbAppendWack(diskPath, sizeof(diskPath));
  46. if(DRIVE_FIXED != GetDriveType(diskPath)){
  47. dwLastError = ERROR_ACCESS_DENIED;
  48. __leave;
  49. }
  50. dwBytesReturned = 0;
  51. bResult = DeviceIoControl(hDisk,
  52. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  53. NULL,
  54. 0,
  55. &pInfo->DiskGeometry,
  56. sizeof(pInfo->DiskGeometry),
  57. &dwBytesReturned,
  58. NULL);
  59. if(!bResult){
  60. dwLastError = GetLastError();
  61. LOG((LOG_WARNING, "GetDiskInfo:DeviceIoControl(%s, IOCTL_DISK_GET_DRIVE_GEOMETRY) failed.", diskPath));
  62. __leave;
  63. }
  64. uiBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX);
  65. do{
  66. uiBufferSize += PARTITIONS_DEFAULT_NUMBER * sizeof(PARTITION_INFORMATION_EX);
  67. if(pinfoLayoutEx){
  68. FreeMem(pinfoLayoutEx);
  69. }
  70. pinfoLayoutEx = (DRIVE_LAYOUT_INFORMATION_EX *)MemAllocZeroed(uiBufferSize);
  71. if(!pinfoLayoutEx){
  72. dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  73. __leave;
  74. }
  75. dwBytesReturned = 0;
  76. bResult = DeviceIoControl(hDisk,
  77. IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
  78. NULL,
  79. 0,
  80. pinfoLayoutEx,
  81. uiBufferSize,
  82. &dwBytesReturned,
  83. NULL);
  84. }while(!bResult && ERROR_INSUFFICIENT_BUFFER == GetLastError());
  85. if(!bResult){
  86. dwLastError = GetLastError();
  87. LOG((LOG_WARNING, "GetDiskInfo:DeviceIoControl(%s, IOCTL_DISK_GET_DRIVE_LAYOUT_EX) failed.", diskPath));
  88. __leave;
  89. }
  90. pInfo->DiskLayout = pinfoLayoutEx;
  91. dwLastError = ERROR_SUCCESS;
  92. }
  93. __except(EXCEPTION_EXECUTE_HANDLER){
  94. if(pinfoLayoutEx){
  95. FreeMem(pinfoLayoutEx);
  96. }
  97. }
  98. if(hDisk){
  99. CloseHandle(hDisk);
  100. }
  101. SetLastError(dwLastError);
  102. return ERROR_SUCCESS == dwLastError;
  103. }
  104. BOOL
  105. GetPhysycalDiskNumber(
  106. OUT UINT * pNumberOfPhysicalDisks
  107. )
  108. {
  109. TCHAR diskPath[MAX_PATH];
  110. HANDLE hDisk;
  111. UINT i;
  112. if(!pNumberOfPhysicalDisks){
  113. SetLastError(ERROR_INVALID_PARAMETER);
  114. MYASSERT(FALSE);
  115. return FALSE;
  116. }
  117. *pNumberOfPhysicalDisks = 0;
  118. for(i = 0; ; i++){
  119. StringCbPrintf(diskPath, sizeof(diskPath), TEXT("\\\\.\\PHYSICALDRIVE%d"), i);
  120. hDisk = CreateFile(diskPath,
  121. GENERIC_READ,
  122. FILE_SHARE_READ | FILE_SHARE_WRITE,
  123. NULL,
  124. OPEN_EXISTING,
  125. 0,
  126. NULL);
  127. if(INVALID_HANDLE_VALUE == hDisk){
  128. MYASSERT(GetLastError() == ERROR_FILE_NOT_FOUND);
  129. break;
  130. }
  131. CloseHandle(hDisk);
  132. StringCbAppendWack(diskPath, sizeof(diskPath));
  133. if(DRIVE_FIXED != GetDriveType(diskPath)){
  134. continue;
  135. }
  136. (*pNumberOfPhysicalDisks)++;
  137. }
  138. SetLastError(ERROR_SUCCESS);
  139. return TRUE;
  140. }
  141. BOOL
  142. GetDisksInfo(
  143. OUT DISKINFO ** pInfo,
  144. OUT UINT * pNumberOfItem
  145. )
  146. {
  147. UINT i;
  148. UINT diskNumber;
  149. if(!pInfo || !pNumberOfItem){
  150. SetLastError(ERROR_INVALID_PARAMETER);
  151. MYASSERT(FALSE);
  152. return FALSE;
  153. }
  154. if(!GetPhysycalDiskNumber(pNumberOfItem)){
  155. DEBUGMSG((DBG_ERROR, "GetDisksInfo:GetPhysycalDiskNumber failed"));
  156. return FALSE;
  157. }
  158. *pInfo = (DISKINFO *)MemAllocZeroed(*pNumberOfItem * sizeof(DISKINFO));
  159. if(!*pInfo){
  160. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  161. LOG((LOG_WARNING, "GetDisksInfo:MemAlloc failed to allocate memory for %d disks", *pNumberOfItem));
  162. return FALSE;
  163. }
  164. diskNumber = 0;
  165. for(i = 0; i < *pNumberOfItem; i++){
  166. while(!GetDiskInfo(diskNumber++, (*pInfo) + i)){
  167. if(ERROR_ACCESS_DENIED == GetLastError()){
  168. continue;
  169. }
  170. if(ERROR_FILE_NOT_FOUND == GetLastError()){
  171. break;
  172. }
  173. LOG((LOG_WARNING, "GetDisksInfo:GetDiskInfo(phisycaldisk%d) failed with total %d", diskNumber, *pNumberOfItem));
  174. FreeDisksInfo(*pInfo, *pNumberOfItem);
  175. return FALSE;
  176. }
  177. }
  178. SetLastError(ERROR_SUCCESS);
  179. return TRUE;
  180. }
  181. VOID
  182. FreeDisksInfo(
  183. IN DISKINFO * pInfo,
  184. IN UINT NumberOfItem
  185. )
  186. {
  187. UINT i;
  188. if(!pInfo || !NumberOfItem){
  189. SetLastError(ERROR_INVALID_PARAMETER);
  190. MYASSERT(FALSE);
  191. return;
  192. }
  193. __try{
  194. for(i = 0; i < NumberOfItem; i++){
  195. if(pInfo[i].DiskLayout){
  196. FreeMem(pInfo[i].DiskLayout);
  197. }
  198. }
  199. FreeMem(pInfo);
  200. }
  201. __except(EXCEPTION_EXECUTE_HANDLER){
  202. DEBUGMSG((DBG_ERROR, "FreeDisksInfo throwed exception"));
  203. }
  204. }
  205. //BUGBUG -- ISSUE -- This function assumes that the members of pInfo are allocated
  206. //with the appropriate minimum sizes!!!
  207. BOOL
  208. GetDriveInfo(
  209. IN WCHAR Drive,
  210. IN OUT DRIVEINFO * pInfo
  211. )
  212. {
  213. WCHAR driveDosPath[] = L"?:\\";
  214. WCHAR driveDosDeviceVolumeMountPoint[MAX_PATH];
  215. BOOL result;
  216. if(!pInfo || !pInfo->FileSystemName || !pInfo->VolumeNTPath){
  217. SetLastError(ERROR_INVALID_PARAMETER);
  218. MYASSERT(FALSE);
  219. return FALSE;
  220. }
  221. pInfo->Drive = Drive;
  222. driveDosPath[0] = Drive;
  223. if(!GetVolumeNameForVolumeMountPointW(driveDosPath,
  224. driveDosDeviceVolumeMountPoint,
  225. ARRAYSIZE(driveDosDeviceVolumeMountPoint))){
  226. DEBUGMSGW((DBG_WARNING, "GetDiskInfo:GetVolumeNameForVolumeMountPoint(%s) failed", driveDosPath));
  227. SetLastError(ERROR_ACCESS_DENIED);
  228. return FALSE;
  229. }
  230. //BUGBUG assumes VolumeNTPath has size MAX_PATH. In a search of the codebase in ntsetup, I found
  231. //this to be the case
  232. wcscpy((LPWSTR)pInfo->VolumeNTPath, driveDosDeviceVolumeMountPoint);
  233. result = GetVolumeInformationW(
  234. driveDosPath,
  235. NULL,
  236. 0,
  237. NULL,
  238. NULL,
  239. &pInfo->FileSystemFlags,
  240. (LPWSTR)pInfo->FileSystemName,
  241. MAX_PATH
  242. );
  243. if(!result && (GetLastError() == ERROR_UNRECOGNIZED_VOLUME)){
  244. //BUGBUG assumes FileSystemName has size MAX_PATH. In a search of the codebase in ntsetup, I found
  245. //this to be the case
  246. wcscpy((LPWSTR)pInfo->FileSystemName, L"UNRECOGNIZED_VOLUME");
  247. result = TRUE;
  248. DEBUGMSGW((DBG_WARNING, "GetDiskInfo:GetVolumeInformation(%s):GetLastError() == ERROR_UNRECOGNIZED_VOLUME", driveDosPath));
  249. }
  250. DEBUGMSGW_IF((!result, DBG_ERROR, "GetDiskInfo:GetVolumeInformation(%s):GetLastError() == %d", driveDosPath, GetLastError()));
  251. return result;
  252. }
  253. BOOL
  254. GetIntegrityInfoW(
  255. IN PCWSTR FileName,
  256. IN PCWSTR DirPath,
  257. OUT FILEINTEGRITYINFO * IntegrityInfoPtr
  258. )
  259. {
  260. WCHAR pathFile[MAX_PATH];
  261. if(!FileName || !DirPath || !IntegrityInfoPtr){
  262. SetLastError(ERROR_INVALID_PARAMETER);
  263. MYASSERT(FALSE);
  264. return FALSE;
  265. }
  266. #pragma prefast(suppress:209, "Use of sizeof(pathFile) is correct")
  267. StringCbCopyW(pathFile, sizeof(pathFile), DirPath);
  268. #pragma prefast(suppress:209, "Use of sizeof(pathFile) is correct")
  269. StringCbCatW(StringCbAppendWackW(pathFile, sizeof(pathFile)), sizeof(pathFile),FileName);
  270. //BUGBUG assumes FileName is of size MAX_PATH.
  271. StringCopyW((LPWSTR)IntegrityInfoPtr->FileName, FileName);
  272. if(!GetFileSizeFromFilePathW(pathFile, &IntegrityInfoPtr->FileSize)){
  273. return FALSE;
  274. }
  275. SetLastError(ERROR_SUCCESS);
  276. return TRUE;
  277. }
  278. BOOL
  279. GetDrivesInfo(
  280. IN OUT DRIVEINFO * pInfo,
  281. IN OUT UINT * pDiskInfoRealCount,
  282. IN UINT DiskInfoMaxCount
  283. )
  284. {
  285. UINT LogicalDrives;
  286. WCHAR DriveName[] = L"?:\\";
  287. UINT i;
  288. if(!pDiskInfoRealCount){
  289. SetLastError(ERROR_INVALID_PARAMETER);
  290. MYASSERT(FALSE);
  291. return FALSE;
  292. }
  293. if(!(LogicalDrives = GetLogicalDrives())) {
  294. return FALSE;
  295. }
  296. *pDiskInfoRealCount = 0;
  297. for(i = 0; LogicalDrives && ((*pDiskInfoRealCount) < DiskInfoMaxCount); LogicalDrives >>= 1, i++){
  298. if(LogicalDrives&1) {
  299. DriveName[0] = 'A' + (char)i;
  300. if(DRIVE_FIXED != GetDriveTypeW(DriveName)) {
  301. continue;
  302. }
  303. if(pInfo){
  304. if(!GetDriveInfo(DriveName[0], pInfo++)){
  305. MYASSERT(FALSE);
  306. return FALSE;
  307. }
  308. }
  309. (*pDiskInfoRealCount)++;
  310. }
  311. }
  312. SetLastError(ERROR_SUCCESS);
  313. return TRUE;
  314. }
  315. BOOL
  316. GetUndoDrivesInfo(
  317. OUT DRIVEINFO * pInfo,
  318. OUT UINT * pNumberOfDrive,
  319. IN WCHAR BootDrive,
  320. IN WCHAR SystemDrive,
  321. IN WCHAR UndoDrive
  322. )
  323. {
  324. if(!pInfo || !pNumberOfDrive){
  325. SetLastError(ERROR_INVALID_PARAMETER);
  326. MYASSERT(FALSE);
  327. return FALSE;
  328. }
  329. *pNumberOfDrive = 0;
  330. if(!GetDriveInfo(BootDrive, pInfo++)){
  331. MYASSERT(FALSE);
  332. return FALSE;
  333. }
  334. (*pNumberOfDrive)++;
  335. if(SystemDrive != BootDrive){
  336. if(!GetDriveInfo(SystemDrive, pInfo++)){
  337. MYASSERT(FALSE);
  338. return FALSE;
  339. }
  340. (*pNumberOfDrive)++;
  341. }
  342. if(UndoDrive != BootDrive && UndoDrive != SystemDrive){
  343. if(!GetDriveInfo(UndoDrive, pInfo++)){
  344. MYASSERT(FALSE);
  345. return FALSE;
  346. }
  347. (*pNumberOfDrive)++;
  348. }
  349. SetLastError(ERROR_SUCCESS);
  350. return TRUE;
  351. }
  352. DISKINFO_COMPARATION_STATUS
  353. CompareDriveInfo(
  354. IN DRIVEINFO * FirstInfo,
  355. IN DRIVEINFO * SecondInfo
  356. )
  357. {
  358. if(!FirstInfo || !SecondInfo){
  359. MYASSERT(FALSE);
  360. return DiskInfoCmp_WrongParameters;
  361. }
  362. if(towlower(FirstInfo->Drive) != towlower(SecondInfo->Drive)){
  363. return DiskInfoCmp_DifferentLetter;
  364. }
  365. MYASSERT(FirstInfo->FileSystemName && SecondInfo->FileSystemName);
  366. if(wcscmp(FirstInfo->FileSystemName, SecondInfo->FileSystemName)){
  367. return DiskInfoCmp_FileSystemHasChanged;
  368. }
  369. if(FirstInfo->FileSystemFlags != SecondInfo->FileSystemFlags){
  370. return DiskInfoCmp_FileSystemHasChanged;
  371. }
  372. MYASSERT(FirstInfo->VolumeNTPath && SecondInfo->VolumeNTPath);
  373. if(wcscmp(FirstInfo->VolumeNTPath, SecondInfo->VolumeNTPath)){
  374. return DiskInfoCmp_DriveMountPointHasChanged;
  375. }
  376. return DiskInfoCmp_Equal;
  377. }
  378. BOOL
  379. CompareDrivesInfo(
  380. IN DRIVEINFO * FirstInfo,
  381. IN DRIVEINFO * SecondInfo,
  382. IN UINT DriveInfoCount,
  383. OUT PDISKINFO_COMPARATION_STATUS OutDiskCmpStatus, OPTIONAL
  384. OUT UINT * OutIfFailedDiskInfoIndex OPTIONAL
  385. )
  386. {
  387. UINT i;
  388. DISKINFO_COMPARATION_STATUS cmpStatus;
  389. if(!FirstInfo || !SecondInfo || !DriveInfoCount){
  390. MYASSERT(FALSE);
  391. SetLastError(ERROR_INVALID_PARAMETER);
  392. return FALSE;
  393. }
  394. for(i = 0; i < DriveInfoCount; i++){
  395. cmpStatus = CompareDriveInfo(FirstInfo++, SecondInfo++);
  396. if(DiskInfoCmp_Equal != cmpStatus){
  397. if(OutDiskCmpStatus){
  398. *OutDiskCmpStatus = cmpStatus;
  399. }
  400. if(OutIfFailedDiskInfoIndex){
  401. *OutIfFailedDiskInfoIndex = i;
  402. }
  403. SetLastError(ERROR_ACCESS_DENIED);
  404. return FALSE;
  405. }
  406. }
  407. SetLastError(ERROR_SUCCESS);
  408. return TRUE;
  409. }
  410. DISKINFO_COMPARATION_STATUS
  411. CompareDiskInfo(
  412. IN DISKINFO * FirstInfo,
  413. IN DISKINFO * SecondInfo
  414. )
  415. {
  416. DWORD i, iLen;
  417. PARTITION_INFORMATION_EX * pPartition1;
  418. PARTITION_INFORMATION_EX * pPartition2;
  419. if(!FirstInfo || !SecondInfo || !FirstInfo->DiskLayout || !SecondInfo->DiskLayout){
  420. MYASSERT(FALSE);
  421. return DiskInfoCmp_WrongParameters;
  422. }
  423. //
  424. //DISK_GEOMETRY
  425. //
  426. if(memcmp(&FirstInfo->DiskGeometry, &SecondInfo->DiskGeometry, sizeof(FirstInfo->DiskGeometry))){
  427. return DiskInfoCmp_GeometryHasChanged;
  428. }
  429. //
  430. //DRIVE_LAYOUT_INFORMATION_EX
  431. //
  432. if(FirstInfo->DiskLayout->PartitionStyle != SecondInfo->DiskLayout->PartitionStyle){
  433. return DiskInfoCmp_PartitionStyleHasChanged;
  434. }
  435. if(FirstInfo->DiskLayout->PartitionCount != SecondInfo->DiskLayout->PartitionCount){
  436. return DiskInfoCmp_PartitionCountHasChanged;
  437. }
  438. //
  439. //PARTITION_INFORMATION
  440. //
  441. for(i = 0, iLen = FirstInfo->DiskLayout->PartitionCount; i < iLen; i++){
  442. pPartition1 = &FirstInfo->DiskLayout->PartitionEntry[i];
  443. pPartition2 = &SecondInfo->DiskLayout->PartitionEntry[i];
  444. if(pPartition1->PartitionStyle != pPartition2->PartitionStyle){
  445. return DiskInfoCmp_PartitionStyleHasChanged;
  446. }
  447. if(pPartition1->StartingOffset.QuadPart != pPartition2->StartingOffset.QuadPart){
  448. return DiskInfoCmp_PartitionPlaceHasChanged;
  449. }
  450. if(pPartition1->PartitionLength.QuadPart != pPartition2->PartitionLength.QuadPart){
  451. return DiskInfoCmp_PartitionLengthHasChanged;
  452. }
  453. if(pPartition1->PartitionNumber != pPartition2->PartitionNumber){
  454. return DiskInfoCmp_PartitionNumberHasChanged;
  455. }
  456. if(pPartition1->RewritePartition != pPartition2->RewritePartition){
  457. return DiskInfoCmp_RewritePartitionHasChanged;
  458. }
  459. if(pPartition1->PartitionStyle == PARTITION_STYLE_MBR){
  460. if(pPartition1->Mbr.PartitionType != pPartition2->Mbr.PartitionType){
  461. return DiskInfoCmp_PartitionTypeHasChanged;
  462. }
  463. if(pPartition1->Mbr.BootIndicator != pPartition2->Mbr.BootIndicator){
  464. return DiskInfoCmp_PartitionAttributesHasChanged;
  465. }
  466. if(pPartition1->Mbr.RecognizedPartition != pPartition2->Mbr.RecognizedPartition){
  467. return DiskInfoCmp_PartitionAttributesHasChanged;
  468. }
  469. if(pPartition1->Mbr.HiddenSectors != pPartition2->Mbr.HiddenSectors){
  470. return DiskInfoCmp_PartitionAttributesHasChanged;
  471. }
  472. }
  473. else if(pPartition1->PartitionStyle == PARTITION_STYLE_GPT){
  474. if(memcmp(&pPartition1->Gpt, &pPartition2->Gpt, sizeof(pPartition1->Mbr))){
  475. return DiskInfoCmp_PartitionAttributesHasChanged;
  476. }
  477. }
  478. }
  479. return DiskInfoCmp_Equal;
  480. }
  481. BOOL
  482. CompareDisksInfo(
  483. IN DISKINFO * FirstInfo,
  484. IN DISKINFO * SecondInfo,
  485. IN UINT DiskInfoCount,
  486. OUT PDISKINFO_COMPARATION_STATUS OutDiskCmpStatus, OPTIONAL
  487. OUT UINT * OutIfFailedDiskInfoIndex OPTIONAL
  488. )
  489. {
  490. UINT i;
  491. DISKINFO_COMPARATION_STATUS cmpStatus;
  492. if(!FirstInfo || !SecondInfo || !DiskInfoCount){
  493. MYASSERT(FALSE);
  494. return FALSE;
  495. }
  496. for(i = 0; i < DiskInfoCount; i++){
  497. cmpStatus = CompareDiskInfo(FirstInfo++, SecondInfo++);
  498. if(DiskInfoCmp_Equal != cmpStatus){
  499. if(OutDiskCmpStatus){
  500. *OutDiskCmpStatus = cmpStatus;
  501. }
  502. if(OutIfFailedDiskInfoIndex){
  503. *OutIfFailedDiskInfoIndex = i;
  504. }
  505. return FALSE;
  506. }
  507. }
  508. return TRUE;
  509. }
  510. BOOL
  511. IsFloppyDiskInDrive(
  512. VOID
  513. )
  514. {
  515. WCHAR Drive[] = L"?:\\";
  516. WCHAR DriveNT[] = L"\\\\.\\?:";
  517. UINT i;
  518. HANDLE hDiskDrive;
  519. BOOL bDiskInDrive = FALSE;
  520. BOOL bResult;
  521. DISK_GEOMETRY diskGeometry;
  522. DWORD bytesReturned;
  523. DWORD Drives;
  524. for(i = 0, Drives = 0x7/*GetLogicalDrives()*/; Drives; Drives >>= 1, i++){
  525. if(!(Drives&1)){
  526. continue;
  527. }
  528. Drive[0] = 'A' + i;
  529. if(DRIVE_REMOVABLE != GetDriveTypeW(Drive)){
  530. continue;
  531. }
  532. DriveNT[4] = Drive[0];
  533. while(1){
  534. hDiskDrive = CreateFileW(DriveNT,
  535. GENERIC_READ,
  536. FILE_SHARE_READ | FILE_SHARE_WRITE,
  537. NULL,
  538. OPEN_EXISTING,
  539. 0,
  540. NULL);
  541. if(INVALID_HANDLE_VALUE == hDiskDrive){
  542. break;
  543. }
  544. bResult = DeviceIoControl(hDiskDrive,
  545. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  546. NULL,
  547. 0,
  548. &diskGeometry,
  549. sizeof(diskGeometry),
  550. &bytesReturned,
  551. NULL);
  552. CloseHandle(hDiskDrive);
  553. if(bResult){
  554. bDiskInDrive = diskGeometry.MediaType != Unknown &&
  555. diskGeometry.MediaType != RemovableMedia &&
  556. diskGeometry.MediaType != FixedMedia;
  557. break;
  558. }
  559. if(ERROR_MEDIA_CHANGED != GetLastError()){
  560. break;
  561. }
  562. }
  563. if(bDiskInDrive){
  564. break;
  565. }
  566. }
  567. return bDiskInDrive;
  568. }
  569. BOOL
  570. GetHardDiskNumberW(
  571. IN WCHAR DriveLetter,
  572. OUT UINT * HarddiskNumberOut
  573. )
  574. {
  575. WCHAR driveName[] = L"\\\\.\\?:";
  576. HANDLE hDisk;
  577. STORAGE_DEVICE_NUMBER deviceNumber;
  578. BOOL bResult;
  579. DWORD dwBytesReturned;
  580. driveName[4] = DriveLetter;
  581. hDisk = CreateFileW(driveName,
  582. GENERIC_READ,
  583. FILE_SHARE_READ | FILE_SHARE_WRITE,
  584. NULL,
  585. OPEN_EXISTING,
  586. 0,
  587. NULL);
  588. if(INVALID_HANDLE_VALUE == hDisk){
  589. return FALSE;
  590. }
  591. bResult = DeviceIoControl(hDisk,
  592. IOCTL_STORAGE_GET_DEVICE_NUMBER,
  593. NULL,
  594. 0,
  595. &deviceNumber,
  596. sizeof(deviceNumber),
  597. &dwBytesReturned,
  598. NULL);
  599. CloseHandle(hDisk);
  600. if(!bResult){
  601. return FALSE;
  602. }
  603. if(HarddiskNumberOut){
  604. *HarddiskNumberOut = deviceNumber.DeviceNumber;
  605. }
  606. return TRUE;
  607. }