Source code of Windows XP (NT5)
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.

716 lines
19 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. wsprintf(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. AppendWack(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. wsprintf(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. AppendWack(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. BOOL
  206. GetDriveInfo(
  207. IN WCHAR Drive,
  208. IN OUT DRIVEINFO * pInfo
  209. )
  210. {
  211. WCHAR driveDosPath[] = L"?:\\";
  212. WCHAR driveDosDeviceVolumeMountPoint[MAX_PATH];
  213. BOOL result;
  214. if(!pInfo || !pInfo->FileSystemName || !pInfo->VolumeNTPath){
  215. SetLastError(ERROR_INVALID_PARAMETER);
  216. MYASSERT(FALSE);
  217. return FALSE;
  218. }
  219. pInfo->Drive = Drive;
  220. driveDosPath[0] = Drive;
  221. if(!GetVolumeNameForVolumeMountPointW(driveDosPath,
  222. driveDosDeviceVolumeMountPoint,
  223. ARRAYSIZE(driveDosDeviceVolumeMountPoint))){
  224. DEBUGMSGW((DBG_WARNING, "GetDiskInfo:GetVolumeNameForVolumeMountPoint(%s) failed", driveDosPath));
  225. SetLastError(ERROR_ACCESS_DENIED);
  226. return FALSE;
  227. }
  228. wcscpy((LPWSTR)pInfo->VolumeNTPath, driveDosDeviceVolumeMountPoint);
  229. result = GetVolumeInformationW(
  230. driveDosPath,
  231. NULL,
  232. 0,
  233. NULL,
  234. NULL,
  235. &pInfo->FileSystemFlags,
  236. (LPWSTR)pInfo->FileSystemName,
  237. MAX_PATH
  238. );
  239. if(!result && (GetLastError() == ERROR_UNRECOGNIZED_VOLUME)){
  240. wcscpy((LPWSTR)pInfo->FileSystemName, L"UNRECOGNIZED_VOLUME");
  241. result = TRUE;
  242. DEBUGMSGW((DBG_WARNING, "GetDiskInfo:GetVolumeInformation(%s):GetLastError() == ERROR_UNRECOGNIZED_VOLUME", driveDosPath));
  243. }
  244. DEBUGMSGW_IF((!result, DBG_ERROR, "GetDiskInfo:GetVolumeInformation(%s):GetLastError() == %d", driveDosPath, GetLastError()));
  245. return result;
  246. }
  247. BOOL
  248. GetIntegrityInfoW(
  249. IN PCWSTR FileName,
  250. IN PCWSTR DirPath,
  251. OUT FILEINTEGRITYINFO * IntegrityInfoPtr
  252. )
  253. {
  254. WCHAR pathFile[MAX_PATH];
  255. if(!FileName || !DirPath || !IntegrityInfoPtr){
  256. SetLastError(ERROR_INVALID_PARAMETER);
  257. MYASSERT(FALSE);
  258. return FALSE;
  259. }
  260. StringCopyW(pathFile, DirPath);
  261. StringCatW(AppendWackW(pathFile), FileName);
  262. StringCopyW((LPWSTR)IntegrityInfoPtr->FileName, FileName);
  263. if(!GetFileSizeFromFilePathW(pathFile, &IntegrityInfoPtr->FileSize)){
  264. return FALSE;
  265. }
  266. SetLastError(ERROR_SUCCESS);
  267. return TRUE;
  268. }
  269. BOOL
  270. GetDrivesInfo(
  271. IN OUT DRIVEINFO * pInfo,
  272. IN OUT UINT * pDiskInfoRealCount,
  273. IN UINT DiskInfoMaxCount
  274. )
  275. {
  276. UINT LogicalDrives;
  277. WCHAR DriveName[] = L"?:\\";
  278. UINT i;
  279. if(!pDiskInfoRealCount){
  280. SetLastError(ERROR_INVALID_PARAMETER);
  281. MYASSERT(FALSE);
  282. return FALSE;
  283. }
  284. if(!(LogicalDrives = GetLogicalDrives())) {
  285. return FALSE;
  286. }
  287. *pDiskInfoRealCount = 0;
  288. for(i = 0; LogicalDrives && ((*pDiskInfoRealCount) < DiskInfoMaxCount); LogicalDrives >>= 1, i++){
  289. if(LogicalDrives&1) {
  290. DriveName[0] = 'A' + (char)i;
  291. if(DRIVE_FIXED != GetDriveTypeW(DriveName)) {
  292. continue;
  293. }
  294. if(pInfo){
  295. if(!GetDriveInfo(DriveName[0], pInfo++)){
  296. MYASSERT(FALSE);
  297. return FALSE;
  298. }
  299. }
  300. (*pDiskInfoRealCount)++;
  301. }
  302. }
  303. SetLastError(ERROR_SUCCESS);
  304. return TRUE;
  305. }
  306. BOOL
  307. GetUndoDrivesInfo(
  308. OUT DRIVEINFO * pInfo,
  309. OUT UINT * pNumberOfDrive,
  310. IN WCHAR BootDrive,
  311. IN WCHAR SystemDrive,
  312. IN WCHAR UndoDrive
  313. )
  314. {
  315. if(!pInfo || !pNumberOfDrive){
  316. SetLastError(ERROR_INVALID_PARAMETER);
  317. MYASSERT(FALSE);
  318. return FALSE;
  319. }
  320. *pNumberOfDrive = 0;
  321. if(!GetDriveInfo(BootDrive, pInfo++)){
  322. MYASSERT(FALSE);
  323. return FALSE;
  324. }
  325. (*pNumberOfDrive)++;
  326. if(SystemDrive != BootDrive){
  327. if(!GetDriveInfo(SystemDrive, pInfo++)){
  328. MYASSERT(FALSE);
  329. return FALSE;
  330. }
  331. (*pNumberOfDrive)++;
  332. }
  333. if(UndoDrive != BootDrive && UndoDrive != SystemDrive){
  334. if(!GetDriveInfo(UndoDrive, pInfo++)){
  335. MYASSERT(FALSE);
  336. return FALSE;
  337. }
  338. (*pNumberOfDrive)++;
  339. }
  340. SetLastError(ERROR_SUCCESS);
  341. return TRUE;
  342. }
  343. DISKINFO_COMPARATION_STATUS
  344. CompareDriveInfo(
  345. IN DRIVEINFO * FirstInfo,
  346. IN DRIVEINFO * SecondInfo
  347. )
  348. {
  349. if(!FirstInfo || !SecondInfo){
  350. MYASSERT(FALSE);
  351. return DiskInfoCmp_WrongParameters;
  352. }
  353. if(towlower(FirstInfo->Drive) != towlower(SecondInfo->Drive)){
  354. return DiskInfoCmp_DifferentLetter;
  355. }
  356. MYASSERT(FirstInfo->FileSystemName && SecondInfo->FileSystemName);
  357. if(wcscmp(FirstInfo->FileSystemName, SecondInfo->FileSystemName)){
  358. return DiskInfoCmp_FileSystemHasChanged;
  359. }
  360. if(FirstInfo->FileSystemFlags != SecondInfo->FileSystemFlags){
  361. return DiskInfoCmp_FileSystemHasChanged;
  362. }
  363. MYASSERT(FirstInfo->VolumeNTPath && SecondInfo->VolumeNTPath);
  364. if(wcscmp(FirstInfo->VolumeNTPath, SecondInfo->VolumeNTPath)){
  365. return DiskInfoCmp_DriveMountPointHasChanged;
  366. }
  367. return DiskInfoCmp_Equal;
  368. }
  369. BOOL
  370. CompareDrivesInfo(
  371. IN DRIVEINFO * FirstInfo,
  372. IN DRIVEINFO * SecondInfo,
  373. IN UINT DriveInfoCount,
  374. OUT PDISKINFO_COMPARATION_STATUS OutDiskCmpStatus, OPTIONAL
  375. OUT UINT * OutIfFailedDiskInfoIndex OPTIONAL
  376. )
  377. {
  378. UINT i;
  379. DISKINFO_COMPARATION_STATUS cmpStatus;
  380. if(!FirstInfo || !SecondInfo || !DriveInfoCount){
  381. MYASSERT(FALSE);
  382. SetLastError(ERROR_INVALID_PARAMETER);
  383. return FALSE;
  384. }
  385. for(i = 0; i < DriveInfoCount; i++){
  386. cmpStatus = CompareDriveInfo(FirstInfo++, SecondInfo++);
  387. if(DiskInfoCmp_Equal != cmpStatus){
  388. if(OutDiskCmpStatus){
  389. *OutDiskCmpStatus = cmpStatus;
  390. }
  391. if(OutIfFailedDiskInfoIndex){
  392. *OutIfFailedDiskInfoIndex = i;
  393. }
  394. SetLastError(ERROR_ACCESS_DENIED);
  395. return FALSE;
  396. }
  397. }
  398. SetLastError(ERROR_SUCCESS);
  399. return TRUE;
  400. }
  401. DISKINFO_COMPARATION_STATUS
  402. CompareDiskInfo(
  403. IN DISKINFO * FirstInfo,
  404. IN DISKINFO * SecondInfo
  405. )
  406. {
  407. DWORD i, iLen;
  408. PARTITION_INFORMATION_EX * pPartition1;
  409. PARTITION_INFORMATION_EX * pPartition2;
  410. if(!FirstInfo || !SecondInfo || !FirstInfo->DiskLayout || !SecondInfo->DiskLayout){
  411. MYASSERT(FALSE);
  412. return DiskInfoCmp_WrongParameters;
  413. }
  414. //
  415. //DISK_GEOMETRY
  416. //
  417. if(memcmp(&FirstInfo->DiskGeometry, &SecondInfo->DiskGeometry, sizeof(FirstInfo->DiskGeometry))){
  418. return DiskInfoCmp_GeometryHasChanged;
  419. }
  420. //
  421. //DRIVE_LAYOUT_INFORMATION_EX
  422. //
  423. if(FirstInfo->DiskLayout->PartitionStyle != SecondInfo->DiskLayout->PartitionStyle){
  424. return DiskInfoCmp_PartitionStyleHasChanged;
  425. }
  426. if(FirstInfo->DiskLayout->PartitionCount != SecondInfo->DiskLayout->PartitionCount){
  427. return DiskInfoCmp_PartitionCountHasChanged;
  428. }
  429. //
  430. //PARTITION_INFORMATION
  431. //
  432. for(i = 0, iLen = FirstInfo->DiskLayout->PartitionCount; i < iLen; i++){
  433. pPartition1 = &FirstInfo->DiskLayout->PartitionEntry[i];
  434. pPartition2 = &SecondInfo->DiskLayout->PartitionEntry[i];
  435. if(pPartition1->PartitionStyle != pPartition2->PartitionStyle){
  436. return DiskInfoCmp_PartitionStyleHasChanged;
  437. }
  438. if(pPartition1->StartingOffset.QuadPart != pPartition2->StartingOffset.QuadPart){
  439. return DiskInfoCmp_PartitionPlaceHasChanged;
  440. }
  441. if(pPartition1->PartitionLength.QuadPart != pPartition2->PartitionLength.QuadPart){
  442. return DiskInfoCmp_PartitionLengthHasChanged;
  443. }
  444. if(pPartition1->PartitionNumber != pPartition2->PartitionNumber){
  445. return DiskInfoCmp_PartitionNumberHasChanged;
  446. }
  447. if(pPartition1->RewritePartition != pPartition2->RewritePartition){
  448. return DiskInfoCmp_RewritePartitionHasChanged;
  449. }
  450. if(pPartition1->PartitionStyle == PARTITION_STYLE_MBR){
  451. if(pPartition1->Mbr.PartitionType != pPartition2->Mbr.PartitionType){
  452. return DiskInfoCmp_PartitionTypeHasChanged;
  453. }
  454. if(pPartition1->Mbr.BootIndicator != pPartition2->Mbr.BootIndicator){
  455. return DiskInfoCmp_PartitionAttributesHasChanged;
  456. }
  457. if(pPartition1->Mbr.RecognizedPartition != pPartition2->Mbr.RecognizedPartition){
  458. return DiskInfoCmp_PartitionAttributesHasChanged;
  459. }
  460. if(pPartition1->Mbr.HiddenSectors != pPartition2->Mbr.HiddenSectors){
  461. return DiskInfoCmp_PartitionAttributesHasChanged;
  462. }
  463. }
  464. else if(pPartition1->PartitionStyle == PARTITION_STYLE_GPT){
  465. if(memcmp(&pPartition1->Gpt, &pPartition2->Gpt, sizeof(pPartition1->Mbr))){
  466. return DiskInfoCmp_PartitionAttributesHasChanged;
  467. }
  468. }
  469. }
  470. return DiskInfoCmp_Equal;
  471. }
  472. BOOL
  473. CompareDisksInfo(
  474. IN DISKINFO * FirstInfo,
  475. IN DISKINFO * SecondInfo,
  476. IN UINT DiskInfoCount,
  477. OUT PDISKINFO_COMPARATION_STATUS OutDiskCmpStatus, OPTIONAL
  478. OUT UINT * OutIfFailedDiskInfoIndex OPTIONAL
  479. )
  480. {
  481. UINT i;
  482. DISKINFO_COMPARATION_STATUS cmpStatus;
  483. if(!FirstInfo || !SecondInfo || !DiskInfoCount){
  484. MYASSERT(FALSE);
  485. return FALSE;
  486. }
  487. for(i = 0; i < DiskInfoCount; i++){
  488. cmpStatus = CompareDiskInfo(FirstInfo++, SecondInfo++);
  489. if(DiskInfoCmp_Equal != cmpStatus){
  490. if(OutDiskCmpStatus){
  491. *OutDiskCmpStatus = cmpStatus;
  492. }
  493. if(OutIfFailedDiskInfoIndex){
  494. *OutIfFailedDiskInfoIndex = i;
  495. }
  496. return FALSE;
  497. }
  498. }
  499. return TRUE;
  500. }
  501. BOOL
  502. IsFloppyDiskInDrive(
  503. VOID
  504. )
  505. {
  506. WCHAR Drive[] = L"?:\\";
  507. WCHAR DriveNT[] = L"\\\\.\\?:";
  508. UINT i;
  509. HANDLE hDiskDrive;
  510. BOOL bDiskInDrive = FALSE;
  511. BOOL bResult;
  512. DISK_GEOMETRY diskGeometry;
  513. DWORD bytesReturned;
  514. DWORD Drives;
  515. for(i = 0, Drives = 0x7/*GetLogicalDrives()*/; Drives; Drives >>= 1, i++){
  516. if(!(Drives&1)){
  517. continue;
  518. }
  519. Drive[0] = 'A' + i;
  520. if(DRIVE_REMOVABLE != GetDriveTypeW(Drive)){
  521. continue;
  522. }
  523. DriveNT[4] = Drive[0];
  524. while(1){
  525. hDiskDrive = CreateFileW(DriveNT,
  526. GENERIC_READ,
  527. FILE_SHARE_READ | FILE_SHARE_WRITE,
  528. NULL,
  529. OPEN_EXISTING,
  530. 0,
  531. NULL);
  532. if(INVALID_HANDLE_VALUE == hDiskDrive){
  533. break;
  534. }
  535. bResult = DeviceIoControl(hDiskDrive,
  536. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  537. NULL,
  538. 0,
  539. &diskGeometry,
  540. sizeof(diskGeometry),
  541. &bytesReturned,
  542. NULL);
  543. CloseHandle(hDiskDrive);
  544. if(bResult){
  545. bDiskInDrive = diskGeometry.MediaType != Unknown &&
  546. diskGeometry.MediaType != RemovableMedia &&
  547. diskGeometry.MediaType != FixedMedia;
  548. break;
  549. }
  550. if(ERROR_MEDIA_CHANGED != GetLastError()){
  551. break;
  552. }
  553. }
  554. if(bDiskInDrive){
  555. break;
  556. }
  557. }
  558. return bDiskInDrive;
  559. }
  560. BOOL
  561. GetHardDiskNumberW(
  562. IN WCHAR DriveLetter,
  563. OUT UINT * HarddiskNumberOut
  564. )
  565. {
  566. WCHAR driveName[] = L"\\\\.\\?:";
  567. HANDLE hDisk;
  568. STORAGE_DEVICE_NUMBER deviceNumber;
  569. BOOL bResult;
  570. DWORD dwBytesReturned;
  571. driveName[4] = DriveLetter;
  572. hDisk = CreateFileW(driveName,
  573. GENERIC_READ,
  574. FILE_SHARE_READ | FILE_SHARE_WRITE,
  575. NULL,
  576. OPEN_EXISTING,
  577. 0,
  578. NULL);
  579. if(INVALID_HANDLE_VALUE == hDisk){
  580. return FALSE;
  581. }
  582. bResult = DeviceIoControl(hDisk,
  583. IOCTL_STORAGE_GET_DEVICE_NUMBER,
  584. NULL,
  585. 0,
  586. &deviceNumber,
  587. sizeof(deviceNumber),
  588. &dwBytesReturned,
  589. NULL);
  590. CloseHandle(hDisk);
  591. if(!bResult){
  592. return FALSE;
  593. }
  594. if(HarddiskNumberOut){
  595. *HarddiskNumberOut = deviceNumber.DeviceNumber;
  596. }
  597. return TRUE;
  598. }