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

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