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.

4783 lines
115 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. disktest.c
  5. Abstract:
  6. Abstract
  7. Author:
  8. Rod Gamache (rodga) 4-Mar-1996
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #define INITGUID 1
  14. //#include <windows.h>
  15. #include <nt.h>
  16. #include <ntdef.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windows.h>
  20. #include <clusapi.h>
  21. #include <ntddvol.h>
  22. #include <mountie.h>
  23. #include <mountmgr.h>
  24. #include <partmgrp.h>
  25. #include <devioctl.h>
  26. #include <ntdddisk.h>
  27. #include <ntddscsi.h>
  28. #include <stdio.h>
  29. #include <stddef.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. //#include <initguid.h>
  33. #include <devguid.h>
  34. #include <setupapi.h>
  35. #include <cfgmgr32.h>
  36. #include "clusdisk.h"
  37. #include "disksp.h"
  38. #include "diskarbp.h"
  39. #ifndef ClusterHashGuid
  40. #define ClusterHashGuid(Guid) (((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[1] ^ ((PULONG) &Guid)[2] ^ ((PULONG) &Guid)[3])
  41. #endif
  42. NTSTATUS
  43. GetAssignedLetter (
  44. PWCHAR deviceName,
  45. PCHAR driveLetter
  46. );
  47. PVOID
  48. DoIoctlAndAllocate(
  49. IN HANDLE FileHandle,
  50. IN DWORD IoControlCode,
  51. IN PVOID InBuf,
  52. IN ULONG InBufSize,
  53. OUT PDWORD BytesReturned
  54. );
  55. VOID
  56. GetSymbolicLink(
  57. IN PCHAR RootName,
  58. IN OUT PCHAR ObjectName,
  59. IN PDISK_INFO DiskInfo
  60. );
  61. HANDLE
  62. OpenObject(
  63. LPSTR lpstrDirectory,
  64. LPSTR lpstrObject,
  65. PDISK_INFO DiskInfo
  66. );
  67. PSTR PartitionName = "\\Device\\Harddisk%d\\Partition%d";
  68. int __cdecl
  69. main(
  70. int argc,
  71. char *argv[]
  72. );
  73. static DWORD
  74. Reset(
  75. HANDLE fileHandle,
  76. int argc,
  77. char *argv[]
  78. );
  79. static DWORD
  80. Reserve(
  81. HANDLE fileHandle,
  82. int argc,
  83. char *argv[]
  84. );
  85. static DWORD
  86. Release(
  87. HANDLE fileHandle,
  88. int argc,
  89. char *argv[]
  90. );
  91. static DWORD
  92. Online(
  93. HANDLE fileHandle,
  94. int argc,
  95. char *argv[]
  96. );
  97. static DWORD
  98. Offline(
  99. HANDLE fileHandle,
  100. int argc,
  101. char *argv[]
  102. );
  103. DWORD
  104. Claim(
  105. HANDLE fileHandle,
  106. int argc,
  107. char *argv[]
  108. );
  109. DWORD
  110. EjectVolumes(
  111. HANDLE fileHandle,
  112. int argc,
  113. char *argv[]
  114. );
  115. DWORD
  116. PokeMountMgr (
  117. VOID
  118. );
  119. DWORD
  120. EnumMounts(
  121. HANDLE fileHandle,
  122. int argc,
  123. char *argv[]
  124. );
  125. DWORD
  126. EnumExtents(
  127. HANDLE fileHandle,
  128. int argc,
  129. char *argv[]
  130. );
  131. DWORD
  132. EnumNodes(
  133. HANDLE fileHandle,
  134. int argc,
  135. char *argv[]
  136. );
  137. DWORD
  138. EnumDisks(
  139. HANDLE fileHandle,
  140. int argc,
  141. char *argv[]
  142. );
  143. DWORD
  144. DisableNode(
  145. HANDLE fileHandle,
  146. int argc,
  147. char *argv[]
  148. );
  149. DWORD
  150. EnableNode(
  151. HANDLE fileHandle,
  152. int argc,
  153. char *argv[]
  154. );
  155. DWORD
  156. DisableDisk(
  157. HANDLE fileHandle,
  158. int argc,
  159. char *argv[]
  160. );
  161. DWORD
  162. EnableDisk(
  163. HANDLE fileHandle,
  164. int argc,
  165. char *argv[]
  166. );
  167. DWORD
  168. GetDiskGeometry(
  169. HANDLE fileHandle,
  170. int argc,
  171. char *argv[]
  172. );
  173. DWORD
  174. GetScsiAddress(
  175. HANDLE fileHandle,
  176. int argc,
  177. char *argv[]
  178. );
  179. DWORD
  180. GetDriveLayout(
  181. HANDLE fileHandle,
  182. int argc,
  183. char *argv[]
  184. );
  185. DWORD
  186. GetDriveLayoutEx(
  187. HANDLE fileHandle,
  188. int argc,
  189. char *argv[]
  190. );
  191. LPTSTR
  192. BooleanToString(
  193. BOOLEAN Value
  194. );
  195. void
  196. FormatGuid(
  197. GUID* Guid,
  198. char* Str
  199. );
  200. DWORD
  201. GetVolumeInfo(
  202. HANDLE fileHandle,
  203. int argc,
  204. char *argv[]
  205. );
  206. DWORD
  207. SetDriveLayout(
  208. HANDLE fileHandle,
  209. int argc,
  210. char *argv[]
  211. );
  212. DWORD
  213. Attach(
  214. HANDLE fileHandle,
  215. int argc,
  216. char *argv[]
  217. );
  218. DWORD
  219. Detach(
  220. HANDLE fileHandle,
  221. int argc,
  222. char *argv[]
  223. );
  224. DWORD
  225. HoldIO(
  226. HANDLE fileHandle,
  227. int argc,
  228. char *argv[]
  229. );
  230. DWORD
  231. ResumeIO(
  232. HANDLE fileHandle,
  233. int argc,
  234. char *argv[]
  235. );
  236. static DWORD
  237. GetPartitionInfo(
  238. HANDLE fileHandle,
  239. int argc,
  240. char *argv[]
  241. );
  242. BOOLEAN
  243. AssignDriveLetters(
  244. PDISK_INFO DiskInfo
  245. );
  246. DWORD
  247. AssignLetters(
  248. HANDLE fileHandle,
  249. int argc,
  250. char *argv[]
  251. );
  252. BOOLEAN
  253. RemoveDriveLetters(
  254. PDISK_INFO DiskInfo
  255. );
  256. DWORD
  257. RemoveLetters(
  258. HANDLE fileHandle,
  259. int argc,
  260. char *argv[]
  261. );
  262. DWORD
  263. ReadSector(
  264. HANDLE fileHandle,
  265. int argc,
  266. char *argv[]
  267. );
  268. DWORD
  269. ReadSectorViaIoctl(
  270. HANDLE fileHandle,
  271. int argc,
  272. char *argv[]
  273. );
  274. DWORD
  275. FixDisk(
  276. HANDLE fileHandle,
  277. int argc,
  278. char *argv[]
  279. );
  280. static DWORD
  281. FixDriveLayout(
  282. HANDLE fileHandle,
  283. int argc,
  284. char *argv[]
  285. );
  286. static DWORD
  287. StartReserve(
  288. HANDLE fileHandle,
  289. int argc,
  290. char *argv[]
  291. );
  292. static DWORD
  293. StopReserve(
  294. HANDLE fileHandle,
  295. int argc,
  296. char *argv[]
  297. );
  298. static DWORD
  299. Active(
  300. HANDLE fileHandle,
  301. int argc,
  302. char *argv[]
  303. );
  304. static DWORD
  305. NotClusterCapable(
  306. HANDLE fileHandle,
  307. int argc,
  308. char *argv[]
  309. );
  310. static DWORD
  311. Test(
  312. HANDLE fileHandle,
  313. int argc,
  314. char *argv[]
  315. );
  316. static DWORD
  317. Nt4Capable(
  318. HANDLE fileHandle,
  319. int argc,
  320. char *argv[]
  321. );
  322. static DWORD
  323. GetDriveLetter(
  324. PUCHAR deviceNameString
  325. );
  326. NTSTATUS
  327. GetVolumeInformationFromHandle(
  328. HANDLE Handle
  329. );
  330. VOID
  331. PrintError(
  332. IN DWORD ErrorCode
  333. );
  334. DWORD
  335. GetSerialNumber(
  336. HANDLE FileHandle
  337. );
  338. static void
  339. usage(
  340. char *programName
  341. );
  342. int
  343. ExecuteCommand(
  344. IN PSTR Command,
  345. IN int argc,
  346. IN char *argv[]
  347. );
  348. //
  349. // Global data
  350. //
  351. PSTR DeviceName;
  352. PSTR ProgramName;
  353. int __cdecl
  354. main(
  355. int argc,
  356. char *argv[]
  357. )
  358. /*++
  359. Routine Description:
  360. Description
  361. Arguments:
  362. None
  363. Return Value:
  364. None
  365. --*/
  366. {
  367. #define MAX_DEVICES 99
  368. DWORD logicalDrives;
  369. DWORD letter;
  370. DWORD index;
  371. PSTR command;
  372. UCHAR buffer[128];
  373. wchar_t * pBuffer;
  374. DWORD status;
  375. HANDLE handle;
  376. if (argc < 3)
  377. {
  378. usage( argv[0] );
  379. return -1;
  380. }
  381. argc--;
  382. ProgramName = *argv++; // skip program name
  383. argc--;
  384. DeviceName = *argv++;
  385. argc--;
  386. command = *argv++;
  387. if ( ( lstrcmpi( DeviceName, "*" ) == 0 ) ||
  388. ( lstrcmpi( DeviceName, "l*" ) == 0 ) ) {
  389. // this is a wildcard request for logical drives.
  390. logicalDrives = GetLogicalDrives();
  391. for ( index = 0; index < 27; index++ ) {
  392. letter = 'A' + index;
  393. if ( (logicalDrives & 1) ) {
  394. sprintf( buffer, "%c:", letter );
  395. printf( "\n ** For device ** %s\n", buffer );
  396. DeviceName = buffer;
  397. status = ExecuteCommand(
  398. command,
  399. argc,
  400. argv );
  401. // Don't stop on error.
  402. }
  403. logicalDrives = logicalDrives >> 1;
  404. } // for
  405. } else if ( lstrcmpi( DeviceName, "p*" ) == 0 ) {
  406. pBuffer = (wchar_t *)buffer;
  407. for ( index = 0; index < MAX_DEVICES; index++ ) {
  408. DWORD accessMode = GENERIC_READ;
  409. DWORD shareMode = FILE_SHARE_READ;
  410. wsprintfW( pBuffer, L"\\\\.\\PhysicalDrive%u", index );
  411. handle = CreateFileW(
  412. pBuffer,
  413. shareMode,
  414. shareMode,
  415. NULL,
  416. OPEN_EXISTING,
  417. 0,
  418. NULL );
  419. status = ERROR_INVALID_HANDLE;
  420. if ( handle != INVALID_HANDLE_VALUE ) {
  421. CloseHandle( handle );
  422. status = ERROR_SUCCESS;
  423. printf( "\n ** For device ** %ws\n", pBuffer );
  424. sprintf( buffer, "%ws", pBuffer );
  425. DeviceName = buffer;
  426. status = ExecuteCommand(
  427. command,
  428. argc,
  429. argv );
  430. if ( status != 0 ) {
  431. return( status );
  432. }
  433. }
  434. }
  435. } else {
  436. status = ExecuteCommand(
  437. command,
  438. argc,
  439. argv );
  440. }
  441. return(status);
  442. }
  443. int
  444. ExecuteCommand(
  445. IN PSTR Command,
  446. IN int argc,
  447. IN char *argv[]
  448. )
  449. {
  450. PSTR device;
  451. HANDLE fileHandle;
  452. DWORD accessMode, shareMode;
  453. DWORD errorCode;
  454. BOOL failed = FALSE;
  455. UCHAR deviceNameString[128];
  456. DWORD logicalDrives;
  457. DWORD letter;
  458. DWORD index;
  459. NTSTATUS ntStatus;
  460. ANSI_STRING objName;
  461. UNICODE_STRING unicodeName;
  462. OBJECT_ATTRIBUTES objAttributes;
  463. IO_STATUS_BLOCK ioStatusBlock;
  464. //
  465. // Note it is important to access the device with 0 access mode so that
  466. // the file open code won't do extra I/O to the device
  467. //
  468. shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  469. accessMode = GENERIC_READ | GENERIC_WRITE;
  470. strcpy(deviceNameString, "\\\\.\\");
  471. strcat(deviceNameString, DeviceName);
  472. fileHandle = CreateFile(deviceNameString,
  473. accessMode,
  474. shareMode,
  475. NULL,
  476. OPEN_EXISTING,
  477. 0,
  478. NULL);
  479. if ( fileHandle == INVALID_HANDLE_VALUE ) {
  480. errorCode = GetLastError();
  481. if ( (errorCode == ERROR_PATH_NOT_FOUND) ||
  482. (errorCode == ERROR_FILE_NOT_FOUND) ) {
  483. strcpy(deviceNameString, "\\Device\\");
  484. strcat(deviceNameString, DeviceName);
  485. RtlInitString(&objName, deviceNameString);
  486. ntStatus = RtlAnsiStringToUnicodeString( &unicodeName,
  487. &objName,
  488. TRUE );
  489. if ( !NT_SUCCESS(ntStatus) ) {
  490. printf("Error converting device name %s to unicode. Error: %lx\n",
  491. deviceNameString, ntStatus);
  492. return -1;
  493. }
  494. InitializeObjectAttributes( &objAttributes,
  495. &unicodeName,
  496. OBJ_CASE_INSENSITIVE,
  497. NULL,
  498. NULL );
  499. ntStatus = NtCreateFile( &fileHandle,
  500. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  501. &objAttributes,
  502. &ioStatusBlock,
  503. NULL,
  504. FILE_ATTRIBUTE_NORMAL,
  505. FILE_SHARE_READ | FILE_SHARE_WRITE,
  506. FILE_OPEN,
  507. 0,
  508. NULL,
  509. 0 );
  510. if ( !NT_SUCCESS(ntStatus) ) {
  511. failed = TRUE;
  512. }
  513. RtlFreeUnicodeString( &unicodeName );
  514. } else {
  515. printf("Error opening %s. Error: %d\n",
  516. deviceNameString, errorCode = GetLastError());
  517. PrintError(errorCode);
  518. return -1;
  519. }
  520. }
  521. if ( failed ) {
  522. strcpy(deviceNameString, "\\Device\\");
  523. strcat(deviceNameString, DeviceName);
  524. //strcat(deviceNameString, "\\Partition0");
  525. RtlInitString(&objName, deviceNameString);
  526. ntStatus = RtlAnsiStringToUnicodeString( &unicodeName,
  527. &objName,
  528. TRUE );
  529. if ( !NT_SUCCESS(ntStatus) ) {
  530. printf("Error converting device name %s to unicode. Error: %lx\n",
  531. deviceNameString, ntStatus);
  532. return -1;
  533. }
  534. InitializeObjectAttributes( &objAttributes,
  535. &unicodeName,
  536. OBJ_CASE_INSENSITIVE,
  537. NULL,
  538. NULL );
  539. ntStatus = NtCreateFile( &fileHandle,
  540. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  541. &objAttributes,
  542. &ioStatusBlock,
  543. NULL,
  544. FILE_ATTRIBUTE_NORMAL,
  545. FILE_SHARE_READ | FILE_SHARE_WRITE,
  546. FILE_OPEN,
  547. 0,
  548. NULL,
  549. 0 );
  550. if ( !NT_SUCCESS(ntStatus) ) {
  551. printf("Error opening device %ws. Error: %lx.\n",
  552. unicodeName.Buffer, ntStatus );
  553. return -1;
  554. }
  555. RtlFreeUnicodeString( &unicodeName );
  556. }
  557. //printf("Accessing %s ... \n", deviceNameString);
  558. if (!_stricmp( Command, "Reset" ))
  559. errorCode = Reset( fileHandle, argc, argv );
  560. else if (!_stricmp( Command, "Reserve" ))
  561. errorCode = Reserve( fileHandle, argc, argv );
  562. else if (!_stricmp( Command, "Release" ))
  563. errorCode = Release( fileHandle, argc, argv );
  564. else if (!_stricmp( Command, "Online" ))
  565. errorCode = Online( fileHandle, argc, argv );
  566. else if (!_stricmp( Command, "Offline" ))
  567. errorCode = Offline( fileHandle, argc, argv );
  568. else if (!_stricmp( Command, "HoldIO" ))
  569. errorCode = HoldIO( fileHandle, argc, argv );
  570. else if (!_stricmp( Command, "ResumeIO" ))
  571. errorCode = ResumeIO( fileHandle, argc, argv );
  572. else if (!_stricmp( Command, "Claim" ))
  573. errorCode = Claim( fileHandle, argc, argv );
  574. else if (!_stricmp( Command, "EjectVolumes" ))
  575. errorCode = EjectVolumes( fileHandle, argc, argv );
  576. else if (!_stricmp( Command, "PokeMountMgr" ))
  577. errorCode = PokeMountMgr();
  578. else if (!_stricmp( Command, "EnumMounts" ))
  579. errorCode = EnumMounts( fileHandle, argc, argv );
  580. else if (!_stricmp( Command, "EnumExtents" ))
  581. errorCode = EnumExtents( fileHandle, argc, argv );
  582. else if (!_stricmp( Command, "EnumNodes" ))
  583. errorCode = EnumNodes( fileHandle, argc, argv );
  584. else if (!_stricmp( Command, "EnumDisks" ))
  585. errorCode = EnumDisks( fileHandle, argc, argv );
  586. else if (!_stricmp( Command, "DisableNode" ))
  587. errorCode = DisableNode( fileHandle, argc, argv );
  588. else if (!_stricmp( Command, "EnableNode" ))
  589. errorCode = EnableNode( fileHandle, argc, argv );
  590. else if (!_stricmp( Command, "DisableDisk" ))
  591. errorCode = DisableDisk( fileHandle, argc, argv );
  592. else if (!_stricmp( Command, "EnableDisk" ))
  593. errorCode = EnableDisk( fileHandle, argc, argv );
  594. else if (!_stricmp( Command, "GetDiskGeometry" ))
  595. errorCode = GetDiskGeometry( fileHandle, argc, argv );
  596. else if (!_stricmp( Command, "GetScsiAddress" ))
  597. errorCode = GetScsiAddress( fileHandle, argc, argv );
  598. else if (!_stricmp( Command, "GetVolumeInfo" ))
  599. errorCode = GetVolumeInfo( fileHandle, argc, argv );
  600. else if (!_stricmp( Command, "GetDriveLayout" ))
  601. errorCode = GetDriveLayout( fileHandle, argc, argv );
  602. else if (!_stricmp( Command, "GetDriveLayoutEx" ))
  603. errorCode = GetDriveLayoutEx( fileHandle, argc, argv );
  604. else if (!_stricmp( Command, "SetDriveLayout" ))
  605. errorCode = SetDriveLayout( fileHandle, argc, argv );
  606. else if (!_stricmp( Command, "GetPartitionInfo" ))
  607. errorCode = GetPartitionInfo( fileHandle, argc, argv );
  608. else if (!_stricmp( Command, "AssignLetters" ))
  609. errorCode = AssignLetters( fileHandle, argc, argv );
  610. else if (!_stricmp( Command, "RemoveLetters" ))
  611. errorCode = RemoveLetters( fileHandle, argc, argv );
  612. else if (!_stricmp( Command, "ReadSector" ))
  613. errorCode = ReadSector( fileHandle, argc, argv );
  614. else if (!_stricmp( Command, "rs" ))
  615. errorCode = ReadSectorViaIoctl( fileHandle, argc, argv );
  616. else if (!_stricmp( Command, "Attach" ))
  617. errorCode = Attach( fileHandle, argc, argv );
  618. else if (!_stricmp( Command, "Detach" ))
  619. errorCode = Detach( fileHandle, argc, argv );
  620. else if (!_stricmp( Command, "FixDisk" ))
  621. errorCode = FixDisk( fileHandle, argc, argv );
  622. else if (!_stricmp( Command, "FixDriveLayout" ))
  623. errorCode = FixDriveLayout( fileHandle, argc, argv );
  624. else if (!_stricmp( Command, "StartReserve" ))
  625. errorCode = StartReserve( fileHandle, argc, argv );
  626. else if (!_stricmp( Command, "StopReserve" ))
  627. errorCode = StopReserve( fileHandle, argc, argv );
  628. else if (!_stricmp( Command, "Test" ))
  629. errorCode = Test( fileHandle, argc, argv );
  630. else if (!_stricmp( Command, "NT4Capable" ))
  631. errorCode = Nt4Capable( fileHandle, argc, argv );
  632. else if (!_stricmp( Command, "Active"))
  633. errorCode = Active( fileHandle, argc, argv );
  634. else if (!_stricmp( Command, "Capable"))
  635. errorCode = NotClusterCapable( fileHandle, argc, argv );
  636. else if (!_stricmp( Command, "GetDriveLetter"))
  637. errorCode = GetDriveLetter( deviceNameString );
  638. else if (!_stricmp( Command, "GetSerialNumber"))
  639. errorCode = GetSerialNumber( fileHandle );
  640. else
  641. {
  642. printf( "Invalid command.\n" );
  643. CloseHandle( fileHandle );
  644. usage( ProgramName );
  645. return(-1);
  646. }
  647. CloseHandle( fileHandle );
  648. if (errorCode != ERROR_SUCCESS) {
  649. printf( "Error performing %s:, error %u.\n", Command, errorCode );
  650. PrintError(errorCode);
  651. printf( "%s: failed.\n", ProgramName );
  652. return(-1);
  653. } else
  654. return(0);
  655. }
  656. static DWORD
  657. Reset(
  658. HANDLE fileHandle,
  659. int argc,
  660. char *argv[]
  661. )
  662. /*++
  663. Routine Description:
  664. Description
  665. Arguments:
  666. None
  667. Return Value:
  668. None
  669. --*/
  670. {
  671. BOOL success;
  672. DWORD errorCode, bytesReturned;
  673. SCSI_PASS_THROUGH scsiBlock;
  674. SCSI_ADDRESS scsiAddress;
  675. STORAGE_BUS_RESET_REQUEST storageReset;
  676. if (argc != 0)
  677. {
  678. printf( "usage: <device> Reset\n" );
  679. return ERROR_INVALID_NAME;
  680. }
  681. success = DeviceIoControl(fileHandle,
  682. IOCTL_SCSI_GET_ADDRESS,
  683. NULL,
  684. 0,
  685. &scsiAddress,
  686. sizeof(SCSI_ADDRESS),
  687. &bytesReturned,
  688. FALSE );
  689. if ( !success ||
  690. bytesReturned < sizeof(DWORD) ) {
  691. printf( "Error reading SCSI address, error = %d\n",
  692. errorCode = GetLastError());
  693. PrintError(errorCode);
  694. return errorCode;
  695. }
  696. scsiBlock.PathId = scsiAddress.PathId;
  697. scsiBlock.TargetId = scsiAddress.TargetId;
  698. scsiBlock.Lun = 0;
  699. scsiBlock.Length = sizeof(SCSI_PASS_THROUGH);
  700. success = DeviceIoControl(fileHandle,
  701. IOCTL_DISK_CLUSTER_RESET_BUS,
  702. &scsiBlock,
  703. sizeof(SCSI_PASS_THROUGH),
  704. NULL,
  705. 0,
  706. &bytesReturned,
  707. FALSE);
  708. if (!success) {
  709. storageReset.PathId = scsiAddress.PathId;
  710. success = DeviceIoControl(fileHandle,
  711. IOCTL_STORAGE_RESET_BUS,
  712. &storageReset,
  713. sizeof(STORAGE_BUS_RESET_REQUEST),
  714. NULL,
  715. 0,
  716. &bytesReturned,
  717. FALSE);
  718. if (!success) {
  719. printf( "Error performing bus reset; error was %d\n",
  720. errorCode = GetLastError());
  721. PrintError(errorCode);
  722. return errorCode;
  723. }
  724. }
  725. return ERROR_SUCCESS;
  726. }
  727. static DWORD
  728. Test(
  729. HANDLE fileHandle,
  730. int argc,
  731. char *argv[]
  732. )
  733. /*++
  734. Routine Description:
  735. Description
  736. Arguments:
  737. None
  738. Return Value:
  739. None
  740. --*/
  741. {
  742. BOOL success;
  743. DWORD errorCode, bytesReturned;
  744. if (argc != 0)
  745. {
  746. printf( "usage: <device> Test\n" );
  747. return ERROR_INVALID_NAME;
  748. }
  749. success = DeviceIoControl(fileHandle,
  750. IOCTL_DISK_CLUSTER_TEST,
  751. NULL,
  752. 0,
  753. NULL,
  754. 0,
  755. &bytesReturned,
  756. FALSE);
  757. if (!success)
  758. {
  759. printf( "Error performing test; error was %d\n",
  760. errorCode = GetLastError());
  761. PrintError(errorCode);
  762. return errorCode;
  763. }
  764. return ERROR_SUCCESS;
  765. }
  766. static DWORD
  767. Nt4Capable(
  768. HANDLE fileHandle,
  769. int argc,
  770. char *argv[]
  771. )
  772. /*++
  773. Routine Description:
  774. Description
  775. Arguments:
  776. None
  777. Return Value:
  778. None
  779. --*/
  780. {
  781. BOOL success;
  782. DWORD errorCode, bytesReturned;
  783. if (argc != 0)
  784. {
  785. printf( "usage: <device> NT4Capable\n" );
  786. return ERROR_INVALID_NAME;
  787. }
  788. success = DeviceIoControl(fileHandle,
  789. IOCTL_DISK_CLUSTER_NT4_CAPABLE,
  790. NULL,
  791. 0,
  792. NULL,
  793. 0,
  794. &bytesReturned,
  795. FALSE);
  796. if (!success)
  797. {
  798. printf( "Error performing NT4Capable; error was %d\n",
  799. errorCode = GetLastError());
  800. PrintError(errorCode);
  801. return errorCode;
  802. }
  803. return ERROR_SUCCESS;
  804. }
  805. static DWORD
  806. NotClusterCapable(
  807. HANDLE fileHandle,
  808. int argc,
  809. char *argv[]
  810. )
  811. /*++
  812. Routine Description:
  813. Description
  814. Arguments:
  815. None
  816. Return Value:
  817. None
  818. --*/
  819. {
  820. BOOL success;
  821. DWORD errorCode, bytesReturned;
  822. if (argc != 0)
  823. {
  824. printf( "usage: <device> Capable\n" );
  825. return ERROR_INVALID_NAME;
  826. }
  827. success = DeviceIoControl(fileHandle,
  828. IOCTL_DISK_CLUSTER_NOT_CLUSTER_CAPABLE,
  829. NULL,
  830. 0,
  831. NULL,
  832. 0,
  833. &bytesReturned,
  834. FALSE);
  835. if (!success)
  836. {
  837. printf( "Error performing Capable; error was %d\n",
  838. errorCode = GetLastError());
  839. PrintError(errorCode);
  840. return errorCode;
  841. }
  842. return ERROR_SUCCESS;
  843. }
  844. static DWORD
  845. StartReserve(
  846. HANDLE fileHandle,
  847. int argc,
  848. char *argv[]
  849. )
  850. /*++
  851. Routine Description:
  852. Description
  853. Arguments:
  854. None
  855. Return Value:
  856. None
  857. --*/
  858. {
  859. BOOL success;
  860. DWORD errorCode, bytesReturned;
  861. DWORD signature;
  862. STRING ansiString;
  863. UNICODE_STRING numberString;
  864. if (argc != 1)
  865. {
  866. printf( "usage: <device> StartReserve <device signature>\n" );
  867. return ERROR_INVALID_NAME;
  868. }
  869. RtlInitAnsiString( &ansiString, *argv );
  870. printf(" Ansi string for signature is %s\n",
  871. ansiString.Buffer );
  872. RtlAnsiStringToUnicodeString(
  873. &numberString,
  874. &ansiString,
  875. TRUE );
  876. errorCode = RtlUnicodeStringToInteger(
  877. &numberString,
  878. 16,
  879. &signature );
  880. RtlFreeUnicodeString( &numberString );
  881. if ( !NT_SUCCESS(errorCode) ) {
  882. printf( "Error converting signature to hex number, NT status %u.\n",
  883. errorCode );
  884. return(errorCode);
  885. }
  886. success = DeviceIoControl(fileHandle,
  887. IOCTL_DISK_CLUSTER_START_RESERVE,
  888. &signature,
  889. sizeof(DWORD),
  890. NULL,
  891. 0,
  892. &bytesReturned,
  893. FALSE);
  894. if (!success)
  895. {
  896. printf( "Error performing StartReserve; error was %d\n",
  897. errorCode = GetLastError());
  898. PrintError(errorCode);
  899. return errorCode;
  900. }
  901. return ERROR_SUCCESS;
  902. }
  903. static DWORD
  904. StopReserve(
  905. HANDLE fileHandle,
  906. int argc,
  907. char *argv[]
  908. )
  909. /*++
  910. Routine Description:
  911. Description
  912. Arguments:
  913. None
  914. Return Value:
  915. None
  916. --*/
  917. {
  918. BOOL success;
  919. DWORD errorCode, bytesReturned;
  920. if (argc != 0)
  921. {
  922. printf( "usage: <device> StopReserve\n" );
  923. return ERROR_INVALID_NAME;
  924. }
  925. success = DeviceIoControl(fileHandle,
  926. IOCTL_DISK_CLUSTER_STOP_RESERVE,
  927. NULL,
  928. 0,
  929. NULL,
  930. 0,
  931. &bytesReturned,
  932. FALSE);
  933. if (!success)
  934. {
  935. printf( "Error performing StopReserve; error was %d\n",
  936. errorCode = GetLastError());
  937. PrintError(errorCode);
  938. return errorCode;
  939. }
  940. return ERROR_SUCCESS;
  941. }
  942. static DWORD
  943. Active(
  944. HANDLE fileHandle,
  945. int argc,
  946. char *argv[]
  947. )
  948. /*++
  949. Routine Description:
  950. Description
  951. Arguments:
  952. None
  953. Return Value:
  954. None
  955. --*/
  956. {
  957. BOOL success;
  958. DWORD errorCode, bytesReturned;
  959. DWORD signatures[100];
  960. DWORD number;
  961. DWORD i;
  962. if (argc != 0)
  963. {
  964. printf( "usage: <device> Active\n" );
  965. return ERROR_INVALID_NAME;
  966. }
  967. success = DeviceIoControl(fileHandle,
  968. IOCTL_DISK_CLUSTER_ACTIVE,
  969. NULL,
  970. 0,
  971. signatures,
  972. sizeof(signatures),
  973. &bytesReturned,
  974. FALSE);
  975. if (!success)
  976. {
  977. printf( "Error performing active; error was %d\n",
  978. errorCode = GetLastError());
  979. PrintError(errorCode);
  980. return errorCode;
  981. }
  982. printf(" List of signatures:\n\n");
  983. number = signatures[0];
  984. for ( i = 1; i <= number; i++ ) {
  985. printf("\t%08lX\n", signatures[i]);
  986. }
  987. printf("\n");
  988. return ERROR_SUCCESS;
  989. }
  990. static DWORD
  991. Reserve(
  992. HANDLE fileHandle,
  993. int argc,
  994. char *argv[]
  995. )
  996. /*++
  997. Routine Description:
  998. Description
  999. Arguments:
  1000. None
  1001. Return Value:
  1002. None
  1003. --*/
  1004. {
  1005. BOOL success;
  1006. DWORD errorCode, bytesReturned;
  1007. SCSI_PASS_THROUGH scsiBlock;
  1008. if (argc != 0)
  1009. {
  1010. printf( "usage: <device> Reserve\n" );
  1011. return ERROR_INVALID_NAME;
  1012. }
  1013. scsiBlock.PathId = 1;
  1014. scsiBlock.TargetId = 3;
  1015. scsiBlock.Lun = 0;
  1016. scsiBlock.Length = sizeof(SCSI_PASS_THROUGH);
  1017. success = DeviceIoControl(fileHandle,
  1018. IOCTL_DISK_RESERVE,
  1019. &scsiBlock,
  1020. sizeof(SCSI_PASS_THROUGH),
  1021. &scsiBlock,
  1022. sizeof(SCSI_PASS_THROUGH),
  1023. &bytesReturned,
  1024. FALSE);
  1025. errorCode = GetLastError();
  1026. if ( errorCode == ERROR_NOT_READY ) {
  1027. success = DeviceIoControl(fileHandle,
  1028. IOCTL_DISK_CLUSTER_RESERVE,
  1029. &scsiBlock,
  1030. sizeof(SCSI_PASS_THROUGH),
  1031. &scsiBlock,
  1032. sizeof(SCSI_PASS_THROUGH),
  1033. &bytesReturned,
  1034. FALSE);
  1035. }
  1036. if (!success) {
  1037. errorCode = GetLastError();
  1038. printf( "Error performing reserve; error was %d\n",
  1039. errorCode);
  1040. PrintError(errorCode);
  1041. return errorCode;
  1042. }
  1043. return ERROR_SUCCESS;
  1044. } // Reserve
  1045. static DWORD
  1046. Release(
  1047. HANDLE fileHandle,
  1048. int argc,
  1049. char *argv[]
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. Description
  1054. Arguments:
  1055. None
  1056. Return Value:
  1057. None
  1058. --*/
  1059. {
  1060. BOOL success;
  1061. DWORD errorCode, bytesReturned;
  1062. SCSI_PASS_THROUGH scsiBlock;
  1063. if (argc != 0)
  1064. {
  1065. printf( "usage: <device> Release\n" );
  1066. return ERROR_INVALID_NAME;
  1067. }
  1068. scsiBlock.PathId = 1;
  1069. scsiBlock.TargetId = 3;
  1070. scsiBlock.Lun = 0;
  1071. scsiBlock.Length = sizeof(SCSI_PASS_THROUGH);
  1072. success = DeviceIoControl(fileHandle,
  1073. IOCTL_DISK_RELEASE,
  1074. &scsiBlock,
  1075. sizeof(SCSI_PASS_THROUGH),
  1076. &scsiBlock,
  1077. sizeof(SCSI_PASS_THROUGH),
  1078. &bytesReturned,
  1079. FALSE);
  1080. if (!success)
  1081. {
  1082. printf( "Error performing release; error was %d\n",
  1083. errorCode = GetLastError());
  1084. PrintError(errorCode);
  1085. return errorCode;
  1086. }
  1087. return ERROR_SUCCESS;
  1088. } // Release
  1089. static DWORD
  1090. Online(
  1091. HANDLE fileHandle,
  1092. int argc,
  1093. char *argv[]
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. Description
  1098. Arguments:
  1099. None
  1100. Return Value:
  1101. None
  1102. --*/
  1103. {
  1104. BOOL success;
  1105. DWORD errorCode, bytesReturned;
  1106. UCHAR newState;
  1107. UCHAR oldState;
  1108. if (argc != 0)
  1109. {
  1110. printf( "usage: <device> Online\n" );
  1111. return ERROR_INVALID_NAME;
  1112. }
  1113. newState = DiskOnline;
  1114. success = DeviceIoControl(fileHandle,
  1115. IOCTL_DISK_CLUSTER_SET_STATE,
  1116. &newState,
  1117. sizeof(newState),
  1118. &oldState,
  1119. sizeof(oldState),
  1120. &bytesReturned,
  1121. FALSE);
  1122. if (!success)
  1123. {
  1124. printf( "Error performing Online; error was %d\n",
  1125. errorCode = GetLastError());
  1126. PrintError(errorCode);
  1127. return errorCode;
  1128. }
  1129. return ERROR_SUCCESS;
  1130. } // Online
  1131. static DWORD
  1132. Offline(
  1133. HANDLE fileHandle,
  1134. int argc,
  1135. char *argv[]
  1136. )
  1137. /*++
  1138. Routine Description:
  1139. Description
  1140. Arguments:
  1141. None
  1142. Return Value:
  1143. None
  1144. --*/
  1145. {
  1146. BOOL success;
  1147. DWORD errorCode;
  1148. DWORD newState;
  1149. DWORD oldState;
  1150. DWORD bytesReturned;
  1151. if (argc != 0)
  1152. {
  1153. printf( "usage: <device> Offline\n" );
  1154. return ERROR_INVALID_NAME;
  1155. }
  1156. newState = DiskOffline;
  1157. success = DeviceIoControl(fileHandle,
  1158. IOCTL_DISK_CLUSTER_SET_STATE,
  1159. &newState,
  1160. sizeof(newState),
  1161. &oldState,
  1162. sizeof(oldState),
  1163. &bytesReturned,
  1164. FALSE);
  1165. if (!success)
  1166. {
  1167. printf( "Error performing Offline; error was %d\n",
  1168. errorCode = GetLastError());
  1169. PrintError(errorCode);
  1170. return errorCode;
  1171. }
  1172. return ERROR_SUCCESS;
  1173. } // Offline
  1174. DWORD
  1175. Claim(
  1176. HANDLE fileHandle,
  1177. int argc,
  1178. char *argv[]
  1179. )
  1180. /*++
  1181. Routine Description:
  1182. Description
  1183. Arguments:
  1184. None
  1185. Return Value:
  1186. None
  1187. --*/
  1188. {
  1189. BOOL success;
  1190. DWORD errorCode;
  1191. DWORD bytesReturned;
  1192. if (argc != 0)
  1193. {
  1194. printf( "usage: <device> Claim \n" );
  1195. return ERROR_INVALID_NAME;
  1196. }
  1197. success = DeviceIoControl(fileHandle,
  1198. IOCTL_PARTMGR_CHECK_UNCLAIMED_PARTITIONS,
  1199. NULL,
  1200. 0,
  1201. NULL,
  1202. 0,
  1203. &bytesReturned,
  1204. FALSE);
  1205. if (!success)
  1206. {
  1207. printf( "Error performing Claim; error was %d\n",
  1208. errorCode = GetLastError());
  1209. PrintError(errorCode);
  1210. return errorCode;
  1211. }
  1212. return ERROR_SUCCESS;
  1213. } // Claim
  1214. DWORD
  1215. EjectVolumes(
  1216. HANDLE fileHandle,
  1217. int argc,
  1218. char *argv[]
  1219. )
  1220. /*++
  1221. Routine Description:
  1222. Description
  1223. Arguments:
  1224. None
  1225. Return Value:
  1226. None
  1227. --*/
  1228. {
  1229. BOOL success;
  1230. DWORD errorCode;
  1231. DWORD bytesReturned;
  1232. if (argc != 0)
  1233. {
  1234. printf( "usage: <PhysicalDriveX> EjectVolumes \n" );
  1235. return ERROR_INVALID_NAME;
  1236. }
  1237. success = DeviceIoControl(fileHandle,
  1238. IOCTL_PARTMGR_EJECT_VOLUME_MANAGERS,
  1239. NULL,
  1240. 0,
  1241. NULL,
  1242. 0,
  1243. &bytesReturned,
  1244. FALSE);
  1245. if (!success)
  1246. {
  1247. printf( "Error performing EjectVolumes; error was %d\n",
  1248. errorCode = GetLastError());
  1249. PrintError(errorCode);
  1250. return errorCode;
  1251. }
  1252. return ERROR_SUCCESS;
  1253. } // EjectVolumes
  1254. DWORD
  1255. EnumMounts(
  1256. HANDLE fileHandle,
  1257. int argc,
  1258. char *argv[]
  1259. )
  1260. /*++
  1261. Routine Description:
  1262. Description
  1263. Arguments:
  1264. None
  1265. Return Value:
  1266. None
  1267. --*/
  1268. {
  1269. BOOL success;
  1270. DWORD status;
  1271. DWORD bytesReturned;
  1272. HANDLE handle;
  1273. HANDLE mHandle;
  1274. DWORD i;
  1275. DWORD signature;
  1276. UCHAR uniqueId[MAX_PATH];
  1277. DWORD idLength;
  1278. STRING ansiString;
  1279. UNICODE_STRING numberString;
  1280. UCHAR volumeName[MAX_PATH];
  1281. UCHAR driveLetter;
  1282. if (argc > 1)
  1283. {
  1284. printf( "usage: <any_device> EnumMounts [signature]\n" );
  1285. return ERROR_INVALID_NAME;
  1286. }
  1287. if ( argc == 1 ) {
  1288. RtlInitAnsiString( &ansiString, *argv );
  1289. printf(" Ansi string for signature is %s\n",
  1290. ansiString.Buffer );
  1291. RtlAnsiStringToUnicodeString(
  1292. &numberString,
  1293. &ansiString,
  1294. TRUE );
  1295. status = RtlUnicodeStringToInteger(
  1296. &numberString,
  1297. 16,
  1298. &signature );
  1299. RtlFreeUnicodeString( &numberString );
  1300. if ( !NT_SUCCESS(status) ) {
  1301. printf( "Error converting signature to hex number, NT status %u.\n",
  1302. status );
  1303. return(status);
  1304. }
  1305. } else {
  1306. signature = 0;
  1307. }
  1308. status = DevfileOpen( &mHandle, MOUNTMGR_DEVICE_NAME );
  1309. if ( status != ERROR_SUCCESS ) {
  1310. printf( "DevfileOpen failed for %s, status = %u\n",
  1311. MOUNTMGR_DEVICE_NAME, status );
  1312. return status;
  1313. }
  1314. idLength = MAX_PATH;
  1315. status = FindFirstVolumeForSignature( mHandle,
  1316. signature,
  1317. volumeName,
  1318. MAX_PATH,
  1319. &handle,
  1320. uniqueId,
  1321. &idLength,
  1322. &driveLetter );
  1323. if ( status != ERROR_SUCCESS ) {
  1324. DevfileClose( mHandle );
  1325. if ( status == ERROR_NO_MORE_FILES ) {
  1326. status = ERROR_SUCCESS;
  1327. } else {
  1328. printf( "FindFirstVolume failed, status = %u\n", status );
  1329. }
  1330. return status;
  1331. }
  1332. i = 1;
  1333. while ( status == ERROR_SUCCESS ) {
  1334. printf( "Found match for volume %s\n", volumeName );
  1335. i++;
  1336. idLength = MAX_PATH;
  1337. status = FindNextVolumeForSignature( mHandle,
  1338. signature,
  1339. handle,
  1340. volumeName,
  1341. MAX_PATH,
  1342. uniqueId,
  1343. &idLength,
  1344. &driveLetter );
  1345. }
  1346. FindVolumeClose( handle );
  1347. DevfileClose( mHandle );
  1348. return ERROR_SUCCESS;
  1349. } // EnumMounts
  1350. DWORD
  1351. EnumExtents(
  1352. HANDLE fileHandle,
  1353. int argc,
  1354. char *argv[]
  1355. )
  1356. /*++
  1357. Routine Description:
  1358. Description
  1359. Arguments:
  1360. None
  1361. Return Value:
  1362. None
  1363. --*/
  1364. {
  1365. BOOL success;
  1366. DWORD status;
  1367. DWORD bytesReturned;
  1368. DWORD diskExtentSize;
  1369. PVOLUME_DISK_EXTENTS diskExtents;
  1370. DWORD i;
  1371. if (argc != 0)
  1372. {
  1373. printf( "usage: <device> EnumExtents\n" );
  1374. return ERROR_INVALID_NAME;
  1375. }
  1376. diskExtentSize = sizeof(VOLUME_DISK_EXTENTS);
  1377. diskExtents = LocalAlloc( LMEM_FIXED, diskExtentSize);
  1378. if ( !diskExtents ) {
  1379. return(ERROR_NOT_ENOUGH_MEMORY);
  1380. }
  1381. //
  1382. // Get volume information for disk extents.
  1383. //
  1384. success = DeviceIoControl( fileHandle,
  1385. IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
  1386. NULL,
  1387. 0,
  1388. diskExtents,
  1389. diskExtentSize,
  1390. &bytesReturned,
  1391. FALSE );
  1392. status = GetLastError();
  1393. if ( !success ) {
  1394. if ( status == ERROR_MORE_DATA ) {
  1395. diskExtentSize = sizeof(VOLUME_DISK_EXTENTS) +
  1396. (sizeof(DISK_EXTENT) * diskExtents->NumberOfDiskExtents);
  1397. LocalFree( diskExtents );
  1398. diskExtents = LocalAlloc( LMEM_FIXED, diskExtentSize);
  1399. if ( !diskExtents ) {
  1400. return(ERROR_NOT_ENOUGH_MEMORY);
  1401. }
  1402. status = ERROR_SUCCESS;
  1403. success = DeviceIoControl( fileHandle,
  1404. IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
  1405. NULL,
  1406. 0,
  1407. diskExtents,
  1408. diskExtentSize,
  1409. &bytesReturned,
  1410. FALSE );
  1411. if ( !success ) {
  1412. status = GetLastError();
  1413. }
  1414. }
  1415. }
  1416. printf( "\n Starting offset Length DiskNumber\n");
  1417. printf( " --------------- ------ ----------\n");
  1418. for ( i = 0; i < diskExtents->NumberOfDiskExtents; i++ ) {
  1419. printf( " %08lx %08lx\t\t%08lx\t\t%u\n",
  1420. diskExtents->Extents[i].StartingOffset.HighPart,
  1421. diskExtents->Extents[i].StartingOffset.LowPart,
  1422. diskExtents->Extents[i].ExtentLength.LowPart,
  1423. diskExtents->Extents[i].DiskNumber );
  1424. }
  1425. return status;
  1426. } // EnumExtents
  1427. DWORD
  1428. EnumNodes(
  1429. HANDLE fileHandle,
  1430. int argc,
  1431. char *argv[]
  1432. )
  1433. /*++
  1434. Routine Description:
  1435. Description
  1436. Arguments:
  1437. None
  1438. Return Value:
  1439. None
  1440. --*/
  1441. {
  1442. BOOL success;
  1443. DWORD status;
  1444. HDEVINFO hDevInfo;
  1445. SP_DEVINFO_DATA devInfoData;
  1446. DWORD index;
  1447. DWORD size;
  1448. LPDWORD dwGuid;
  1449. UCHAR devDesc[MAX_PATH];
  1450. UCHAR devID[MAX_PATH];
  1451. hDevInfo = SetupDiGetClassDevs( NULL,
  1452. NULL,
  1453. NULL,
  1454. DIGCF_ALLCLASSES | DIGCF_PRESENT );
  1455. if ( hDevInfo == INVALID_HANDLE_VALUE ) {
  1456. status = GetLastError();
  1457. printf( "SetupDiGetClassDevs failed with error %u\n", status );
  1458. return status;
  1459. }
  1460. memset( &devInfoData, 0, sizeof(SP_DEVINFO_DATA));
  1461. devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  1462. //
  1463. // First see if anything works...
  1464. //
  1465. success = SetupDiEnumDeviceInfo( hDevInfo, 0, &devInfoData );
  1466. if ( !success ) {
  1467. status = GetLastError();
  1468. printf( "SetupDiEnumDeviceInfo failed, status = %u\n", status );
  1469. return status;
  1470. }
  1471. index = 0;
  1472. while ( SetupDiEnumDeviceInfo( hDevInfo, index, &devInfoData ) ) {
  1473. devDesc[0] = '\0';
  1474. size = sizeof(devDesc);
  1475. printf( "Index = %u\n", index );
  1476. if ( CM_Get_DevNode_Registry_Property( devInfoData.DevInst,
  1477. CM_DRP_DEVICEDESC,
  1478. NULL,
  1479. devDesc,
  1480. &size,
  1481. 0 ) == 0 ) {
  1482. printf( "Device description = %s\n", devDesc );
  1483. dwGuid = (LPDWORD)&devInfoData.ClassGuid;
  1484. printf( " GUID = %lx, %lx, %lx, %lx\n", dwGuid[0], dwGuid[1], dwGuid[2], dwGuid[3] );
  1485. devID[0] = '\0';
  1486. CM_Get_Device_ID( devInfoData.DevInst,
  1487. devID,
  1488. sizeof(devID),
  1489. 0 );
  1490. if ( devID[0] ) {
  1491. printf( " Device Id = %s\n", devID );
  1492. }
  1493. }
  1494. index++;
  1495. }
  1496. return ERROR_SUCCESS;
  1497. } // EnumNodes
  1498. DWORD
  1499. EnumDisks(
  1500. HANDLE fileHandle,
  1501. int argc,
  1502. char *argv[]
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. Description
  1507. Arguments:
  1508. None
  1509. Return Value:
  1510. None
  1511. --*/
  1512. {
  1513. DWORD status;
  1514. BOOL success;
  1515. HDEVINFO DeviceInfoSet;
  1516. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  1517. DWORD i;
  1518. PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData = NULL;
  1519. DWORD DeviceInterfaceDetailDataSize = 0;
  1520. DWORD RequiredSize;
  1521. SP_DEVINFO_DATA DeviceInfoData;
  1522. SP_PROPCHANGE_PARAMS PropChangeParams;
  1523. BOOL disable = FALSE;
  1524. BOOL parent = FALSE;
  1525. //GUID mountDevGuid;
  1526. GUID diskDevGuid;
  1527. HANDLE devHandle;
  1528. UCHAR driveLayoutBuf[sizeof(DRIVE_LAYOUT_INFORMATION) +
  1529. (sizeof(PARTITION_INFORMATION) * 64 )];
  1530. PDRIVE_LAYOUT_INFORMATION driveLayout = (PDRIVE_LAYOUT_INFORMATION)driveLayoutBuf;
  1531. if (argc > 1)
  1532. {
  1533. printf( "usage: <any_device> EnumDisks [DISABLE | PARENT]\n" );
  1534. return ERROR_INVALID_NAME;
  1535. }
  1536. if ( argc == 1 ) {
  1537. if (!_stricmp( *argv, "Disable" ))
  1538. disable = TRUE;
  1539. else if (!_stricmp( *argv, "Parent" ))
  1540. parent = TRUE;
  1541. else {
  1542. printf( "usage: <any_device> EnumDisks [DISABLE | PARENT]\n" );
  1543. return ERROR_INVALID_NAME;
  1544. }
  1545. }
  1546. memcpy( &diskDevGuid, &DiskClassGuid, sizeof(GUID) );
  1547. //memcpy( &mountDevGuid, &MOUNTDEV_MOUNTED_DEVICE_GUID, sizeof(GUID) );
  1548. DeviceInfoSet = SetupDiGetClassDevs(&diskDevGuid,
  1549. NULL,
  1550. NULL,
  1551. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT
  1552. );
  1553. DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  1554. DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  1555. for(i = 0;
  1556. SetupDiEnumDeviceInterfaces(DeviceInfoSet,
  1557. NULL,
  1558. &diskDevGuid,
  1559. i,
  1560. &DeviceInterfaceData);
  1561. i++) {
  1562. //
  1563. // To retrieve the device interface name (e.g., that you can call
  1564. // CreateFile() on...
  1565. //
  1566. while(!SetupDiGetDeviceInterfaceDetailW(DeviceInfoSet,
  1567. &DeviceInterfaceData,
  1568. DeviceInterfaceDetailData,
  1569. DeviceInterfaceDetailDataSize,
  1570. &RequiredSize,
  1571. &DeviceInfoData) ) {
  1572. //
  1573. // We failed to get the device interface detail data--was it because
  1574. // our buffer was too small? (Hopefully so!)
  1575. //
  1576. status = GetLastError();
  1577. //printf("Call to SetupDiGetDeviceInterfaceData failed status = %u, required size = %u\n",
  1578. // status, RequiredSize);
  1579. // Free our current buffer since we failed anyway.
  1580. free(DeviceInterfaceDetailData);
  1581. DeviceInterfaceDetailData = NULL;
  1582. if(status != ERROR_INSUFFICIENT_BUFFER) {
  1583. //
  1584. // Failure!
  1585. //
  1586. break;
  1587. }
  1588. DeviceInterfaceDetailData = malloc(RequiredSize);
  1589. if(DeviceInterfaceDetailData) {
  1590. DeviceInterfaceDetailDataSize = RequiredSize;
  1591. DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
  1592. } else {
  1593. //
  1594. // Failure!
  1595. //
  1596. DeviceInterfaceDetailDataSize = 0;
  1597. break;
  1598. }
  1599. }
  1600. if(!DeviceInterfaceDetailData) {
  1601. //
  1602. // We encountered a failure above--abort.
  1603. //
  1604. break;
  1605. }
  1606. //
  1607. // Now we may use the device interface name contained in the
  1608. // DeviceInterfaceDetailData->DevicePath field (e.g., in a call to
  1609. // CreateFile).
  1610. //
  1611. printf("DevicePath = %ws\n", DeviceInterfaceDetailData->DevicePath );
  1612. devHandle = CreateFileW( DeviceInterfaceDetailData->DevicePath,
  1613. GENERIC_READ,
  1614. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1615. NULL,
  1616. OPEN_EXISTING,
  1617. 0,
  1618. NULL );
  1619. if ( devHandle != INVALID_HANDLE_VALUE ) {
  1620. // Get signature
  1621. success = DeviceIoControl( devHandle,
  1622. IOCTL_DISK_GET_DRIVE_LAYOUT,
  1623. NULL,
  1624. 0,
  1625. driveLayout,
  1626. sizeof(driveLayoutBuf),
  1627. &RequiredSize,
  1628. FALSE );
  1629. if ( success ) {
  1630. printf( " Signature for device = %08lx\n", driveLayout->Signature );
  1631. }
  1632. CloseHandle( devHandle );
  1633. }
  1634. //
  1635. // To open up the persistent storage registry key associated with this
  1636. // device interface (e.g., to retrieve it's FriendlyName value entry),
  1637. // use SetupDiCreateDeviceInterfaceRegKey or
  1638. // SetupDiOpenDeviceInterfaceRegKey.
  1639. //
  1640. //
  1641. // Notice that we retrieved the associated device information element
  1642. // in the above call to SetupDiGetDeviceInterfaceDetail. We can thus
  1643. // use this element in setupapi calls to effect changes to the devnode
  1644. // (including invoking the class installer and any co-installers that
  1645. // may be involved).
  1646. //
  1647. // For example, here's how we'd disable the device...
  1648. //
  1649. if ( disable ) {
  1650. // Perform following only if we are supposed to disable
  1651. #ifdef PERSISTENT
  1652. PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  1653. PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  1654. PropChangeParams.StateChange = DICS_DISABLE;
  1655. PropChangeParams.Scope = DICS_FLAG_GLOBAL;
  1656. //
  1657. // No need to set PropChangeParams.HwProfile since we're doing global
  1658. // property change.
  1659. //
  1660. if( !SetupDiSetClassInstallParamsW(DeviceInfoSet,
  1661. &DeviceInfoData,
  1662. (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
  1663. sizeof(PropChangeParams)
  1664. ) ) {
  1665. status = GetLastError();
  1666. printf( "SetupDiSetClassInstallParams failed with %u\n", status );
  1667. continue;
  1668. }
  1669. if ( !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
  1670. DeviceInfoSet,
  1671. &DeviceInfoData
  1672. ) ) {
  1673. status = GetLastError();
  1674. printf( "SetupDiCallClassInstaller failed with %u\n", status );
  1675. continue;
  1676. }
  1677. printf("Disabled!\n");
  1678. getchar();
  1679. //
  1680. // ...and here's how we'd re-enable it...
  1681. //
  1682. PropChangeParams.StateChange = DICS_ENABLE;
  1683. if ( !SetupDiSetClassInstallParamsW(DeviceInfoSet,
  1684. &DeviceInfoData,
  1685. (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
  1686. sizeof(PropChangeParams)
  1687. ) ) {
  1688. status = GetLastError();
  1689. printf( "SetupDiSetClassInstallParams failed with %u\n", status );
  1690. continue;
  1691. }
  1692. if ( !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
  1693. DeviceInfoSet,
  1694. &DeviceInfoData
  1695. ) ) {
  1696. status = GetLastError();
  1697. printf( "SetupDiCallClassInstaller failed with %u\n", status );
  1698. }
  1699. #else
  1700. #if 0 // we don't support multiple switches together - this would need disable
  1701. // and parent set together!
  1702. //
  1703. // Try to find parent
  1704. //
  1705. if ( parent ) {
  1706. status = CM_Get_Parent( parentDev,
  1707. DeviceInfoData.DevInst,
  1708. 0 );
  1709. if ( status != ERROR_SUCCESS ) {
  1710. printf( "CM_Get_Parent failed with %u\n", status );
  1711. continue;
  1712. }
  1713. }
  1714. #endif
  1715. //
  1716. // NOTE: The code above does a persistent disable/enable. If you only
  1717. // wanted this to be temporary (i.e., in effect till reboot), then you
  1718. // could retrieve the devnode handle from the DeviceInfoData.DevInst
  1719. // field and call CM_Disable_DevNode and CM_Enable_DevNode directly.
  1720. //
  1721. status = CM_Disable_DevNode( DeviceInfoData.DevInst, 0 );
  1722. if ( status != ERROR_SUCCESS ) {
  1723. printf( "CM_Disable_DevNode failed with %u\n", status );
  1724. continue;
  1725. }
  1726. printf("Disabled!\n");
  1727. getchar();
  1728. status = CM_Enable_DevNode( DeviceInfoData.DevInst, 0 );
  1729. if ( status != ERROR_SUCCESS ) {
  1730. printf( "CM_Enable_DevNode failed with %u\n", status );
  1731. }
  1732. #endif //PERSISTENT
  1733. } else { // If we are supposed to disable the disk
  1734. //
  1735. // Try to find parent
  1736. //
  1737. if ( parent ) {
  1738. DEVINST parentDev;
  1739. DEVINST pParentDev = 0;
  1740. WCHAR outBuffer[MAX_PATH];
  1741. HDEVINFO devInfoSet;
  1742. SP_DEVINFO_DATA devInfoData;
  1743. SP_DEVICE_INTERFACE_DATA devInterfaceData;
  1744. do {
  1745. status = CM_Get_Parent( &parentDev,
  1746. DeviceInfoData.DevInst,
  1747. 0 );
  1748. if ( status != ERROR_SUCCESS ) {
  1749. printf( "CM_Get_Parent failed with %u\n", status );
  1750. break;
  1751. }
  1752. if ( pParentDev == parentDev ) {
  1753. break;
  1754. }
  1755. pParentDev = parentDev;
  1756. status = CM_Get_Device_IDW( parentDev,
  1757. outBuffer,
  1758. sizeof(outBuffer)/sizeof(WCHAR),
  1759. 0 );
  1760. if ( status != ERROR_SUCCESS ) {
  1761. printf( "CM_Get_Parent failed with %u\n", status );
  1762. //status = ERROR_SUCCESS;
  1763. } else {
  1764. printf( " ParentDev = %ws\n", outBuffer );
  1765. }
  1766. } while ( status == ERROR_SUCCESS );
  1767. }
  1768. }
  1769. }
  1770. SetupDiDestroyDeviceInfoList(DeviceInfoSet);
  1771. return ERROR_SUCCESS;
  1772. } // EnumDisks
  1773. DWORD
  1774. DisableNode(
  1775. HANDLE fileHandle,
  1776. int argc,
  1777. char *argv[]
  1778. )
  1779. /*++
  1780. Routine Description:
  1781. Description
  1782. Arguments:
  1783. None
  1784. Return Value:
  1785. None
  1786. --*/
  1787. {
  1788. BOOL success;
  1789. DWORD status;
  1790. HDEVINFO hDevInfo;
  1791. GUID devClassDisk;
  1792. SP_DEVINFO_DATA devInfoData;
  1793. DWORD index;
  1794. DWORD size;
  1795. LPDWORD dwGuid;
  1796. UCHAR devDesc[MAX_PATH];
  1797. UCHAR devID[MAX_PATH];
  1798. printf( "Not supported yet\n");
  1799. return ERROR_SUCCESS;
  1800. } // DisableNode
  1801. DWORD
  1802. EnableNode(
  1803. HANDLE fileHandle,
  1804. int argc,
  1805. char *argv[]
  1806. )
  1807. /*++
  1808. Routine Description:
  1809. Description
  1810. Arguments:
  1811. None
  1812. Return Value:
  1813. None
  1814. --*/
  1815. {
  1816. BOOL success;
  1817. DWORD status;
  1818. HDEVINFO hDevInfo;
  1819. GUID devClassDisk;
  1820. SP_DEVINFO_DATA devInfoData;
  1821. DWORD index;
  1822. DWORD size;
  1823. LPDWORD dwGuid;
  1824. UCHAR devDesc[MAX_PATH];
  1825. UCHAR devID[MAX_PATH];
  1826. printf( "Not supported yet\n");
  1827. return ERROR_SUCCESS;
  1828. } // EnableNode
  1829. DWORD
  1830. DisableDisk(
  1831. HANDLE fileHandle,
  1832. int argc,
  1833. char *argv[]
  1834. )
  1835. /*++
  1836. Routine Description:
  1837. Description
  1838. Arguments:
  1839. None
  1840. Return Value:
  1841. None
  1842. --*/
  1843. {
  1844. BOOL success;
  1845. DWORD status;
  1846. HDEVINFO hDevInfo;
  1847. GUID devClassDisk;
  1848. SP_DEVINFO_DATA devInfoData;
  1849. DWORD index;
  1850. DWORD size;
  1851. LPDWORD dwGuid;
  1852. UCHAR devDesc[MAX_PATH];
  1853. UCHAR devID[MAX_PATH];
  1854. printf( "Not supported yet\n");
  1855. return ERROR_SUCCESS;
  1856. } // DisableDisk
  1857. DWORD
  1858. EnableDisk(
  1859. HANDLE fileHandle,
  1860. int argc,
  1861. char *argv[]
  1862. )
  1863. /*++
  1864. Routine Description:
  1865. Description
  1866. Arguments:
  1867. None
  1868. Return Value:
  1869. None
  1870. --*/
  1871. {
  1872. BOOL success;
  1873. DWORD status;
  1874. HDEVINFO hDevInfo;
  1875. GUID devClassDisk;
  1876. SP_DEVINFO_DATA devInfoData;
  1877. DWORD index;
  1878. DWORD size;
  1879. LPDWORD dwGuid;
  1880. UCHAR devDesc[MAX_PATH];
  1881. UCHAR devID[MAX_PATH];
  1882. printf( "Not supported yet\n");
  1883. return ERROR_SUCCESS;
  1884. } // EnableDisk
  1885. DWORD
  1886. HoldIO(
  1887. HANDLE fileHandle,
  1888. int argc,
  1889. char *argv[]
  1890. )
  1891. /*++
  1892. Routine Description:
  1893. Description
  1894. Arguments:
  1895. None
  1896. Return Value:
  1897. None
  1898. --*/
  1899. {
  1900. BOOL success;
  1901. DWORD errorCode;
  1902. DWORD bytesReturned;
  1903. if (argc != 0)
  1904. {
  1905. printf( "usage: <device> HoldIO\n" );
  1906. return ERROR_INVALID_NAME;
  1907. }
  1908. success = DeviceIoControl( fileHandle,
  1909. IOCTL_DISK_CLUSTER_HOLD_IO,
  1910. NULL,
  1911. 0,
  1912. NULL,
  1913. 0,
  1914. &bytesReturned,
  1915. FALSE );
  1916. if (!success) {
  1917. printf( "Error performing Hold IO, error %d\n",
  1918. errorCode = GetLastError());
  1919. PrintError(errorCode);
  1920. return errorCode;
  1921. }
  1922. return ERROR_SUCCESS;
  1923. } // HoldIO
  1924. DWORD
  1925. ResumeIO(
  1926. HANDLE fileHandle,
  1927. int argc,
  1928. char *argv[]
  1929. )
  1930. /*++
  1931. Routine Description:
  1932. Description
  1933. Arguments:
  1934. None
  1935. Return Value:
  1936. None
  1937. --*/
  1938. {
  1939. BOOL success;
  1940. DWORD errorCode;
  1941. DWORD bytesReturned;
  1942. if (argc != 0)
  1943. {
  1944. printf( "usage: <device> ResumeIO\n" );
  1945. return ERROR_INVALID_NAME;
  1946. }
  1947. success = DeviceIoControl( fileHandle,
  1948. IOCTL_DISK_CLUSTER_RESUME_IO,
  1949. NULL,
  1950. 0,
  1951. NULL,
  1952. 0,
  1953. &bytesReturned,
  1954. FALSE );
  1955. if (!success) {
  1956. printf( "Error performing Resume IO, error %d\n",
  1957. errorCode = GetLastError());
  1958. PrintError(errorCode);
  1959. return errorCode;
  1960. }
  1961. return ERROR_SUCCESS;
  1962. } // ResumeIO
  1963. DWORD
  1964. GetDiskGeometry(
  1965. HANDLE fileHandle,
  1966. int argc,
  1967. char *argv[]
  1968. )
  1969. /*++
  1970. Routine Description:
  1971. Description
  1972. Arguments:
  1973. None
  1974. Return Value:
  1975. None
  1976. --*/
  1977. {
  1978. BOOL success;
  1979. DWORD errorCode;
  1980. DWORD bytesReturned;
  1981. DISK_GEOMETRY diskGeometry;
  1982. if (argc != 0)
  1983. {
  1984. printf( "usage: <device> GetDiskGeometry\n" );
  1985. return ERROR_INVALID_NAME;
  1986. }
  1987. ZeroMemory( &diskGeometry, sizeof(DISK_GEOMETRY) );
  1988. success = DeviceIoControl( fileHandle,
  1989. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  1990. NULL,
  1991. 0,
  1992. &diskGeometry,
  1993. sizeof(DISK_GEOMETRY),
  1994. &bytesReturned,
  1995. FALSE );
  1996. if (!success) {
  1997. printf( "Error performing GetDiskGeometry, error %d\n",
  1998. errorCode = GetLastError());
  1999. PrintError(errorCode);
  2000. return errorCode;
  2001. }
  2002. if ( bytesReturned < sizeof(DISK_GEOMETRY) ) {
  2003. printf("Error reading DiskGeometry information. Expected %u bytes, got %u bytes.\n",
  2004. sizeof(DISK_GEOMETRY),
  2005. bytesReturned);
  2006. return(ERROR_INSUFFICIENT_BUFFER);
  2007. }
  2008. printf("GetDiskGeometry was successful, we got %d bytes returned.\n",
  2009. bytesReturned);
  2010. printf("Cylinders = %lx%lx, TracksPerCylinder = %lx, SectorsPerTrack = %lx, BytesPerSector = %lx\n",
  2011. diskGeometry.Cylinders.HighPart, diskGeometry.Cylinders.LowPart,
  2012. diskGeometry.TracksPerCylinder, diskGeometry.SectorsPerTrack,
  2013. diskGeometry.BytesPerSector);
  2014. return ERROR_SUCCESS;
  2015. } // GetDiskGeometry
  2016. DWORD
  2017. GetScsiAddress(
  2018. HANDLE fileHandle,
  2019. int argc,
  2020. char *argv[]
  2021. )
  2022. /*++
  2023. Routine Description:
  2024. Description
  2025. Arguments:
  2026. None
  2027. Return Value:
  2028. None
  2029. --*/
  2030. {
  2031. BOOL success;
  2032. DWORD errorCode;
  2033. DWORD bytesReturned;
  2034. SCSI_ADDRESS scsiAddress;
  2035. if (argc != 0)
  2036. {
  2037. printf( "usage: <device> GetScsiAddress\n" );
  2038. return ERROR_INVALID_NAME;
  2039. }
  2040. ZeroMemory( &scsiAddress, sizeof(scsiAddress) );
  2041. success = DeviceIoControl( fileHandle,
  2042. IOCTL_SCSI_GET_ADDRESS,
  2043. NULL,
  2044. 0,
  2045. &scsiAddress,
  2046. sizeof(DISK_GEOMETRY),
  2047. &bytesReturned,
  2048. FALSE );
  2049. if (!success) {
  2050. printf( "Error performing GetScsiAddress, error %d\n",
  2051. errorCode = GetLastError());
  2052. PrintError(errorCode);
  2053. return errorCode;
  2054. }
  2055. if ( bytesReturned < sizeof(scsiAddress) ) {
  2056. printf("Error reading ScsiAddress information. Expected %u bytes, got %u bytes.\n",
  2057. sizeof(scsiAddress),
  2058. bytesReturned);
  2059. return(ERROR_INSUFFICIENT_BUFFER);
  2060. }
  2061. printf("GetScsiAddress was successful, we got %d bytes returned.\n",
  2062. bytesReturned);
  2063. printf("PortNumber = %x, PathId = %x, TargetId = %x, Lun = %x\n",
  2064. scsiAddress.PortNumber, scsiAddress.PathId,
  2065. scsiAddress.TargetId, scsiAddress.Lun);
  2066. return ERROR_SUCCESS;
  2067. } // GetScsiAddress
  2068. DWORD
  2069. GetDriveLayout(
  2070. HANDLE fileHandle,
  2071. int argc,
  2072. char *argv[]
  2073. )
  2074. /*++
  2075. Routine Description:
  2076. Description
  2077. Arguments:
  2078. None
  2079. Return Value:
  2080. None
  2081. --*/
  2082. {
  2083. BOOL success;
  2084. DWORD errorCode;
  2085. DWORD bytesReturned;
  2086. DWORD harddiskNo;
  2087. DWORD i;
  2088. PDRIVE_LAYOUT_INFORMATION driveLayout;
  2089. PPARTITION_INFORMATION partInfo;
  2090. if (argc != 0)
  2091. {
  2092. printf( "usage: <device> GetDriveLayout\n" );
  2093. return ERROR_INVALID_NAME;
  2094. }
  2095. driveLayout = DoIoctlAndAllocate(fileHandle,
  2096. IOCTL_DISK_GET_DRIVE_LAYOUT,
  2097. NULL, 0, &bytesReturned);
  2098. if (!driveLayout) {
  2099. return GetLastError();
  2100. }
  2101. printf("GetDriveLayout was successful, %d bytes returned.\n",
  2102. bytesReturned);
  2103. printf("Partition Count = %u \n", driveLayout->PartitionCount);
  2104. printf("Signature = %lx\n", driveLayout->Signature);
  2105. printf("\n");
  2106. printf("Part# Type Recog BootInd PartOff PartLeng HidSect Rewrite \n");
  2107. printf("===== ==== ===== ======= ============ ============ ======= ======= \n");
  2108. for (i = 0; i < driveLayout->PartitionCount; i++ ) {
  2109. partInfo = &driveLayout->PartitionEntry[i];
  2110. printf(" %2u %2X %1u %1u %12I64X %12I64X %7u %s \n",
  2111. partInfo->PartitionNumber,
  2112. partInfo->PartitionType,
  2113. partInfo->RecognizedPartition,
  2114. partInfo->BootIndicator,
  2115. partInfo->StartingOffset.QuadPart,
  2116. partInfo->PartitionLength.QuadPart,
  2117. partInfo->HiddenSectors,
  2118. BooleanToString( partInfo->RewritePartition )
  2119. );
  2120. }
  2121. free( driveLayout );
  2122. return ERROR_SUCCESS;
  2123. } // GetDriveLayout
  2124. DWORD
  2125. GetDriveLayoutEx(
  2126. HANDLE fileHandle,
  2127. int argc,
  2128. char *argv[]
  2129. )
  2130. /*++
  2131. Routine Description:
  2132. Description
  2133. Arguments:
  2134. None
  2135. Return Value:
  2136. None
  2137. --*/
  2138. {
  2139. PDRIVE_LAYOUT_INFORMATION_EX driveLayout = NULL;
  2140. PPARTITION_INFORMATION_EX partInfo;
  2141. DWORD errorCode = NO_ERROR;
  2142. DWORD bytesReturned;
  2143. DWORD harddiskNo;
  2144. DWORD idx;
  2145. DWORD nameIdx;
  2146. BOOL success;
  2147. TCHAR strGuid[MAX_PATH];
  2148. TCHAR strType[MAX_PATH];
  2149. if ( argc != 0 ) {
  2150. printf( "usage: <device> GetDriveLayoutEx \n" );
  2151. errorCode = ERROR_INVALID_NAME;
  2152. goto FnExit;
  2153. }
  2154. driveLayout = DoIoctlAndAllocate( fileHandle,
  2155. IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
  2156. NULL, 0, &bytesReturned );
  2157. if ( !driveLayout ) {
  2158. errorCode = GetLastError();
  2159. printf("IOCTL_DISK_GET_DRIVE_LAYOUT_EX failed: %u \n", errorCode);
  2160. PrintError( errorCode );
  2161. goto FnExit;
  2162. }
  2163. printf("GetDriveLayoutEx was successful: %d bytes returned.\n",
  2164. bytesReturned);
  2165. printf("Partition style = ");
  2166. if ( PARTITION_STYLE_MBR == driveLayout->PartitionStyle ) {
  2167. printf("MBR \n");
  2168. } else if ( PARTITION_STYLE_GPT == driveLayout->PartitionStyle ) {
  2169. printf("GPT \n");
  2170. } else if ( PARTITION_STYLE_RAW == driveLayout->PartitionStyle ) {
  2171. printf("RAW \n");
  2172. goto FnExit;
  2173. } else {
  2174. printf("Unknown \n");
  2175. goto FnExit;
  2176. }
  2177. printf("Partition Count = %u \n", driveLayout->PartitionCount);
  2178. if ( PARTITION_STYLE_MBR == driveLayout->PartitionStyle ) {
  2179. printf("Signature = %lx \n", driveLayout->Mbr.Signature);
  2180. printf("\n");
  2181. printf("Part# Type Recog BootInd PartOff PartLeng HidSect Rewrite \n");
  2182. printf("===== ==== ===== ======= ============ ============ ======= ======= \n");
  2183. for ( idx = 0; idx < driveLayout->PartitionCount; idx++ ) {
  2184. partInfo = &driveLayout->PartitionEntry[idx];
  2185. if ( PARTITION_STYLE_MBR != partInfo->PartitionStyle ) {
  2186. printf("Skipping partition: style is not MBR (%u) \n", partInfo->PartitionStyle);
  2187. continue;
  2188. }
  2189. printf(" %2u %2X %1u %1u %12I64X %12I64X %7u %s \n",
  2190. partInfo->PartitionNumber,
  2191. partInfo->Mbr.PartitionType,
  2192. partInfo->Mbr.RecognizedPartition,
  2193. partInfo->Mbr.BootIndicator,
  2194. partInfo->StartingOffset.QuadPart,
  2195. partInfo->PartitionLength.QuadPart,
  2196. partInfo->Mbr.HiddenSectors,
  2197. BooleanToString( partInfo->RewritePartition )
  2198. );
  2199. }
  2200. } else {
  2201. FormatGuid( &(driveLayout->Gpt.DiskId), strGuid );
  2202. printf("Signature (GUID) = %s \n", strGuid );
  2203. printf("Signature (hashed) = %08x \n", ClusterHashGuid( driveLayout->Gpt.DiskId ) );
  2204. printf("\n");
  2205. printf("Part# PartOff PartLeng Rewrite \n");
  2206. printf("===== ================ ================ ======= \n");
  2207. for ( idx = 0; idx < driveLayout->PartitionCount; idx++ ) {
  2208. partInfo = &driveLayout->PartitionEntry[idx];
  2209. if ( idx ) {
  2210. printf("\n");
  2211. }
  2212. if ( PARTITION_STYLE_GPT != partInfo->PartitionStyle ) {
  2213. printf("Skipping partition: style is not GPT (%u) \n", partInfo->PartitionStyle);
  2214. continue;
  2215. }
  2216. printf(" %2u %16I64X %16I64X %s \n",
  2217. partInfo->PartitionNumber,
  2218. partInfo->StartingOffset.QuadPart,
  2219. partInfo->PartitionLength.QuadPart,
  2220. BooleanToString( partInfo->RewritePartition )
  2221. );
  2222. FormatGuid( &(partInfo->Gpt.PartitionType), strGuid);
  2223. if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_SYSTEM_GUID, sizeof(GUID) ) ) {
  2224. sprintf(strType, "System");
  2225. } else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_MSFT_RESERVED_GUID, sizeof(GUID) ) ) {
  2226. sprintf(strType, "Microsoft Reserved");
  2227. } else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_BASIC_DATA_GUID, sizeof(GUID) ) ) {
  2228. sprintf(strType, "Basic Data");
  2229. } else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_LDM_METADATA_GUID, sizeof(GUID) ) ) {
  2230. sprintf(strType, "LDM Metadata");
  2231. } else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_LDM_DATA_GUID, sizeof(GUID) ) ) {
  2232. sprintf(strType, "LDM Data");
  2233. #if PARTITION_CLUSTER_GUID
  2234. } else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_CLUSTER_GUID, sizeof(GUID) ) ) {
  2235. sprintf(strType, "Cluster Data");
  2236. #endif
  2237. } else {
  2238. sprintf(strType, "Unknown partition type");
  2239. }
  2240. printf("\n");
  2241. printf(" PartitionType = %s \n", strGuid);
  2242. printf(" %s \n", strType);
  2243. FormatGuid(&(partInfo->Gpt.PartitionId), strGuid);
  2244. printf(" PartitionId = %s \n", strGuid);
  2245. printf(" Attributes = %I64X \n", partInfo->Gpt.Attributes);
  2246. printf(" Name: ");
  2247. for ( nameIdx = 0; nameIdx < 36; nameIdx++ ) {
  2248. printf("%c", partInfo->Gpt.Name[nameIdx]);
  2249. }
  2250. printf("\n");
  2251. }
  2252. }
  2253. FnExit:
  2254. free( driveLayout );
  2255. return ERROR_SUCCESS;
  2256. } // GetDriveLayoutEx
  2257. LPTSTR
  2258. BooleanToString(
  2259. BOOLEAN Value
  2260. )
  2261. {
  2262. if ( Value ) {
  2263. return "TRUE ";
  2264. }
  2265. return "FALSE";
  2266. } // BooleanToString
  2267. void
  2268. FormatGuid(
  2269. GUID* Guid,
  2270. char* Str
  2271. )
  2272. {
  2273. //
  2274. // Code from guidgen
  2275. //
  2276. sprintf(Str, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  2277. // first copy...
  2278. Guid->Data1, Guid->Data2, Guid->Data3,
  2279. Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3],
  2280. Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]);
  2281. }
  2282. DWORD
  2283. GetVolumeInfo(
  2284. HANDLE fileHandle,
  2285. int argc,
  2286. char *argv[]
  2287. )
  2288. /*++
  2289. Routine Description:
  2290. Description
  2291. Arguments:
  2292. None
  2293. Return Value:
  2294. None
  2295. --*/
  2296. {
  2297. BOOL success;
  2298. DWORD errorCode;
  2299. PCLUSPROP_PARTITION_INFO partInfo;
  2300. ANSI_STRING ansiName;
  2301. UNICODE_STRING unicodeName;
  2302. NTSTATUS ntStatus;
  2303. if (argc != 0) {
  2304. printf( "usage: <device> GetVolumeInfo\n" );
  2305. return ERROR_INVALID_NAME;
  2306. }
  2307. ntStatus = GetVolumeInformationFromHandle(fileHandle);
  2308. if ( !NT_SUCCESS(ntStatus) ) {
  2309. errorCode = RtlNtStatusToDosError( ntStatus );
  2310. printf( "GetVolumeInformationFromHandle failed with status %X, %u\n",
  2311. ntStatus, errorCode );
  2312. }
  2313. partInfo = LocalAlloc( LMEM_FIXED, sizeof(CLUSPROP_PARTITION_INFO) );
  2314. if ( !partInfo ) {
  2315. return ERROR_NOT_ENOUGH_MEMORY;
  2316. }
  2317. ZeroMemory( partInfo, sizeof(CLUSPROP_PARTITION_INFO) );
  2318. RtlInitString(&ansiName, DeviceName);
  2319. errorCode = RtlAnsiStringToUnicodeString( &unicodeName,
  2320. &ansiName,
  2321. TRUE );
  2322. if ( !NT_SUCCESS(errorCode) ) {
  2323. return(errorCode);
  2324. }
  2325. // The following assumes a drive letter is used.
  2326. // wsprintfW( partInfo->szDeviceName, L"%c:\\", unicodeName.Buffer[0] );
  2327. wcsncpy( partInfo->szDeviceName, unicodeName.Buffer, unicodeName.Length );
  2328. RtlFreeUnicodeString( &unicodeName );
  2329. if ( !GetVolumeInformationW( partInfo->szDeviceName,
  2330. partInfo->szVolumeLabel,
  2331. sizeof(partInfo->szVolumeLabel),
  2332. &partInfo->dwSerialNumber,
  2333. &partInfo->rgdwMaximumComponentLength,
  2334. &partInfo->dwFileSystemFlags,
  2335. partInfo->szFileSystem,
  2336. sizeof(partInfo->szFileSystem) ) ) {
  2337. partInfo->szVolumeLabel[0] = L'\0';
  2338. errorCode = GetLastError();
  2339. printf("Error reading volume information for %ws. Error %u.\n",
  2340. partInfo->szDeviceName,
  2341. errorCode);
  2342. LocalFree( partInfo );
  2343. return( errorCode );
  2344. }
  2345. printf("DeviceName = %ws\n", partInfo->szDeviceName);
  2346. printf("VolumeLabel = %ws\n", partInfo->szVolumeLabel);
  2347. printf("FileSystemFlags = %lx, FileSystem = %ws\n",
  2348. partInfo->dwFileSystemFlags, partInfo->szFileSystem);
  2349. LocalFree( partInfo );
  2350. return ERROR_SUCCESS;
  2351. } // GetVolumeInfo
  2352. DWORD
  2353. SetDriveLayout(
  2354. HANDLE fileHandle,
  2355. int argc,
  2356. char *argv[]
  2357. )
  2358. /*++
  2359. Routine Description:
  2360. Description
  2361. Arguments:
  2362. None
  2363. Return Value:
  2364. None
  2365. --*/
  2366. {
  2367. BOOL success;
  2368. DWORD errorCode;
  2369. DWORD bytesReturned;
  2370. DWORD driveLayoutSize;
  2371. PDRIVE_LAYOUT_INFORMATION driveLayout;
  2372. PPARTITION_INFORMATION partInfo;
  2373. DWORD index;
  2374. DWORD partShift = 0;
  2375. if (argc != 0)
  2376. {
  2377. printf( "usage: <device> SetDriveLayout\n" );
  2378. return ERROR_INVALID_NAME;
  2379. }
  2380. driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
  2381. (sizeof(PARTITION_INFORMATION) * MAX_PARTITIONS);
  2382. driveLayout = LocalAlloc( LMEM_FIXED, driveLayoutSize );
  2383. if ( !driveLayout ) {
  2384. return(ERROR_OUTOFMEMORY);
  2385. }
  2386. ZeroMemory( driveLayout, driveLayoutSize );
  2387. success = DeviceIoControl( fileHandle,
  2388. IOCTL_DISK_GET_DRIVE_LAYOUT,
  2389. NULL,
  2390. 0,
  2391. driveLayout,
  2392. driveLayoutSize,
  2393. &bytesReturned,
  2394. FALSE );
  2395. if (!success) {
  2396. printf( "Error performing GetDriveLayout; error was %d\n",
  2397. errorCode = GetLastError());
  2398. PrintError(errorCode);
  2399. LocalFree( driveLayout );
  2400. return errorCode;
  2401. }
  2402. driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
  2403. (sizeof(PARTITION_INFORMATION) *
  2404. (driveLayout->PartitionCount - 1));
  2405. if ( bytesReturned < driveLayoutSize ) {
  2406. printf("Error reading DriveLayout information. Expected %u bytes, got %u bytes.\n",
  2407. sizeof(DRIVE_LAYOUT_INFORMATION) + (sizeof(PARTITION_INFORMATION) *
  2408. (driveLayout->PartitionCount - 1)), bytesReturned);
  2409. LocalFree( driveLayout );
  2410. return(ERROR_INSUFFICIENT_BUFFER);
  2411. }
  2412. if ( driveLayout->PartitionCount > MAX_PARTITIONS ) {
  2413. printf("SetDriveLayout, exiting - too many partitions!\n");
  2414. LocalFree( driveLayout );
  2415. return(ERROR_TOO_MANY_LINKS);
  2416. }
  2417. for ( index = 0;
  2418. (index < driveLayout->PartitionCount) &&
  2419. (index < MAX_PARTITIONS );
  2420. index++ ) {
  2421. partInfo = &driveLayout->PartitionEntry[index];
  2422. if ( (partInfo->PartitionType == PARTITION_ENTRY_UNUSED) ||
  2423. !partInfo->RecognizedPartition ) {
  2424. continue;
  2425. }
  2426. if ( (index == 0) &&
  2427. (partInfo->PartitionNumber == 0) ) {
  2428. partShift = 1;
  2429. }
  2430. printf("Partition %u was %s\n", partInfo->PartitionNumber, (partShift? "incremented" : "left alone"));
  2431. partInfo->PartitionNumber += partShift;
  2432. }
  2433. success = DeviceIoControl( fileHandle,
  2434. IOCTL_DISK_SET_DRIVE_LAYOUT,
  2435. driveLayout,
  2436. driveLayoutSize,
  2437. NULL,
  2438. 0,
  2439. &bytesReturned,
  2440. FALSE );
  2441. if ( !success ) {
  2442. printf("Error performing SetDriveLayout, error %u.\n",
  2443. errorCode = GetLastError());
  2444. PrintError(errorCode);
  2445. LocalFree( driveLayout );
  2446. return(errorCode);
  2447. }
  2448. LocalFree( driveLayout );
  2449. printf("SetDriveLayout was successful. Set %d bytes.\n", driveLayoutSize);
  2450. return ERROR_SUCCESS;
  2451. } // SetDriveLayout
  2452. static DWORD
  2453. Attach(
  2454. HANDLE fileHandle,
  2455. int argc,
  2456. char *argv[]
  2457. )
  2458. /*++
  2459. Routine Description:
  2460. Description
  2461. Arguments:
  2462. None
  2463. Return Value:
  2464. None
  2465. --*/
  2466. {
  2467. BOOL success;
  2468. DWORD errorCode;
  2469. DWORD bytesReturned;
  2470. DWORD signature;
  2471. STRING ansiString;
  2472. UNICODE_STRING numberString;
  2473. if (argc != 1)
  2474. {
  2475. printf( "usage: <device> Attach <device signature>\n" );
  2476. return ERROR_INVALID_NAME;
  2477. }
  2478. RtlInitAnsiString( &ansiString, *argv );
  2479. printf(" Ansi string for signature is %s\n",
  2480. ansiString.Buffer );
  2481. RtlAnsiStringToUnicodeString(
  2482. &numberString,
  2483. &ansiString,
  2484. TRUE );
  2485. errorCode = RtlUnicodeStringToInteger(
  2486. &numberString,
  2487. 16,
  2488. &signature );
  2489. RtlFreeUnicodeString( &numberString );
  2490. if ( !NT_SUCCESS(errorCode) ) {
  2491. printf( "Error converting signature to hex number, NT status %u.\n",
  2492. errorCode );
  2493. return(errorCode);
  2494. }
  2495. success = DeviceIoControl( fileHandle,
  2496. IOCTL_DISK_CLUSTER_ATTACH,
  2497. &signature,
  2498. sizeof(DWORD),
  2499. NULL,
  2500. 0,
  2501. &bytesReturned,
  2502. FALSE );
  2503. if (!success) {
  2504. printf( "Error performing ATTACH, error was %d\n",
  2505. errorCode = GetLastError());
  2506. PrintError(errorCode);
  2507. return errorCode;
  2508. }
  2509. return ERROR_SUCCESS;
  2510. } // Attach
  2511. static DWORD
  2512. Detach(
  2513. HANDLE fileHandle,
  2514. int argc,
  2515. char *argv[]
  2516. )
  2517. /*++
  2518. Routine Description:
  2519. Description
  2520. Arguments:
  2521. None
  2522. Return Value:
  2523. None
  2524. --*/
  2525. {
  2526. BOOL success;
  2527. DWORD errorCode;
  2528. DWORD bytesReturned;
  2529. DWORD signature;
  2530. STRING ansiString;
  2531. UNICODE_STRING numberString;
  2532. if (argc != 1)
  2533. {
  2534. printf( "usage: <device> Detach <device signature>\n" );
  2535. return ERROR_INVALID_NAME;
  2536. }
  2537. RtlInitAnsiString( &ansiString, *argv );
  2538. printf(" Ansi string for signature is %s\n",
  2539. ansiString.Buffer );
  2540. RtlAnsiStringToUnicodeString(
  2541. &numberString,
  2542. &ansiString,
  2543. TRUE );
  2544. errorCode = RtlUnicodeStringToInteger(
  2545. &numberString,
  2546. 16,
  2547. &signature );
  2548. RtlFreeUnicodeString( &numberString );
  2549. if ( !NT_SUCCESS(errorCode) ) {
  2550. printf( "Error converting signature to hex number, NT status %u.\n",
  2551. errorCode );
  2552. return(errorCode);
  2553. }
  2554. success = DeviceIoControl( fileHandle,
  2555. IOCTL_DISK_CLUSTER_DETACH,
  2556. &signature,
  2557. sizeof(DWORD),
  2558. NULL,
  2559. 0,
  2560. &bytesReturned,
  2561. FALSE );
  2562. if (!success) {
  2563. printf( "Error performing DETACH, error was %d\n",
  2564. errorCode = GetLastError());
  2565. PrintError(errorCode);
  2566. return errorCode;
  2567. }
  2568. return ERROR_SUCCESS;
  2569. } // Detach
  2570. static DWORD
  2571. GetPartitionInfo(
  2572. HANDLE fileHandle,
  2573. int argc,
  2574. char *argv[]
  2575. )
  2576. /*++
  2577. Routine Description:
  2578. Description
  2579. Arguments:
  2580. None
  2581. Return Value:
  2582. None
  2583. --*/
  2584. {
  2585. BOOL success;
  2586. DWORD errorCode;
  2587. DWORD bytesReturned;
  2588. PARTITION_INFORMATION partInfo;
  2589. if (argc != 0)
  2590. {
  2591. printf( "usage: <device> GetPartitionInfo\n" );
  2592. return ERROR_INVALID_NAME;
  2593. }
  2594. success = DeviceIoControl( fileHandle,
  2595. IOCTL_DISK_GET_PARTITION_INFO,
  2596. NULL,
  2597. 0,
  2598. &partInfo,
  2599. sizeof(PARTITION_INFORMATION),
  2600. &bytesReturned,
  2601. FALSE );
  2602. if (!success) {
  2603. printf( "Error performing GetPartitionInfo; error was %d\n",
  2604. errorCode = GetLastError());
  2605. PrintError(errorCode);
  2606. return errorCode;
  2607. }
  2608. printf("GetPartitionInfo was successful, we got %d bytes returned.\n\n",
  2609. bytesReturned);
  2610. printf("Part# Type Recog BootInd PartOff PartLeng HidSect\n");
  2611. #if 0
  2612. Part# Type Recog BootInd PartOff PartLeng HidSect
  2613. xx xx x x xxxxxxxxxxxx xxxxxxxxxxxx xxxxxxx
  2614. #endif
  2615. printf(" %2u %2X %1u %1u %12I64X %12I64X %7u\n",
  2616. partInfo.PartitionNumber,
  2617. partInfo.PartitionType,
  2618. partInfo.RecognizedPartition,
  2619. partInfo.BootIndicator,
  2620. partInfo.StartingOffset.QuadPart,
  2621. partInfo.PartitionLength.QuadPart,
  2622. partInfo.HiddenSectors);
  2623. return ERROR_SUCCESS;
  2624. } // GetPartitionInfo
  2625. DWORD
  2626. AssignLetters(
  2627. HANDLE fileHandle,
  2628. int argc,
  2629. char *argv[]
  2630. )
  2631. /*++
  2632. Routine Description:
  2633. Description
  2634. Arguments:
  2635. None
  2636. Return Value:
  2637. None
  2638. --*/
  2639. {
  2640. DWORD errorCode;
  2641. LPSTR device;
  2642. DISK_INFO diskInfo;
  2643. DWORD count;
  2644. if (argc != 0)
  2645. {
  2646. printf( "usage: <device> AssignLetters\n" );
  2647. return ERROR_INVALID_NAME;
  2648. }
  2649. diskInfo.FileHandle = fileHandle;
  2650. --argv;
  2651. device = *--argv;
  2652. count = sscanf( device, "physicaldrive%d", &diskInfo.PhysicalDrive );
  2653. if ( count != 1 ) {
  2654. printf("AssignLetters, failed to get device drive number for '%s', count %u.\n",
  2655. device, count);
  2656. return(ERROR_INVALID_PARAMETER);
  2657. }
  2658. errorCode = AssignDriveLetters( &diskInfo );
  2659. return(errorCode);
  2660. } // AssignLetters
  2661. DWORD
  2662. RemoveLetters(
  2663. HANDLE fileHandle,
  2664. int argc,
  2665. char *argv[]
  2666. )
  2667. /*++
  2668. Routine Description:
  2669. Description
  2670. Arguments:
  2671. None
  2672. Return Value:
  2673. None
  2674. --*/
  2675. {
  2676. DWORD errorCode = ERROR_SUCCESS;
  2677. LPSTR device;
  2678. DISK_INFO diskInfo;
  2679. DWORD count;
  2680. UCHAR fileName[MAX_PATH];
  2681. UCHAR objectLink[MAX_PATH];
  2682. DWORD length;
  2683. DWORD partitionNumber;
  2684. DWORD deviceNumber;
  2685. DWORD maxPartitions = 8;
  2686. DWORD bytesReturned;
  2687. HANDLE FileHandle;
  2688. if (argc != 0) {
  2689. printf( "usage: <device> RemoveLetters\n" );
  2690. return ERROR_INVALID_NAME;
  2691. }
  2692. diskInfo.FileHandle = fileHandle;
  2693. --argv;
  2694. device = *--argv;
  2695. count = sscanf( device, "physicaldrive%d", &diskInfo.PhysicalDrive );
  2696. if ( count != 1 ) {
  2697. printf("RemoveLetters, failed to get device drive number for '%s', count %u.\n",
  2698. device, count);
  2699. return(ERROR_INVALID_PARAMETER);
  2700. }
  2701. //errorCode = RemoveDriveLetters( &diskInfo );
  2702. sprintf( objectLink, "PhysicalDrive%d", diskInfo.PhysicalDrive );
  2703. GetSymbolicLink( "\\DosDevices\\", objectLink, &diskInfo );
  2704. length = sscanf( objectLink, PartitionName, &deviceNumber, &partitionNumber );
  2705. if ( length != 2 || partitionNumber != 0 ) {
  2706. printf("Cannot find partition info for %s.\n",
  2707. objectLink);
  2708. maxPartitions = 0;
  2709. }
  2710. length = strlen( objectLink );
  2711. objectLink[length-1] = '\0';
  2712. for ( partitionNumber = 1;
  2713. partitionNumber <= maxPartitions;
  2714. partitionNumber++ ) {
  2715. sprintf( fileName, "%s%d\0", objectLink, partitionNumber );
  2716. FileHandle = OpenObject( "\\DosDevices", fileName, &diskInfo );
  2717. if ( FileHandle == INVALID_HANDLE_VALUE ||
  2718. FileHandle == NULL ) {
  2719. #if 0
  2720. printf("Error opening partitions on device %s%s, error %u.\n",
  2721. "\\DosDevices",
  2722. fileName,
  2723. GetLastError() );
  2724. #endif
  2725. break;
  2726. }
  2727. if ( !DeviceIoControl( FileHandle,
  2728. FSCTL_DISMOUNT_VOLUME,
  2729. NULL,
  2730. 0,
  2731. NULL,
  2732. 0,
  2733. &bytesReturned,
  2734. NULL ) ) {
  2735. printf("Error dismounting volume, %u.\n",
  2736. GetLastError() );
  2737. }
  2738. CloseHandle( FileHandle );
  2739. }
  2740. #if 0
  2741. errorCode = RemoveDriveLetters( &diskInfo );
  2742. #endif
  2743. return(errorCode);
  2744. } // RemoveLetters
  2745. DWORD
  2746. ReadSector(
  2747. HANDLE fileHandle,
  2748. int argc,
  2749. char *argv[]
  2750. )
  2751. /*++
  2752. Routine Description:
  2753. Description
  2754. Arguments:
  2755. None
  2756. Return Value:
  2757. None
  2758. --*/
  2759. {
  2760. BOOL success;
  2761. DWORD errorCode;
  2762. DWORD status;
  2763. DWORD bytesReturned;
  2764. DWORD bytesRead;
  2765. DWORD x,y;
  2766. DISK_GEOMETRY diskGeometry;
  2767. LPBYTE buf = 0;
  2768. INT sectorNo;
  2769. if (argc != 1)
  2770. {
  2771. printf( "usage: <device> ReadSector No\n" );
  2772. return ERROR_INVALID_NAME;
  2773. }
  2774. status = sscanf(argv[0], "%d", &sectorNo);
  2775. if ( 0 == status ) {
  2776. printf("Unable to get sector number from input \n");
  2777. return ERROR_INVALID_PARAMETER;
  2778. }
  2779. ZeroMemory( &diskGeometry, sizeof(DISK_GEOMETRY) );
  2780. success = DeviceIoControl( fileHandle,
  2781. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  2782. NULL,
  2783. 0,
  2784. &diskGeometry,
  2785. sizeof(DISK_GEOMETRY),
  2786. &bytesReturned,
  2787. FALSE );
  2788. if (!success) {
  2789. printf( "Error performing GetDiskGeometry, error %d\n",
  2790. errorCode = GetLastError());
  2791. PrintError(errorCode);
  2792. return errorCode;
  2793. }
  2794. if ( bytesReturned < sizeof(DISK_GEOMETRY) ) {
  2795. printf("Error reading DiskGeometry information. Expected %u bytes, got %u bytes.\n",
  2796. sizeof(DISK_GEOMETRY),
  2797. bytesReturned);
  2798. return(ERROR_INSUFFICIENT_BUFFER);
  2799. }
  2800. printf("GetDiskGeometry was successful, we got %d bytes returned.\n",
  2801. bytesReturned);
  2802. printf("Cylinders = %lx%lx, TracksPerCylinder = %lx, SectorsPerTrack = %lx, BytesPerSector = %lx\n",
  2803. diskGeometry.Cylinders.HighPart, diskGeometry.Cylinders.LowPart,
  2804. diskGeometry.TracksPerCylinder, diskGeometry.SectorsPerTrack,
  2805. diskGeometry.BytesPerSector);
  2806. errorCode = ERROR_SUCCESS;
  2807. __try {
  2808. buf = VirtualAlloc(0, diskGeometry.BytesPerSector, MEM_COMMIT, PAGE_READWRITE);
  2809. if(buf == 0) {
  2810. printf("Virtual Alloc failed\n");
  2811. errorCode = GetLastError();
  2812. __leave;
  2813. }
  2814. printf("Sector %d\n", sectorNo);
  2815. status = SetFilePointer(fileHandle,
  2816. diskGeometry.BytesPerSector * sectorNo,
  2817. NULL,
  2818. FILE_BEGIN);
  2819. if( 0xFFFFFFFF == status ) {
  2820. printf("Error setting file pointer to %lx \n", diskGeometry.BytesPerSector * sectorNo);
  2821. errorCode = GetLastError();
  2822. __leave;
  2823. }
  2824. status = ReadFile(fileHandle,
  2825. buf,
  2826. diskGeometry.BytesPerSector,
  2827. &bytesRead,
  2828. NULL);
  2829. if( status == 0 ) {
  2830. printf("Error reading sector %lx \n.", sectorNo);
  2831. errorCode = GetLastError();
  2832. __leave;
  2833. }
  2834. if ( bytesRead != diskGeometry.BytesPerSector ) {
  2835. printf("Error reading sector. Expected %ul bytes, got %ul bytes.\n",
  2836. diskGeometry.BytesPerSector,
  2837. bytesRead);
  2838. errorCode = ERROR_INSUFFICIENT_BUFFER;
  2839. __leave;
  2840. }
  2841. for(x = 0; x < diskGeometry.BytesPerSector; x += 16) {
  2842. for(y = 0; y < 16; ++y) {
  2843. BYTE ch = buf[x+y];
  2844. if (ch >= ' ' && ch <= '~') {
  2845. printf(" %c", ch);
  2846. } else {
  2847. printf(" %02x", ch);
  2848. }
  2849. }
  2850. printf("\n");
  2851. }
  2852. errorCode = ERROR_SUCCESS;
  2853. }
  2854. __finally {
  2855. if(buf) {
  2856. VirtualFree(buf, 0, MEM_RELEASE);
  2857. }
  2858. }
  2859. return errorCode;
  2860. } // ReadSector
  2861. DWORD
  2862. ReadSectorViaIoctl(
  2863. HANDLE fileHandle,
  2864. int argc,
  2865. char *argv[]
  2866. )
  2867. /*++
  2868. Routine Description:
  2869. Description
  2870. Arguments:
  2871. None
  2872. Return Value:
  2873. None
  2874. --*/
  2875. {
  2876. BOOL success;
  2877. DWORD errorCode;
  2878. DWORD bytesReturned;
  2879. DISK_GEOMETRY diskGeometry;
  2880. DWORD bytesRead;
  2881. DWORD status;
  2882. DWORD x,y;
  2883. ARBITRATION_READ_WRITE_PARAMS params;
  2884. LPBYTE buf = 0;
  2885. INT sectorNo;
  2886. if (argc != 1)
  2887. {
  2888. printf( "usage: <device> rs No\n" );
  2889. return ERROR_INVALID_NAME;
  2890. }
  2891. status = sscanf(argv[0], "%d", &sectorNo);
  2892. if ( 0 == status ) {
  2893. printf("Unable to get sector number from input \n");
  2894. return ERROR_INVALID_PARAMETER;
  2895. }
  2896. ZeroMemory( &diskGeometry, sizeof(DISK_GEOMETRY) );
  2897. success = DeviceIoControl( fileHandle,
  2898. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  2899. NULL,
  2900. 0,
  2901. &diskGeometry,
  2902. sizeof(DISK_GEOMETRY),
  2903. &bytesReturned,
  2904. FALSE );
  2905. if (!success) {
  2906. printf( "Error performing GetDiskGeometry, error %d\n",
  2907. errorCode = GetLastError());
  2908. PrintError(errorCode);
  2909. return errorCode;
  2910. }
  2911. if ( bytesReturned < sizeof(DISK_GEOMETRY) ) {
  2912. printf("Error reading DiskGeometry information. Expected %u bytes, got %u bytes.\n",
  2913. sizeof(DISK_GEOMETRY),
  2914. bytesReturned);
  2915. return(ERROR_INSUFFICIENT_BUFFER);
  2916. }
  2917. printf("GetDiskGeometry was successful, we got %d bytes returned.\n",
  2918. bytesReturned);
  2919. printf("Cylinders = %lx%lx, TracksPerCylinder = %lx, SectorsPerTrack = %lx, BytesPerSector = %lx\n",
  2920. diskGeometry.Cylinders.HighPart, diskGeometry.Cylinders.LowPart,
  2921. diskGeometry.TracksPerCylinder, diskGeometry.SectorsPerTrack,
  2922. diskGeometry.BytesPerSector);
  2923. errorCode = ERROR_SUCCESS;
  2924. __try {
  2925. buf = VirtualAlloc(0, diskGeometry.BytesPerSector, MEM_COMMIT, PAGE_READWRITE);
  2926. if(buf == 0) {
  2927. printf("Virtual Alloc failed\n");
  2928. errorCode = GetLastError();
  2929. __leave;
  2930. }
  2931. printf("Sector %d\n", sectorNo);
  2932. params.Operation = AE_READ;
  2933. params.SectorSize = diskGeometry.BytesPerSector;
  2934. params.SectorNo = sectorNo;
  2935. params.Buffer = buf;
  2936. success = DeviceIoControl( fileHandle,
  2937. IOCTL_DISK_CLUSTER_ARBITRATION_ESCAPE,
  2938. &params,
  2939. sizeof(params),
  2940. NULL,
  2941. 0,
  2942. &bytesReturned,
  2943. FALSE );
  2944. if(!success) {
  2945. printf("Error reading sector %lx\n.", sectorNo);
  2946. errorCode = GetLastError();
  2947. __leave;
  2948. }
  2949. for(x = 0; x < diskGeometry.BytesPerSector; x += 16) {
  2950. for(y = 0; y < 16; ++y) {
  2951. BYTE ch = buf[x+y];
  2952. if (ch >= ' ' && ch <= '~') {
  2953. printf(" %c", ch);
  2954. } else {
  2955. printf(" %02x", ch);
  2956. }
  2957. }
  2958. printf("\n");
  2959. }
  2960. errorCode = ERROR_SUCCESS;
  2961. }
  2962. __finally {
  2963. if(buf) {
  2964. VirtualFree(buf, 0, MEM_RELEASE);
  2965. }
  2966. }
  2967. return errorCode;
  2968. } // ReadSectorViaIoctl
  2969. DWORD
  2970. FixDisk(
  2971. HANDLE fileHandle,
  2972. int argc,
  2973. char *argv[]
  2974. )
  2975. /*++
  2976. Routine Description:
  2977. Fix the drive layout for the disk.
  2978. Arguments:
  2979. Return Value:
  2980. ERROR_SUCCESS if successful.
  2981. A Win32 error code on failure.
  2982. --*/
  2983. {
  2984. DWORD status;
  2985. DWORD index;
  2986. DWORD driveLayoutSize;
  2987. DWORD bytesPerTrack;
  2988. DWORD bytesPerCylinder;
  2989. PDRIVE_LAYOUT_INFORMATION driveLayout;
  2990. PPARTITION_INFORMATION partInfo;
  2991. BOOL success;
  2992. BOOL reset = FALSE;
  2993. DWORD returnLength;
  2994. DISK_GEOMETRY diskGeometry;
  2995. LARGE_INTEGER partOffset;
  2996. LARGE_INTEGER partLength;
  2997. LARGE_INTEGER partSize;
  2998. LARGE_INTEGER modulo;
  2999. if (argc > 1)
  3000. {
  3001. printf( "usage: <device> FixDisk [RESET]\n" );
  3002. return ERROR_INVALID_NAME;
  3003. }
  3004. if ( argc != 0 ) {
  3005. if ( !_stricmp( *argv, "reset" ) ) {
  3006. reset = TRUE;
  3007. }
  3008. }
  3009. driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
  3010. (sizeof(PARTITION_INFORMATION) * (1 + MAX_PARTITIONS));
  3011. driveLayout = LocalAlloc( LMEM_FIXED, driveLayoutSize );
  3012. if ( !driveLayout ) {
  3013. printf("FixDisk, failed to allocate drive layout info.\n");
  3014. return(ERROR_OUTOFMEMORY);
  3015. }
  3016. //
  3017. // Read the drive capacity to get bytesPerSector and bytesPerCylinder.
  3018. //
  3019. success = DeviceIoControl( fileHandle,
  3020. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  3021. NULL,
  3022. 0,
  3023. &diskGeometry,
  3024. sizeof(DISK_GEOMETRY),
  3025. &returnLength,
  3026. FALSE );
  3027. if ( !success ) {
  3028. printf("FixDriveLayout, error reading drive capacity. Error: %u.\n",
  3029. status = GetLastError());
  3030. LocalFree( driveLayout );
  3031. return(status);
  3032. }
  3033. printf("FixDriveLayout, bps = %u, spt = %u, tpc = %u.\n",
  3034. diskGeometry.BytesPerSector, diskGeometry.SectorsPerTrack,
  3035. diskGeometry.TracksPerCylinder);
  3036. //
  3037. // If read of the partition table originally failed, then we rebuild
  3038. // it!
  3039. //
  3040. if ( reset ) {
  3041. driveLayout->PartitionCount = MAX_PARTITIONS;
  3042. driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
  3043. (MAX_PARTITIONS * sizeof(PARTITION_INFORMATION));
  3044. driveLayout->Signature = 2196277081;
  3045. bytesPerTrack = diskGeometry.SectorsPerTrack *
  3046. diskGeometry.BytesPerSector;
  3047. bytesPerCylinder = diskGeometry.TracksPerCylinder *
  3048. bytesPerTrack;
  3049. partInfo = &driveLayout->PartitionEntry[0];
  3050. partLength.QuadPart = bytesPerCylinder * diskGeometry.Cylinders.QuadPart;
  3051. //
  3052. // The partition offset is 1 track (in bytes).
  3053. // Size is media_size - offset, rounded down to cylinder boundary.
  3054. //
  3055. partOffset.QuadPart = bytesPerTrack;
  3056. partSize.QuadPart = partLength.QuadPart - partOffset.QuadPart;
  3057. modulo.QuadPart = (partOffset.QuadPart + partSize.QuadPart) %
  3058. bytesPerCylinder;
  3059. partSize.QuadPart -= modulo.QuadPart;
  3060. partInfo = driveLayout->PartitionEntry;
  3061. //
  3062. // Initialize first partition entry.
  3063. //
  3064. partInfo->RewritePartition = TRUE;
  3065. partInfo->PartitionType = PARTITION_IFS;
  3066. partInfo->BootIndicator = FALSE;
  3067. partInfo->StartingOffset.QuadPart = partOffset.QuadPart;
  3068. partInfo->PartitionLength.QuadPart = partSize.QuadPart;
  3069. partInfo->HiddenSectors = 0;
  3070. partInfo->PartitionNumber = 1;
  3071. //
  3072. // For now the remaining partition entries are unused.
  3073. //
  3074. for ( index = 1; index < driveLayout->PartitionCount; index++ ) {
  3075. partInfo = &driveLayout->PartitionEntry[index];
  3076. partInfo->PartitionType = PARTITION_ENTRY_UNUSED;
  3077. partInfo->RewritePartition = TRUE;
  3078. partInfo->BootIndicator = FALSE;
  3079. partInfo->StartingOffset.QuadPart = 0;
  3080. partInfo->PartitionLength.QuadPart = 0;
  3081. partInfo->HiddenSectors = 0;
  3082. partInfo->PartitionNumber = 0;
  3083. }
  3084. } else {
  3085. //
  3086. // For now, the remaining partition entries are unused.
  3087. //
  3088. for ( index = 0; index < driveLayout->PartitionCount; index++ ) {
  3089. partInfo = &driveLayout->PartitionEntry[index];
  3090. partInfo->RewritePartition = TRUE;
  3091. partInfo->PartitionNumber = index+1;
  3092. }
  3093. #if 0
  3094. //
  3095. // Recalculate the starting offset for the extended partitions.
  3096. //
  3097. for ( index = 0; index < driveLayout->PartitionCount; index++ ) {
  3098. LARGE_INTEGER extendedOffset;
  3099. LARGE_INTEGER bytesPerSector;
  3100. bytesPerSector.QuadPart = diskGeometry.BytesPerSector;
  3101. extendedOffset.QuadPart = 0;
  3102. partInfo = &driveLayout->PartitionEntry[index];
  3103. partInfo->RewritePartition = TRUE;
  3104. if ( IsContainerPartition(partInfo->PartitionType) ) {
  3105. //
  3106. // If this is the first extended partition, then remember
  3107. // the offset to added to the next partition.
  3108. //
  3109. if ( extendedOffset.QuadPart == 0 ) {
  3110. extendedOffset.QuadPart = bytesPerSector.QuadPart *
  3111. (LONGLONG)partInfo->HiddenSectors;
  3112. } else {
  3113. //
  3114. // We need to recalculate this extended partition's starting
  3115. // offset based on the current 'HiddenSectors' field and
  3116. // the first extended partition's offset.
  3117. //
  3118. partInfo->StartingOffset.QuadPart = extendedOffset.QuadPart
  3119. + (bytesPerSector.QuadPart *
  3120. (LONGLONG)partInfo->HiddenSectors);
  3121. partInfo->HiddenSectors = 0;
  3122. }
  3123. }
  3124. }
  3125. #endif
  3126. }
  3127. //
  3128. // Now set the new partition information.
  3129. //
  3130. success = DeviceIoControl( fileHandle,
  3131. IOCTL_DISK_SET_DRIVE_LAYOUT,
  3132. driveLayout,
  3133. driveLayoutSize,
  3134. NULL,
  3135. 0,
  3136. &returnLength,
  3137. FALSE );
  3138. if ( !success ) {
  3139. printf("FixDisk, error setting partition information. Error: %u.\n",
  3140. status = GetLastError() );
  3141. LocalFree( driveLayout );
  3142. return(status);
  3143. }
  3144. LocalFree( driveLayout );
  3145. return(ERROR_SUCCESS);
  3146. } // FixDisk
  3147. static DWORD
  3148. FixDriveLayout(
  3149. HANDLE fileHandle,
  3150. int argc,
  3151. char *argv[]
  3152. )
  3153. /*++
  3154. Routine Description:
  3155. Fix the (broken) disk.
  3156. Arguments:
  3157. Return Value:
  3158. ERROR_SUCCESS if successful.
  3159. A Win32 error code on failure.
  3160. --*/
  3161. {
  3162. DWORD status;
  3163. DWORD index;
  3164. DWORD driveLayoutSize;
  3165. DWORD bytesPerTrack;
  3166. DWORD bytesPerCylinder;
  3167. PDRIVE_LAYOUT_INFORMATION driveLayout;
  3168. PPARTITION_INFORMATION partInfo;
  3169. BOOL success;
  3170. DWORD returnLength;
  3171. DISK_GEOMETRY diskGeometry;
  3172. LARGE_INTEGER partOffset;
  3173. LARGE_INTEGER partLength;
  3174. LARGE_INTEGER partSize;
  3175. LARGE_INTEGER modulo;
  3176. driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
  3177. (sizeof(PARTITION_INFORMATION) * 2 * MAX_PARTITIONS);
  3178. driveLayout = LocalAlloc( LMEM_FIXED, driveLayoutSize );
  3179. if ( !driveLayout ) {
  3180. printf("FixDriveLayout, failed to allocate drive layout info.\n");
  3181. return(ERROR_OUTOFMEMORY);
  3182. }
  3183. success = DeviceIoControl( fileHandle,
  3184. IOCTL_DISK_GET_DRIVE_LAYOUT,
  3185. NULL,
  3186. 0,
  3187. driveLayout,
  3188. driveLayoutSize,
  3189. &returnLength,
  3190. FALSE );
  3191. if ( !success ) {
  3192. printf("FixDriveLayout, error getting partition information. Error: %u.\n",
  3193. status = GetLastError() );
  3194. LocalFree( driveLayout );
  3195. return(status);
  3196. }
  3197. printf("FixDriveLayout, disk signature is %u, partition count is %u.\n",
  3198. driveLayout->Signature, driveLayout->PartitionCount);
  3199. //
  3200. // Read the drive capacity to get bytesPerSector and bytesPerCylinder.
  3201. //
  3202. success = DeviceIoControl( fileHandle,
  3203. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  3204. NULL,
  3205. 0,
  3206. &diskGeometry,
  3207. sizeof(DISK_GEOMETRY),
  3208. &returnLength,
  3209. FALSE );
  3210. if ( !success ) {
  3211. printf("FixDriveLayout, error reading drive capacity. Error: %u.\n",
  3212. status = GetLastError());
  3213. LocalFree( driveLayout );
  3214. return(status);
  3215. }
  3216. printf("FixDriveLayout, bps = %u, spt = %u, tpc = %u.\n",
  3217. diskGeometry.BytesPerSector, diskGeometry.SectorsPerTrack,
  3218. diskGeometry.TracksPerCylinder);
  3219. //
  3220. // If read of the partition table originally failed, then we rebuild
  3221. // it!
  3222. //
  3223. if ( !driveLayout->PartitionCount ) {
  3224. driveLayout->PartitionCount = MAX_PARTITIONS;
  3225. bytesPerTrack = diskGeometry.SectorsPerTrack *
  3226. diskGeometry.BytesPerSector;
  3227. bytesPerCylinder = diskGeometry.TracksPerCylinder *
  3228. bytesPerTrack;
  3229. partInfo = &driveLayout->PartitionEntry[0];
  3230. partLength.QuadPart = partInfo->PartitionLength.QuadPart;
  3231. //
  3232. // The partition offset is 1 track (in bytes).
  3233. // Size is media_size - offset, rounded down to cylinder boundary.
  3234. //
  3235. partOffset.QuadPart = bytesPerTrack;
  3236. partSize.QuadPart = partLength.QuadPart - partOffset.QuadPart;
  3237. modulo.QuadPart = (partOffset.QuadPart + partSize.QuadPart) %
  3238. bytesPerCylinder;
  3239. partSize.QuadPart -= modulo.QuadPart;
  3240. partInfo = driveLayout->PartitionEntry;
  3241. //
  3242. // Initialize first partition entry.
  3243. //
  3244. partInfo->RewritePartition = TRUE;
  3245. partInfo->PartitionType = PARTITION_HUGE;
  3246. partInfo->BootIndicator = FALSE;
  3247. partInfo->StartingOffset.QuadPart = partOffset.QuadPart;
  3248. partInfo->PartitionLength.QuadPart = partSize.QuadPart;
  3249. partInfo->HiddenSectors = 0;
  3250. partInfo->PartitionNumber = 0;
  3251. //
  3252. // For now, the remaining partition entries are unused.
  3253. //
  3254. for ( index = 1; index < MAX_PARTITIONS; index++ ) {
  3255. partInfo->RewritePartition = TRUE;
  3256. partInfo->PartitionType = PARTITION_ENTRY_UNUSED;
  3257. partInfo->BootIndicator = FALSE;
  3258. partInfo->StartingOffset.QuadPart = 0;
  3259. partInfo->PartitionLength.QuadPart = 0;
  3260. partInfo->HiddenSectors = 0;
  3261. partInfo->PartitionNumber = 0;
  3262. }
  3263. } else {
  3264. //
  3265. // Recalculate the starting offset for the extended partitions.
  3266. //
  3267. for ( index = 0; index < driveLayout->PartitionCount; index++ ) {
  3268. LARGE_INTEGER extendedOffset;
  3269. LARGE_INTEGER bytesPerSector;
  3270. bytesPerSector.QuadPart = diskGeometry.BytesPerSector;
  3271. extendedOffset.QuadPart = 0;
  3272. partInfo = &driveLayout->PartitionEntry[index];
  3273. partInfo->RewritePartition = TRUE;
  3274. if ( IsContainerPartition(partInfo->PartitionType) ) {
  3275. //
  3276. // If this is the first extended partition, then remember
  3277. // the offset to added to the next partition.
  3278. //
  3279. if ( extendedOffset.QuadPart == 0 ) {
  3280. extendedOffset.QuadPart = bytesPerSector.QuadPart *
  3281. (LONGLONG)partInfo->HiddenSectors;
  3282. } else {
  3283. //
  3284. // We need to recalculate this extended partition's starting
  3285. // offset based on the current 'HiddenSectors' field and
  3286. // the first extended partition's offset.
  3287. //
  3288. partInfo->StartingOffset.QuadPart = extendedOffset.QuadPart
  3289. + (bytesPerSector.QuadPart *
  3290. (LONGLONG)partInfo->HiddenSectors);
  3291. partInfo->HiddenSectors = 0;
  3292. }
  3293. }
  3294. }
  3295. }
  3296. //
  3297. // Now set the new partition information.
  3298. //
  3299. success = DeviceIoControl( fileHandle,
  3300. IOCTL_DISK_SET_DRIVE_LAYOUT,
  3301. driveLayout,
  3302. driveLayoutSize,
  3303. NULL,
  3304. 0,
  3305. &returnLength,
  3306. FALSE );
  3307. if ( !success ) {
  3308. printf("FixDriveLayout, error setting partition information. Error: %u.\n",
  3309. status = GetLastError() );
  3310. LocalFree( driveLayout );
  3311. return(status);
  3312. }
  3313. LocalFree( driveLayout );
  3314. return(ERROR_SUCCESS);
  3315. } // FixDriveLayout
  3316. static DWORD
  3317. GetDriveLetter(
  3318. PUCHAR deviceNameString
  3319. )
  3320. {
  3321. UCHAR driveLetter;
  3322. WCHAR deviceName[MAX_PATH];
  3323. NTSTATUS status;
  3324. mbstowcs( deviceName, deviceNameString, strlen(deviceNameString) );
  3325. status = GetAssignedLetter(deviceName, &driveLetter);
  3326. if ( NT_SUCCESS(status) ) {
  3327. if (driveLetter) {
  3328. wprintf(L"%ws ----> %c:\n", deviceName, driveLetter);
  3329. } else {
  3330. wprintf(L"%ws has no drive letter\n", deviceName);
  3331. }
  3332. }
  3333. return RtlNtStatusToDosError( status );
  3334. }
  3335. static void
  3336. usage(
  3337. char *programName
  3338. )
  3339. /*++
  3340. Routine Description:
  3341. Description
  3342. Arguments:
  3343. None
  3344. Return Value:
  3345. None
  3346. --*/
  3347. {
  3348. printf( "usage: %s target_device command\n", programName );
  3349. printf( "commands:\n" );
  3350. printf( "\tReset\n" );
  3351. printf( "\tReserve\n" );
  3352. printf( "\tRelease\n" );
  3353. printf( "\tOnline\n" );
  3354. printf( "\tOffline\n" );
  3355. printf( "\tClaim\n" );
  3356. printf( "\tEjectVolumes\n");
  3357. printf( "\tHoldIO\n" );
  3358. printf( "\tResumeIO\n" );
  3359. printf( "\tPokeMountMgr\n" );
  3360. printf( "\tEnumMounts\n" );
  3361. printf( "\tEnumExtents\n" );
  3362. printf( "\tEnumNodes\n" );
  3363. printf( "\tEnumDisks\n" );
  3364. printf( "\tGetDiskGeometry\n" );
  3365. printf( "\tGetScsiAddress\n" );
  3366. printf( "\tGetDriveLayout\n" );
  3367. printf( "\tGetDriveLayoutEx\n");
  3368. printf( "\tSetDriveLayout\n" );
  3369. printf( "\tGetPartitionInfo\n" );
  3370. printf( "\tGetVolumeInfo\n" );
  3371. printf( "\tGetDriveLetter\n" );
  3372. printf( "\tGetSerialNumber\n");
  3373. printf( "\tAssignLetters\n" );
  3374. printf( "\tRemoveLetters\n" );
  3375. printf( "\tReadSector\n" );
  3376. printf( "\tTest\n" );
  3377. printf( "\tNt4Capable\n" );
  3378. printf( "\tAttach [ClusDisk0 device] \n" );
  3379. printf( "\tDetach [ClusDisk0 device] \n" );
  3380. printf( "\tStartReserve [ClusDisk0 device] \n" );
  3381. printf( "\tStopReserve [ClusDisk0 device] \n" );
  3382. printf( "\tActive [ClusDisk0 device] \n" );
  3383. printf( "target_device wildcards: \n" );
  3384. printf( "\tAll physical devices: use p* \n" );
  3385. printf( "\tAll logical devices: use l* or * \n" );
  3386. }
  3387. NTSTATUS
  3388. GetVolumeInformationFromHandle(
  3389. HANDLE Handle
  3390. )
  3391. {
  3392. NTSTATUS Status;
  3393. IO_STATUS_BLOCK IoStatusBlock;
  3394. UCHAR VolumeInfoBuffer[ sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(WCHAR) * MAX_PATH ];
  3395. UCHAR AttrInfoBuffer[ sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + sizeof(WCHAR) * MAX_PATH ];
  3396. ULONG VolumeInfoLength = sizeof(VolumeInfoBuffer);
  3397. ULONG AttributeInfoLength = sizeof(AttrInfoBuffer);
  3398. PFILE_FS_VOLUME_INFORMATION VolumeInfo = (PFILE_FS_VOLUME_INFORMATION)VolumeInfoBuffer;
  3399. PFILE_FS_ATTRIBUTE_INFORMATION AttributeInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)AttrInfoBuffer;
  3400. ZeroMemory(VolumeInfoBuffer, (sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(WCHAR) * MAX_PATH));
  3401. ZeroMemory(AttrInfoBuffer, (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + sizeof(WCHAR) * MAX_PATH));
  3402. Status = NtQueryVolumeInformationFile(
  3403. Handle,
  3404. &IoStatusBlock,
  3405. VolumeInfo,
  3406. VolumeInfoLength,
  3407. FileFsVolumeInformation
  3408. );
  3409. if ( !NT_SUCCESS(Status) ) {
  3410. return Status;
  3411. }
  3412. Status = NtQueryVolumeInformationFile(
  3413. Handle,
  3414. &IoStatusBlock,
  3415. AttributeInfo,
  3416. AttributeInfoLength,
  3417. FileFsAttributeInformation
  3418. );
  3419. if ( !NT_SUCCESS(Status) ) {
  3420. return Status;
  3421. }
  3422. AttributeInfo->FileSystemName[AttributeInfo->FileSystemNameLength] = 0;
  3423. VolumeInfo->VolumeLabel[VolumeInfo->VolumeLabelLength] = 0;
  3424. printf("\nGetVolumeInformationFromHandle data: \n");
  3425. printf("Volume information: \n");
  3426. printf(" VolumeCreationTime 0x%lx : %lx \n",
  3427. VolumeInfo->VolumeCreationTime.HighPart,
  3428. VolumeInfo->VolumeCreationTime.LowPart);
  3429. printf(" VolumeSerialNumber 0x%lx \n", VolumeInfo->VolumeSerialNumber);
  3430. printf(" VolumeLabelLength 0x%lx \n", VolumeInfo->VolumeLabelLength);
  3431. printf(" SupportsObjects (BOOL) 0x%lx \n", VolumeInfo->SupportsObjects);
  3432. printf(" VolumeLabel %ws \n", VolumeInfo->VolumeLabel);
  3433. printf("Attribute Information: \n");
  3434. printf(" FileSystemAttributes (Flags) 0x%lx \n", AttributeInfo->FileSystemAttributes);
  3435. printf(" MaximumComponentNameLength 0x%lx \n", AttributeInfo->MaximumComponentNameLength);
  3436. printf(" FileSystemNameLength 0x%lx \n", AttributeInfo->FileSystemNameLength);
  3437. printf(" FileSystemName %ws \n\n", AttributeInfo->FileSystemName);
  3438. return STATUS_SUCCESS;
  3439. }
  3440. #define FIRST_SHOT_SIZE 512
  3441. PVOID
  3442. DoIoctlAndAllocate(
  3443. IN HANDLE FileHandle,
  3444. IN DWORD IoControlCode,
  3445. IN PVOID InBuf,
  3446. IN ULONG InBufSize,
  3447. OUT PDWORD BytesReturned
  3448. )
  3449. {
  3450. UCHAR firstShot[ FIRST_SHOT_SIZE ];
  3451. DWORD status = ERROR_SUCCESS;
  3452. BOOL success;
  3453. DWORD outBufSize;
  3454. PVOID outBuf = 0;
  3455. DWORD bytesReturned;
  3456. success = DeviceIoControl( FileHandle,
  3457. IoControlCode,
  3458. InBuf,
  3459. InBufSize,
  3460. &firstShot,
  3461. sizeof(firstShot),
  3462. &bytesReturned,
  3463. (LPOVERLAPPED) NULL );
  3464. if ( success ) {
  3465. outBufSize = bytesReturned;
  3466. outBuf = malloc( outBufSize );
  3467. if (!outBuf) {
  3468. status = ERROR_OUTOFMEMORY;
  3469. } else {
  3470. RtlCopyMemory(outBuf, &firstShot, outBufSize);
  3471. status = ERROR_SUCCESS;
  3472. }
  3473. } else {
  3474. outBufSize = sizeof(firstShot);
  3475. for(;;) {
  3476. status = GetLastError();
  3477. //
  3478. // If it is not a buffer size related error, then we cannot do much
  3479. //
  3480. if ( status != ERROR_INSUFFICIENT_BUFFER && status != ERROR_MORE_DATA) {
  3481. break;
  3482. }
  3483. //
  3484. // Otherwise, try an outbut buffer twice the previous size
  3485. //
  3486. outBufSize *= 2;
  3487. outBuf = malloc( outBufSize );
  3488. if ( !outBuf ) {
  3489. status = ERROR_OUTOFMEMORY;
  3490. break;
  3491. }
  3492. success = DeviceIoControl( FileHandle,
  3493. IoControlCode,
  3494. InBuf,
  3495. InBufSize,
  3496. outBuf,
  3497. outBufSize,
  3498. &bytesReturned,
  3499. (LPOVERLAPPED) NULL );
  3500. if (success) {
  3501. status = ERROR_SUCCESS;
  3502. break;
  3503. }
  3504. free( outBuf );
  3505. }
  3506. }
  3507. if (status != ERROR_SUCCESS) {
  3508. free( outBuf ); // free( 0 ) is legal //
  3509. outBuf = 0;
  3510. bytesReturned = 0;
  3511. }
  3512. SetLastError( status );
  3513. *BytesReturned = bytesReturned;
  3514. return outBuf;
  3515. }
  3516. #define OUTPUT_BUFFER_LEN (1024)
  3517. #define INPUT_BUFFER_LEN (sizeof(MOUNTMGR_MOUNT_POINT) + 2 * MAX_PATH * sizeof(WCHAR))
  3518. static
  3519. NTSTATUS
  3520. GetAssignedLetterM (
  3521. IN HANDLE MountMgrHandle,
  3522. IN PWCHAR deviceName,
  3523. OUT PCHAR driveLetter )
  3524. /*++
  3525. Routine Description:
  3526. Get an assigned drive letter from MountMgr, if any
  3527. Inputs:
  3528. MountMgrHandle -
  3529. deviceName -
  3530. driveLetter - receives drive letter
  3531. Return value:
  3532. STATUS_SUCCESS - on success
  3533. NTSTATUS code - on failure
  3534. --*/
  3535. {
  3536. DWORD status = STATUS_SUCCESS;
  3537. PMOUNTMGR_MOUNT_POINT input = NULL;
  3538. PMOUNTMGR_MOUNT_POINTS output = NULL;
  3539. PMOUNTMGR_MOUNT_POINT out;
  3540. DWORD len = wcslen( deviceName ) * sizeof(WCHAR);
  3541. DWORD bytesReturned;
  3542. DWORD idx;
  3543. DWORD outputLen;
  3544. DWORD inputLen;
  3545. WCHAR wc;
  3546. inputLen = INPUT_BUFFER_LEN;
  3547. input = LocalAlloc( LPTR, inputLen );
  3548. if ( !input ) {
  3549. goto FnExit;
  3550. }
  3551. input->SymbolicLinkNameOffset = 0;
  3552. input->SymbolicLinkNameLength = 0;
  3553. input->UniqueIdOffset = 0;
  3554. input->UniqueIdLength = 0;
  3555. input->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
  3556. input->DeviceNameLength = (USHORT) len;
  3557. RtlCopyMemory((PCHAR)input + input->DeviceNameOffset,
  3558. deviceName, len );
  3559. if (len > sizeof(WCHAR) && deviceName[1] == L'\\') {
  3560. // convert Dos name to NT name
  3561. ((PWCHAR)(input + input->DeviceNameOffset))[1] = L'?';
  3562. }
  3563. outputLen = OUTPUT_BUFFER_LEN;
  3564. output = LocalAlloc( LPTR, outputLen );
  3565. if ( !output ) {
  3566. goto FnExit;
  3567. }
  3568. status = DevfileIoctl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
  3569. input, inputLen, output, outputLen, &bytesReturned);
  3570. if ( STATUS_BUFFER_OVERFLOW == status ) {
  3571. outputLen = output->Size;
  3572. LocalFree( output );
  3573. output = LocalAlloc( LPTR, outputLen );
  3574. if ( !output ) {
  3575. goto FnExit;
  3576. }
  3577. status = DevfileIoctl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
  3578. input, inputLen, output, outputLen, &bytesReturned);
  3579. }
  3580. if ( !NT_SUCCESS(status) ) {
  3581. goto FnExit;
  3582. }
  3583. if (driveLetter) {
  3584. *driveLetter = 0;
  3585. }
  3586. for ( idx = 0; idx < output->NumberOfMountPoints; ++idx ) {
  3587. out = &output->MountPoints[idx];
  3588. if (out->SymbolicLinkNameLength/sizeof(WCHAR) == 14 &&
  3589. (_wcsnicmp((PWCHAR)((PCHAR)output + out->SymbolicLinkNameOffset), L"\\DosDevices\\", 12) == 0) &&
  3590. L':' == *((PCHAR)output + out->SymbolicLinkNameOffset + 13*sizeof(WCHAR)) )
  3591. {
  3592. wc = *((PCHAR)output + out->SymbolicLinkNameOffset + 12*sizeof(WCHAR));
  3593. if (driveLetter && out->UniqueIdLength) {
  3594. *driveLetter = (CHAR)toupper((UCHAR)wc);
  3595. break;
  3596. }
  3597. }
  3598. }
  3599. FnExit:
  3600. if ( output ) {
  3601. LocalFree( output );
  3602. }
  3603. if ( input ) {
  3604. LocalFree( input );
  3605. }
  3606. return status;
  3607. }
  3608. NTSTATUS
  3609. GetAssignedLetter (
  3610. PWCHAR deviceName,
  3611. PCHAR driveLetter )
  3612. {
  3613. HANDLE MountMgrHandle;
  3614. DWORD status = DevfileOpen( &MountMgrHandle, MOUNTMGR_DEVICE_NAME );
  3615. if (driveLetter) {
  3616. *driveLetter = 0;
  3617. }
  3618. if ( NT_SUCCESS(status) ) {
  3619. status = GetAssignedLetterM(MountMgrHandle, deviceName, driveLetter);
  3620. DevfileClose(MountMgrHandle);
  3621. }
  3622. return status;
  3623. }
  3624. DWORD
  3625. PokeMountMgr (
  3626. VOID
  3627. )
  3628. {
  3629. HANDLE MountMgrHandle;
  3630. NTSTATUS ntStatus = DevfileOpen( &MountMgrHandle, MOUNTMGR_DEVICE_NAME );
  3631. DWORD status = ERROR_SUCCESS;
  3632. if ( NT_SUCCESS(ntStatus) ) {
  3633. BOOL success;
  3634. DWORD bytesReturned;
  3635. printf("About to call MOUNTMGR_CHECK_UNPROCESSED_VOLUMES...");
  3636. success = DeviceIoControl( MountMgrHandle,
  3637. IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES,
  3638. NULL,
  3639. 0,
  3640. NULL,
  3641. 0,
  3642. &bytesReturned,
  3643. FALSE );
  3644. printf("complete.\n");
  3645. if (!success) {
  3646. status = GetLastError();
  3647. }
  3648. DevfileClose(MountMgrHandle);
  3649. } else {
  3650. status = RtlNtStatusToDosError(ntStatus);
  3651. }
  3652. return status;
  3653. }
  3654. VOID
  3655. PrintError(
  3656. IN DWORD ErrorCode
  3657. )
  3658. {
  3659. LPVOID lpMsgBuf;
  3660. ULONG count;
  3661. count = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  3662. FORMAT_MESSAGE_FROM_SYSTEM |
  3663. FORMAT_MESSAGE_IGNORE_INSERTS,
  3664. NULL,
  3665. ErrorCode,
  3666. 0,
  3667. (LPTSTR) &lpMsgBuf,
  3668. 0,
  3669. NULL
  3670. );
  3671. if (count != 0) {
  3672. printf(" (%d) %s\n", ErrorCode, (LPCTSTR) lpMsgBuf);
  3673. LocalFree( lpMsgBuf );
  3674. } else {
  3675. printf("Format message failed. Error: %d\n", GetLastError());
  3676. }
  3677. } // PrintError
  3678. DWORD
  3679. GetSerialNumber(
  3680. HANDLE FileHandle
  3681. )
  3682. {
  3683. PSTORAGE_DEVICE_DESCRIPTOR descriptor = NULL;
  3684. PCHAR sigString;
  3685. DWORD dwError = NO_ERROR;
  3686. DWORD descriptorSize;
  3687. DWORD bytesReturned;
  3688. STORAGE_PROPERTY_QUERY propQuery;
  3689. descriptorSize = sizeof( STORAGE_DEVICE_DESCRIPTOR) + 2048;
  3690. descriptor = LocalAlloc( LPTR, descriptorSize );
  3691. if ( !descriptor ) {
  3692. dwError = GetLastError();
  3693. printf("Unable to allocate output buffer: %d \n", dwError);
  3694. PrintError( dwError );
  3695. goto FnExit;
  3696. }
  3697. ZeroMemory( &propQuery, sizeof( propQuery ) );
  3698. propQuery.PropertyId = StorageDeviceProperty;
  3699. propQuery.QueryType = PropertyStandardQuery;
  3700. if ( !DeviceIoControl( FileHandle,
  3701. IOCTL_STORAGE_QUERY_PROPERTY,
  3702. &propQuery,
  3703. sizeof(propQuery),
  3704. descriptor,
  3705. descriptorSize,
  3706. &bytesReturned,
  3707. NULL ) ) {
  3708. dwError = GetLastError();
  3709. printf("IOCTL_STORAGE_QUERY_PROPERTY failed: %d \n", dwError);
  3710. PrintError( dwError );
  3711. goto FnExit;
  3712. }
  3713. if ( !bytesReturned || bytesReturned < sizeof( STORAGE_DEVICE_DESCRIPTOR ) ) {
  3714. printf("Invalid byte length returned: %d \n", bytesReturned);
  3715. goto FnExit;
  3716. }
  3717. //
  3718. // IA64 sometimes returns -1 for SerialNumberOffset.
  3719. //
  3720. if ( 0 == descriptor->SerialNumberOffset ||
  3721. descriptor->SerialNumberOffset > descriptor->Size ) {
  3722. printf("No serial number information available \n");
  3723. goto FnExit;
  3724. }
  3725. //
  3726. // Serial number string is a zero terminated ASCII string.
  3727. //
  3728. // The header ntddstor.h says the for devices with no serial number,
  3729. // the offset will be zero. This doesn't seem to be true.
  3730. //
  3731. // For devices with no serial number, it looks like a string with a single
  3732. // null character '\0' is returned.
  3733. //
  3734. sigString = (PCHAR)descriptor + (DWORD)descriptor->SerialNumberOffset;
  3735. if ( strlen(sigString) == 0) {
  3736. printf("Serial number: NULL string returned \n");
  3737. } else {
  3738. printf("Serial number: %s \n", sigString);
  3739. }
  3740. FnExit:
  3741. if ( descriptor ) {
  3742. LocalFree( descriptor );
  3743. }
  3744. return dwError;
  3745. } // GetSerialNumber