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

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
disktest.c
Abstract:
Abstract
Author:
Rod Gamache (rodga) 4-Mar-1996
Environment:
User Mode
Revision History:
--*/
#define INITGUID 1
//#include <windows.h>
#include <nt.h>
#include <ntdef.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <clusapi.h>
#include <ntddvol.h>
#include <mountie.h>
#include <mountmgr.h>
#include <partmgrp.h>
#include <devioctl.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
//#include <initguid.h>
#include <devguid.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include "clusdisk.h"
#include "disksp.h"
#include "diskarbp.h"
#include <clstrcmp.h>
#define _NTSRB_ // to keep srb.h from being included
#include <scsi.h>
#include <strsafe.h> // Should be included last.
#ifndef ClusterHashGuid
#define ClusterHashGuid(Guid) (((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[1] ^ ((PULONG) &Guid)[2] ^ ((PULONG) &Guid)[3])
#endif
#define DEVICE_CLUSDISK0 TEXT("\\Device\\ClusDisk0")
#define CLUSDISK_SRB_SIGNATURE "CLUSDISK"
//
// Routine to get drive layout table
//
BOOL
ClRtlGetDriveLayoutTable(
IN HANDLE hDisk,
OUT PDRIVE_LAYOUT_INFORMATION * DriveLayout,
OUT PDWORD InfoSize OPTIONAL
);
NTSTATUS
GetAssignedLetter (
PWCHAR deviceName,
PCHAR driveLetter
);
PVOID
DoIoctlAndAllocate(
IN HANDLE FileHandle,
IN DWORD IoControlCode,
IN PVOID InBuf,
IN ULONG InBufSize,
OUT PDWORD BytesReturned
);
PSTR PartitionName = "\\Device\\Harddisk%d\\Partition%d";
int __cdecl
main(
int argc,
char *argv[]
);
static DWORD
Reset(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
BreakReservation(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
Reserve(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
Release(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
Online(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
Offline(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
CheckUnclaimedPartitions(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
EjectVolumes(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
PokeMountMgr (
VOID
);
DWORD
EnumMounts(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
EnumExtents(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
EnumNodes(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
EnumDisks(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
GetDiskGeometry(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
GetScsiAddress(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
GetDriveLayout(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
GetDriveLayoutEx(
HANDLE fileHandle,
int argc,
char *argv[]
);
LPTSTR
BooleanToString(
BOOLEAN Value
);
void
FormatGuid(
GUID* Guid,
char* Str,
int StrCharMax
);
DWORD
GetVolumeInfo(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
SetDriveLayout(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
Attach(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
Detach(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
GetPartitionInfo(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
ReadSector(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
ReadSectorViaIoctl(
HANDLE fileHandle,
int argc,
char *argv[]
);
#if 0
DWORD
FixDisk(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
FixDriveLayout(
HANDLE fileHandle,
int argc,
char *argv[]
);
#endif
static DWORD
StartReserve(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
StopReserve(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
Active(
HANDLE fileHandle,
int argc,
char *argv[]
);
DWORD
Capable(
HANDLE fileHandle,
int argc,
char *argv[]
);
BOOL
IsClusDiskLoaded(
);
BOOL
IsClusterCapable(
HANDLE Scsi
);
static DWORD
Test(
HANDLE fileHandle,
int argc,
char *argv[]
);
static DWORD
GetDriveLetter(
PUCHAR deviceNameString
);
NTSTATUS
GetVolumeInformationFromHandle(
HANDLE Handle
);
VOID
PrintError(
IN DWORD ErrorCode
);
DWORD
GetSerialNumber(
HANDLE FileHandle
);
PCHAR
DiskStateToString(
UCHAR DiskState
);
DWORD
UpdateDiskProperties(
HANDLE fileHandle
);
DWORD
SetState(
HANDLE FileHandle,
UCHAR NewState
);
static DWORD
GetState(
HANDLE fileHandle,
int argc,
char *argv[]
);
static void
usage(
char *programName
);
BOOL
IsDeviceClustered(
HANDLE Device
);
DWORD
GetReserveInfo(
HANDLE FileHandle
);
int
ExecuteCommand(
IN PSTR Command,
IN int argc,
IN char *argv[]
);
//
// Global data
//
PSTR DeviceName;
PSTR ProgramName;
int __cdecl
main(
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
#define MAX_DEVICES 99
DWORD logicalDrives;
DWORD letter;
DWORD index;
PSTR command;
UCHAR buffer[128];
DWORD status;
HANDLE handle;
if (argc < 3)
{
usage( argv[0] );
return -1;
}
argc--;
ProgramName = *argv++; // skip program name
argc--;
DeviceName = *argv++;
argc--;
command = *argv++;
if ( ( CompareString( LOCALE_INVARIANT,
NORM_IGNORECASE,
DeviceName,
-1,
"*",
-1 ) == CSTR_EQUAL ) ||
( CompareString( LOCALE_INVARIANT,
NORM_IGNORECASE,
DeviceName,
-1,
"l*",
-1 ) == CSTR_EQUAL ) ) {
// this is a wildcard request for logical drives.
logicalDrives = GetLogicalDrives();
for ( index = 0; index < 27; index++ ) {
letter = 'A' + index;
if ( (logicalDrives & 1) ) {
(VOID) StringCchPrintf( buffer, RTL_NUMBER_OF(buffer), "%c:", letter );
printf( "\n ** For device ** %s\n", buffer );
DeviceName = buffer;
status = ExecuteCommand(
command,
argc,
argv );
// Stop only for invalid option...
if ( -1 == status ) {
break;
}
}
logicalDrives = logicalDrives >> 1;
} // for
} else if ( CompareString( LOCALE_INVARIANT,
NORM_IGNORECASE,
DeviceName,
-1,
"p*",
-1 ) == CSTR_EQUAL ) {
for ( index = 0; index < MAX_DEVICES; index++ ) {
DWORD accessMode = GENERIC_READ;
DWORD shareMode = FILE_SHARE_READ;
(VOID) StringCchPrintf( buffer, RTL_NUMBER_OF(buffer), "\\\\.\\PhysicalDrive%u", index );
handle = CreateFile(
buffer,
shareMode,
shareMode,
NULL,
OPEN_EXISTING,
0,
NULL );
status = ERROR_INVALID_HANDLE;
if ( handle != INVALID_HANDLE_VALUE ) {
CloseHandle( handle );
status = ERROR_SUCCESS;
printf( "\n ** For device ** %s\n", buffer );
DeviceName = (PSTR)buffer;
status = ExecuteCommand(
command,
argc,
argv );
// Stop only for invalid option...
if ( -1 == status ) {
break;
}
}
}
} else {
status = ExecuteCommand(
command,
argc,
argv );
}
return(status);
}
int
ExecuteCommand(
IN PSTR Command,
IN int argc,
IN char *argv[]
)
{
PSTR device;
HANDLE fileHandle;
DWORD accessMode, shareMode;
DWORD errorCode;
BOOL failed = FALSE;
UCHAR deviceNameString[128];
DWORD logicalDrives;
DWORD letter;
DWORD index;
NTSTATUS ntStatus;
ANSI_STRING objName;
UNICODE_STRING unicodeName;
OBJECT_ATTRIBUTES objAttributes;
IO_STATUS_BLOCK ioStatusBlock;
//
// Note it is important to access the device with 0 access mode so that
// the file open code won't do extra I/O to the device
//
shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
accessMode = GENERIC_READ | GENERIC_WRITE;
if ( FAILED( StringCchCopy( deviceNameString,
RTL_NUMBER_OF(deviceNameString),
"\\\\.\\" ) ) ) {
return -1;
}
if ( FAILED( StringCchCat( deviceNameString,
RTL_NUMBER_OF(deviceNameString),
DeviceName ) ) ) {
return -1;
}
fileHandle = CreateFile(deviceNameString,
accessMode,
shareMode,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( fileHandle == INVALID_HANDLE_VALUE ) {
errorCode = GetLastError();
if ( (errorCode == ERROR_PATH_NOT_FOUND) ||
(errorCode == ERROR_FILE_NOT_FOUND) ) {
if ( FAILED( StringCchCopy( deviceNameString,
RTL_NUMBER_OF(deviceNameString),
"\\Device\\" ) ) ) {
return -1;
}
if ( FAILED( StringCchCat( deviceNameString,
RTL_NUMBER_OF(deviceNameString),
DeviceName ) ) ) {
return -1;
}
RtlInitString(&objName, deviceNameString);
ntStatus = RtlAnsiStringToUnicodeString( &unicodeName,
&objName,
TRUE );
if ( !NT_SUCCESS(ntStatus) ) {
printf("Error converting device name %s to unicode. Error: %lx \n",
deviceNameString, ntStatus);
return -1;
}
InitializeObjectAttributes( &objAttributes,
&unicodeName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
ntStatus = NtCreateFile( &fileHandle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0 );
if ( !NT_SUCCESS(ntStatus) ) {
failed = TRUE;
}
RtlFreeUnicodeString( &unicodeName );
} else {
printf("Error opening %s. Error: %d \n",
deviceNameString, errorCode = GetLastError());
PrintError(errorCode);
return -1;
}
}
if ( failed ) {
if ( FAILED( StringCchCopy( deviceNameString,
RTL_NUMBER_OF(deviceNameString),
"\\Device\\" ) ) ) {
return -1;
}
if ( FAILED( StringCchCat( deviceNameString,
RTL_NUMBER_OF(deviceNameString),
DeviceName ) ) ) {
return -1;
}
RtlInitString(&objName, deviceNameString);
ntStatus = RtlAnsiStringToUnicodeString( &unicodeName,
&objName,
TRUE );
if ( !NT_SUCCESS(ntStatus) ) {
printf("Error converting device name %s to unicode. Error: %lx \n",
deviceNameString, ntStatus);
return -1;
}
InitializeObjectAttributes( &objAttributes,
&unicodeName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
ntStatus = NtCreateFile( &fileHandle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0 );
if ( !NT_SUCCESS(ntStatus) ) {
printf("Error opening device %ws. Error: %lx \n",
unicodeName.Buffer, ntStatus );
return -1;
}
RtlFreeUnicodeString( &unicodeName );
}
//printf("Accessing %s ... \n", deviceNameString);
if (!_stricmp( Command, "Reset" ))
errorCode = Reset( fileHandle, argc, argv );
else if (!_stricmp( Command, "Reserve" ))
errorCode = Reserve( fileHandle, argc, argv );
else if (!_stricmp( Command, "Release" ))
errorCode = Release( fileHandle, argc, argv );
else if (!_stricmp( Command, "BreakReserve" ))
errorCode = BreakReservation( fileHandle, argc, argv );
else if (!_stricmp( Command, "Online" ))
errorCode = Online( fileHandle, argc, argv );
else if (!_stricmp( Command, "Offline" ))
errorCode = Offline( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetState" ))
errorCode = GetState( fileHandle, argc, argv );
else if (!_stricmp( Command, "CheckUnclaimedPartitions" ))
errorCode = CheckUnclaimedPartitions( fileHandle, argc, argv );
else if (!_stricmp( Command, "EjectVolumes" ))
errorCode = EjectVolumes( fileHandle, argc, argv );
else if (!_stricmp( Command, "PokeMountMgr" ))
errorCode = PokeMountMgr();
else if (!_stricmp( Command, "EnumMounts" ))
errorCode = EnumMounts( fileHandle, argc, argv );
else if (!_stricmp( Command, "EnumExtents" ))
errorCode = EnumExtents( fileHandle, argc, argv );
else if (!_stricmp( Command, "EnumNodes" ))
errorCode = EnumNodes( fileHandle, argc, argv );
else if (!_stricmp( Command, "EnumDisks" ))
errorCode = EnumDisks( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetDiskGeometry" ))
errorCode = GetDiskGeometry( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetScsiAddress" ))
errorCode = GetScsiAddress( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetDriveLayout" ))
errorCode = GetDriveLayout( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetDriveLayoutEx" ))
errorCode = GetDriveLayoutEx( fileHandle, argc, argv );
else if (!_stricmp( Command, "SetDriveLayout" ))
errorCode = SetDriveLayout( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetPartitionInfo" ))
errorCode = GetPartitionInfo( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetVolumeInfo" ))
errorCode = GetVolumeInfo( fileHandle, argc, argv );
else if (!_stricmp( Command, "GetDriveLetter"))
errorCode = GetDriveLetter( deviceNameString );
else if (!_stricmp( Command, "GetSerialNumber"))
errorCode = GetSerialNumber( fileHandle );
else if (!_stricmp( Command, "GetReserveInfo"))
errorCode = GetReserveInfo( fileHandle );
else if (!_stricmp( Command, "ReadSector" ))
errorCode = ReadSector( fileHandle, argc, argv );
else if (!_stricmp( Command, "ReadSectorIoctl" ))
errorCode = ReadSectorViaIoctl( fileHandle, argc, argv );
else if (!_stricmp( Command, "Test" ))
errorCode = Test( fileHandle, argc, argv );
else if (!_stricmp( Command, "UpdateDiskProperties"))
errorCode = UpdateDiskProperties( fileHandle );
else if (!_stricmp( Command, "IsClustered" ))
errorCode = IsDeviceClustered( fileHandle );
else if (!_stricmp( Command, "Capable"))
errorCode = Capable( fileHandle, argc, argv );
else if (!_stricmp( Command, "Attach" ))
errorCode = Attach( fileHandle, argc, argv );
else if (!_stricmp( Command, "Detach" ))
errorCode = Detach( fileHandle, argc, argv );
#if 0
else if (!_stricmp( Command, "FixDisk" ))
errorCode = FixDisk( fileHandle, argc, argv );
else if (!_stricmp( Command, "FixDriveLayout" ))
errorCode = FixDriveLayout( fileHandle, argc, argv );
#endif
else if (!_stricmp( Command, "StartReserve" ))
errorCode = StartReserve( fileHandle, argc, argv );
else if (!_stricmp( Command, "StopReserve" ))
errorCode = StopReserve( fileHandle, argc, argv );
else if (!_stricmp( Command, "Active"))
errorCode = Active( fileHandle, argc, argv );
else
{
printf( "Invalid command.\n" );
CloseHandle( fileHandle );
usage( ProgramName );
return(-1);
}
CloseHandle( fileHandle );
if (errorCode != ERROR_SUCCESS) {
printf( "Error performing %s:, error %u.\n", Command, errorCode );
PrintError(errorCode);
printf( "%s: failed.\n", ProgramName );
}
return errorCode;
}
static DWORD
Reset(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
HANDLE hScsi = INVALID_HANDLE_VALUE;
DWORD dwError = NO_ERROR;
DWORD bytesReturned;
SCSI_ADDRESS scsiAddress;
STORAGE_BUS_RESET_REQUEST storageReset;
BOOL success;
UCHAR hbaName[64];
if (argc != 0)
{
printf( "usage: <device> Reset\n" );
dwError = ERROR_INVALID_NAME;
goto FnExit;
}
success = DeviceIoControl(fileHandle,
IOCTL_SCSI_GET_ADDRESS,
NULL,
0,
&scsiAddress,
sizeof(SCSI_ADDRESS),
&bytesReturned,
FALSE );
if ( !success ||
bytesReturned < sizeof(DWORD) ) {
dwError = GetLastError();
printf( "Error reading SCSI address, error = %u \n", dwError );
PrintError( dwError );
goto FnExit;
}
storageReset.PathId = scsiAddress.PathId;
success = DeviceIoControl( fileHandle,
IOCTL_STORAGE_RESET_BUS,
&storageReset,
sizeof(STORAGE_BUS_RESET_REQUEST),
NULL,
0,
&bytesReturned,
FALSE );
if ( !success ) {
dwError = GetLastError();
printf( "Error performing bus reset, error was %u \n", dwError );
PrintError( dwError );
printf( "Try sending reset IOCTL to HBA \n");
(VOID) StringCchPrintf( hbaName,
RTL_NUMBER_OF(hbaName),
"\\\\.\\Scsi%d:",
scsiAddress.PortNumber );
hScsi = CreateFile( hbaName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( INVALID_HANDLE_VALUE == hScsi ) {
dwError = GetLastError();
printf( "Error opening %s, error = %u \n", hbaName, dwError );
PrintError( dwError );
goto FnExit;
}
success = DeviceIoControl( hScsi,
IOCTL_STORAGE_RESET_BUS,
&storageReset,
sizeof(STORAGE_BUS_RESET_REQUEST),
NULL,
0,
&bytesReturned,
FALSE );
if ( !success ) {
dwError = GetLastError();
printf( "Error sending bus reset IOCTL, error was %u \n", dwError );
PrintError( dwError );
goto FnExit;
}
printf( "Bus reset successful \n" );
dwError = NO_ERROR;
// Fall through...
}
FnExit:
if ( INVALID_HANDLE_VALUE != hScsi ) {
CloseHandle( hScsi );
}
return dwError;
} // Reset
DWORD
BreakReservation(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
HANDLE hScsi = INVALID_HANDLE_VALUE;
DWORD dwError = NO_ERROR;
DWORD bytesReturned;
SCSI_ADDRESS scsiAddress;
BOOL success;
UCHAR hbaName[64];
if (argc != 0)
{
printf( "usage: <device> BreakReserve \n" );
dwError = ERROR_INVALID_NAME;
goto FnExit;
}
success = DeviceIoControl(fileHandle,
IOCTL_SCSI_GET_ADDRESS,
NULL,
0,
&scsiAddress,
sizeof(SCSI_ADDRESS),
&bytesReturned,
FALSE );
if ( !success ||
bytesReturned < sizeof(DWORD) ) {
dwError = GetLastError();
printf( "Error reading SCSI address, error = %u \n", dwError );
PrintError( dwError );
goto FnExit;
}
(VOID) StringCchPrintf( hbaName,
RTL_NUMBER_OF(hbaName),
"\\\\.\\Scsi%d:",
scsiAddress.PortNumber );
hScsi = CreateFile( hbaName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( INVALID_HANDLE_VALUE == hScsi ) {
dwError = GetLastError();
printf( "Error opening %s, error = %u \n", hbaName, dwError );
PrintError( dwError );
goto FnExit;
}
success = DeviceIoControl( hScsi,
IOCTL_STORAGE_BREAK_RESERVATION,
&scsiAddress,
sizeof(SCSI_ADDRESS),
NULL,
0,
&bytesReturned,
FALSE );
if ( !success ) {
dwError = GetLastError();
printf( "Error sending break reservation IOCTL, error was %u \n", dwError );
PrintError( dwError );
goto FnExit;
}
printf( "Break reservation successful \n" );
dwError = NO_ERROR;
// Fall through...
FnExit:
if ( INVALID_HANDLE_VALUE != hScsi ) {
CloseHandle( hScsi );
}
return dwError;
} // BreakReservation
static DWORD
Test(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode, bytesReturned;
if (argc != 0)
{
printf( "usage: <device> Test\n" );
return ERROR_INVALID_NAME;
}
success = DeviceIoControl(fileHandle,
IOCTL_DISK_CLUSTER_TEST,
NULL,
0,
NULL,
0,
&bytesReturned,
FALSE);
if (!success)
{
printf( "Error performing test; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
}
DWORD
Capable(
HANDLE Device,
int argc,
char *argv[]
)
/*++
Routine Description:
Determine if the disk is cluster capable.
Disks that are controlled by a miniport that supports
IOCTL_SCSI_MINIPORT_NOT_QUORUM_CAPABLE are NOT cluster
capable.
Arguments:
Device - physical disk, logical volume, or scsi adapter.
Return Value:
Win32 error value
--*/
{
DWORD dwError = ERROR_SUCCESS;
DWORD bytesReturned;
HANDLE scsiAdapter = INVALID_HANDLE_VALUE;
SCSI_ADDRESS scsiAddress;
CHAR scsiName[MAX_PATH];
if ( argc != 0 ) {
printf( "usage: <device> Capable \n" );
dwError = ERROR_INVALID_NAME;
goto FnExit;
}
//
// Open the scsi device hosting this device.
//
if ( !DeviceIoControl( Device,
IOCTL_SCSI_GET_ADDRESS,
NULL,
0,
&scsiAddress,
sizeof(SCSI_ADDRESS),
&bytesReturned,
FALSE ) ) {
dwError = GetLastError();
printf("Capable: IOCTL_SCSI_GET_ADDRESS failed, error %d \n", dwError );
PrintError( dwError );
goto FnExit;
}
(VOID) StringCchPrintf( scsiName,
RTL_NUMBER_OF(scsiName),
"\\\\.\\Scsi%d:",
scsiAddress.PortNumber );
scsiAdapter = CreateFile( scsiName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( INVALID_HANDLE_VALUE == scsiAdapter ) {
dwError = GetLastError();
printf("Capable: Error opening device %s, error %d \n", scsiName, dwError );
PrintError( dwError );
goto FnExit;
}
//
// If clusdisk is loaded and the device is clustered, send the clusdisk
// IOCTL to the device.
//
// Make sure the target is controlled by clusdisk.
// If not, then fail. If the IOCTL is sent to non-clustered
// device, the IOCTL will fail and give invalid capable value.
//
if ( IsClusDiskLoaded() && IsDeviceClustered( Device ) ) {
//
// Try using the clusdisk IOCTL.
//
if ( !DeviceIoControl( Device,
IOCTL_DISK_CLUSTER_NOT_CLUSTER_CAPABLE,
NULL,
0,
NULL,
0,
&bytesReturned,
FALSE ) ) {
printf("ClusDisk IOCTL: Disks are cluster capable (failed with error %d) \n\n", GetLastError() );
} else {
printf("ClusDisk IOCTL: Disks are NOT cluster capable \n\n");
}
}
//
// Now try sending the request via IOCTL_SCSI_MINIPORT to the scsi adapter.
//
if ( IsClusterCapable( scsiAdapter ) ) {
printf("IOCTL_SCSI_MINIPORT: Disks are cluster capable \n\n");
} else {
printf("IOCTL_SCSI_MINIPORT: Disks are NOT cluster capable \n\n");
}
FnExit:
if ( INVALID_HANDLE_VALUE != scsiAdapter ) {
CloseHandle( scsiAdapter );
}
return dwError;
} // Capable
BOOL
IsClusDiskLoaded(
)
/*++
Routine Description:
Determine whether clusdisk driver is loaded.
Arguments:
None
Return Value:
TRUE - clusdisk driver loaded.
FALSE - clusdisk driver not loaded or cannot determine driver status.
--*/
{
NTSTATUS ntStatus;
HANDLE hClusDisk0;
DWORD dwError;
UNICODE_STRING unicodeName;
ANSI_STRING objName;
OBJECT_ATTRIBUTES objAttributes;
IO_STATUS_BLOCK ioStatusBlock;
BOOL loaded = FALSE; // Assume clusdisk is not loaded
RtlInitString( &objName, DEVICE_CLUSDISK0 );
ntStatus = RtlAnsiStringToUnicodeString( &unicodeName,
&objName,
TRUE );
if ( !NT_SUCCESS(ntStatus) ) {
dwError = RtlNtStatusToDosError( ntStatus );
printf( "Error converting string to unicode; error was %d \n", dwError);
PrintError( dwError );
goto FnExit;
}
InitializeObjectAttributes( &objAttributes,
&unicodeName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
ntStatus = NtCreateFile( &hClusDisk0,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0 );
RtlFreeUnicodeString( &unicodeName );
if ( !NT_SUCCESS(ntStatus) ) {
dwError = RtlNtStatusToDosError(ntStatus);
printf( "Error opening ClusDisk0 device; error was %d \n", dwError);
PrintError( dwError );
goto FnExit;
}
loaded = TRUE;
NtClose( hClusDisk0 );
FnExit:
return loaded;
} // IsClusDiskLoaded
BOOL
IsClusterCapable(
HANDLE Scsi
)
{
DWORD dwSize;
BOOL capable;
SRB_IO_CONTROL srb;
ZeroMemory( &srb, sizeof( srb ) );
srb.HeaderLength = sizeof( srb );
CopyMemory( srb.Signature, CLUSDISK_SRB_SIGNATURE, sizeof( srb.Signature ) );
srb.ControlCode = IOCTL_SCSI_MINIPORT_NOT_QUORUM_CAPABLE;
//
// Issue miniport IOCTL to determine whether the disk is cluster capable.
// If the IOCTL fails, the disk is cluster capable.
// If the IOCTL succeeds, the disk is NOT cluster capable.
//
if ( !DeviceIoControl( Scsi,
IOCTL_SCSI_MINIPORT,
&srb,
sizeof(SRB_IO_CONTROL),
NULL,
0,
&dwSize,
NULL
) ) {
capable = TRUE;
} else {
capable = FALSE;
}
return capable;
} // IsClusterCapable
static DWORD
StartReserve(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode, bytesReturned;
DWORD signature;
STRING ansiString;
UNICODE_STRING numberString;
if (argc != 1)
{
printf( "usage: <device> StartReserve <device signature>\n" );
return ERROR_INVALID_NAME;
}
RtlInitAnsiString( &ansiString, *argv );
printf(" Ansi string for signature is %s\n",
ansiString.Buffer );
RtlAnsiStringToUnicodeString(
&numberString,
&ansiString,
TRUE );
errorCode = RtlUnicodeStringToInteger(
&numberString,
16,
&signature );
RtlFreeUnicodeString( &numberString );
if ( !NT_SUCCESS(errorCode) ) {
printf( "Error converting signature to hex number, NT status %u.\n",
errorCode );
return(errorCode);
}
success = DeviceIoControl(fileHandle,
IOCTL_DISK_CLUSTER_START_RESERVE,
&signature,
sizeof(DWORD),
NULL,
0,
&bytesReturned,
FALSE);
if (!success)
{
printf( "Error performing StartReserve; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
}
static DWORD
StopReserve(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode, bytesReturned;
if (argc != 0)
{
printf( "usage: <device> StopReserve\n" );
return ERROR_INVALID_NAME;
}
success = DeviceIoControl(fileHandle,
IOCTL_DISK_CLUSTER_STOP_RESERVE,
NULL,
0,
NULL,
0,
&bytesReturned,
FALSE);
if (!success)
{
printf( "Error performing StopReserve; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
}
static DWORD
Active(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode, bytesReturned;
DWORD signatures[100];
DWORD number;
DWORD i;
if (argc != 0)
{
printf( "usage: <device> Active\n" );
return ERROR_INVALID_NAME;
}
success = DeviceIoControl(fileHandle,
IOCTL_DISK_CLUSTER_ACTIVE,
NULL,
0,
signatures,
sizeof(signatures),
&bytesReturned,
FALSE);
if (!success)
{
printf( "Error performing active; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
printf(" List of signatures:\n\n");
number = signatures[0];
for ( i = 1; i <= number; i++ ) {
printf("\t%08lX\n", signatures[i]);
}
printf("\n");
return ERROR_SUCCESS;
}
static DWORD
Reserve(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode, bytesReturned;
SCSI_PASS_THROUGH scsiBlock;
if (argc != 0)
{
printf( "usage: <device> Reserve\n" );
return ERROR_INVALID_NAME;
}
scsiBlock.PathId = 1;
scsiBlock.TargetId = 3;
scsiBlock.Lun = 0;
scsiBlock.Length = sizeof(SCSI_PASS_THROUGH);
success = DeviceIoControl(fileHandle,
IOCTL_DISK_RESERVE,
&scsiBlock,
sizeof(SCSI_PASS_THROUGH),
&scsiBlock,
sizeof(SCSI_PASS_THROUGH),
&bytesReturned,
FALSE);
errorCode = GetLastError();
if ( errorCode == ERROR_NOT_READY ) {
success = DeviceIoControl(fileHandle,
IOCTL_DISK_CLUSTER_RESERVE,
&scsiBlock,
sizeof(SCSI_PASS_THROUGH),
&scsiBlock,
sizeof(SCSI_PASS_THROUGH),
&bytesReturned,
FALSE);
}
if (!success) {
errorCode = GetLastError();
printf( "Error performing reserve; error was %d\n",
errorCode);
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
} // Reserve
static DWORD
Release(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode, bytesReturned;
SCSI_PASS_THROUGH scsiBlock;
if (argc != 0)
{
printf( "usage: <device> Release\n" );
return ERROR_INVALID_NAME;
}
scsiBlock.PathId = 1;
scsiBlock.TargetId = 3;
scsiBlock.Lun = 0;
scsiBlock.Length = sizeof(SCSI_PASS_THROUGH);
success = DeviceIoControl(fileHandle,
IOCTL_DISK_RELEASE,
&scsiBlock,
sizeof(SCSI_PASS_THROUGH),
&scsiBlock,
sizeof(SCSI_PASS_THROUGH),
&bytesReturned,
FALSE);
if (!success)
{
printf( "Error performing release; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
} // Release
static DWORD
Online(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
DWORD dwError = NO_ERROR;
if (argc != 0)
{
printf( "usage: <device> Online\n" );
dwError = ERROR_INVALID_NAME;
goto FnExit;
}
dwError = SetState( fileHandle, DiskOnline );
FnExit:
return dwError;
} // Online
static DWORD
Offline(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
DWORD dwError = NO_ERROR;
if (argc != 0)
{
printf( "usage: <device> Offline\n" );
dwError = ERROR_INVALID_NAME;
goto FnExit;
}
dwError = SetState( fileHandle, DiskOffline );
FnExit:
return dwError;
} // Offline
DWORD
SetState(
HANDLE FileHandle,
UCHAR NewState
)
{
PDRIVE_LAYOUT_INFORMATION driveLayout = NULL;
NTSTATUS ntStatus;
DWORD dwError;
DWORD bytesReturned;
HANDLE hClusDisk0;
UNICODE_STRING unicodeName;
ANSI_STRING objName;
OBJECT_ATTRIBUTES objAttributes;
IO_STATUS_BLOCK ioStatusBlock;
SET_DISK_STATE_PARAMS params;
BOOL success;
printf( "Setting disk state to %s \n", DiskStateToString( NewState ) );
//
// Get the signature.
//
success = ClRtlGetDriveLayoutTable( FileHandle, &driveLayout, NULL );
if ( !success || !driveLayout ) {
printf(" Unable to read drive layout \n");
dwError = ERROR_GEN_FAILURE;
goto FnExit;
}
RtlInitString( &objName, DEVICE_CLUSDISK0 );
ntStatus = RtlAnsiStringToUnicodeString( &unicodeName,
&objName,
TRUE );
if ( !NT_SUCCESS(ntStatus) ) {
dwError = RtlNtStatusToDosError(ntStatus);
printf( "Error converting string to unicode; error was %d \n", dwError);
PrintError(dwError);
goto FnExit;
}
InitializeObjectAttributes( &objAttributes,
&unicodeName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
ntStatus = NtCreateFile( &hClusDisk0,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0 );
RtlFreeUnicodeString( &unicodeName );
if ( !NT_SUCCESS(ntStatus) ) {
dwError = RtlNtStatusToDosError(ntStatus);
printf( "Error opening ClusDisk0 device; error was %d \n", dwError);
PrintError(dwError);
goto FnExit;
}
params.Signature = driveLayout->Signature;
params.NewState = NewState;
params.OldState = DiskStateInvalid;
success = DeviceIoControl( hClusDisk0,
IOCTL_DISK_CLUSTER_SET_STATE,
&params,
sizeof(params),
&params, // OldState can be returned in either structure or UCHAR
sizeof(params), // ...with appropriate size here
&bytesReturned,
FALSE);
NtClose( hClusDisk0 );
if ( !success ) {
printf( "Error performing %s; error was %d\n",
DiskStateToString( NewState ),
dwError = GetLastError() );
PrintError(dwError);
} else {
printf( "Disk state set %s, old state %s [bytes returned = %d] \n",
DiskStateToString( NewState ),
DiskStateToString( params.OldState ),
bytesReturned );
dwError = NO_ERROR;
}
FnExit:
LocalFree( driveLayout );
return dwError;
} // SetState
static DWORD
GetState(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode = NO_ERROR;
DWORD bytesReturned;
UCHAR oldState;
if (argc != 0) {
printf( "usage: <device> GetState\n" );
errorCode = ERROR_INVALID_NAME;
goto FnExit;
}
//
// Try the new "get state" IOCTL.
//
success = DeviceIoControl( fileHandle,
IOCTL_DISK_CLUSTER_GET_STATE,
NULL,
0,
&oldState,
sizeof(oldState),
&bytesReturned,
FALSE );
if ( !success ) {
printf( "IOCTL_DISK_CLUSTER_GET_STATE failed; error was %d \n",
errorCode = GetLastError());
PrintError( errorCode );
if ( ERROR_INVALID_FUNCTION != errorCode ) {
goto FnExit;
}
printf( "Using old IOCTL to get disk state... \n");
// Try the old "set state" IOCTL.
// To get current disk state, don't specify input buffer.
// Current disk state returned in output buffer.
success = DeviceIoControl( fileHandle,
IOCTL_DISK_CLUSTER_SET_STATE,
NULL,
0,
&oldState,
sizeof(oldState),
&bytesReturned,
FALSE );
if ( !success ) {
printf( "IOCTL_DISK_CLUSTER_SET_STATE failed; error was %d\n",
errorCode = GetLastError());
PrintError( errorCode );
goto FnExit;
}
}
if ( bytesReturned != sizeof(oldState) ) {
printf( "Invalid data retrieving cluster state: bytes returned = %d \n",
bytesReturned );
errorCode = ERROR_INVALID_DATA;
goto FnExit;
}
printf( "Current cluster disk state: %s \n",
DiskStateToString( oldState ) );
FnExit:
return errorCode;
} // GetState
PCHAR
DiskStateToString(
UCHAR DiskState
)
{
switch ( DiskState ) {
case DiskOffline:
return "DiskOffline (0)";
case DiskOnline:
return "DiskOnline (1)";
case DiskFailed:
return "DiskFailed (2)";
case DiskStalled:
return "DiskStalled (3)";
case DiskOfflinePending:
return "DiskOfflinePending (4)";
default:
return "Unknown DiskState";
}
} // DiskStateToString
DWORD
CheckUnclaimedPartitions(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
if (argc != 0)
{
printf( "usage: <device> Claim \n" );
return ERROR_INVALID_NAME;
}
success = DeviceIoControl(fileHandle,
IOCTL_PARTMGR_CHECK_UNCLAIMED_PARTITIONS,
NULL,
0,
NULL,
0,
&bytesReturned,
FALSE);
if (!success)
{
printf( "Error performing Claim; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
} // CheckUnclaimedPartitions
DWORD
EjectVolumes(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
if (argc != 0)
{
printf( "usage: <PhysicalDriveX> EjectVolumes \n" );
return ERROR_INVALID_NAME;
}
success = DeviceIoControl(fileHandle,
IOCTL_PARTMGR_EJECT_VOLUME_MANAGERS,
NULL,
0,
NULL,
0,
&bytesReturned,
FALSE);
if (!success)
{
printf( "Error performing EjectVolumes; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
} // EjectVolumes
DWORD
EnumMounts(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD status;
DWORD bytesReturned;
HANDLE handle;
HANDLE mHandle;
DWORD i;
DWORD signature;
UCHAR uniqueId[MAX_PATH];
DWORD idLength;
STRING ansiString;
UNICODE_STRING numberString;
UCHAR volumeName[MAX_PATH];
UCHAR driveLetter;
if (argc > 1)
{
printf( "usage: <any_device> EnumMounts [signature]\n" );
return ERROR_INVALID_NAME;
}
if ( argc == 1 ) {
RtlInitAnsiString( &ansiString, *argv );
printf(" Ansi string for signature is %s\n",
ansiString.Buffer );
RtlAnsiStringToUnicodeString(
&numberString,
&ansiString,
TRUE );
status = RtlUnicodeStringToInteger(
&numberString,
16,
&signature );
RtlFreeUnicodeString( &numberString );
if ( !NT_SUCCESS(status) ) {
printf( "Error converting signature to hex number, NT status %u.\n",
status );
return(status);
}
} else {
signature = 0;
}
status = DevfileOpen( &mHandle, MOUNTMGR_DEVICE_NAME );
if ( status != ERROR_SUCCESS ) {
printf( "DevfileOpen failed for %ws, status = %u\n",
MOUNTMGR_DEVICE_NAME, status );
return status;
}
idLength = MAX_PATH;
status = FindFirstVolumeForSignature( mHandle,
signature,
volumeName,
MAX_PATH,
&handle,
uniqueId,
&idLength,
&driveLetter );
if ( status != ERROR_SUCCESS ) {
DevfileClose( mHandle );
if ( status == ERROR_NO_MORE_FILES ) {
status = ERROR_SUCCESS;
} else {
printf( "FindFirstVolume failed, status = %u\n", status );
}
return status;
}
i = 1;
while ( status == ERROR_SUCCESS ) {
printf( "Found match for volume %s\n", volumeName );
i++;
idLength = MAX_PATH;
status = FindNextVolumeForSignature( mHandle,
signature,
handle,
volumeName,
MAX_PATH,
uniqueId,
&idLength,
&driveLetter );
}
FindVolumeClose( handle );
DevfileClose( mHandle );
return ERROR_SUCCESS;
} // EnumMounts
DWORD
EnumExtents(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD status;
DWORD bytesReturned;
DWORD diskExtentSize;
PVOLUME_DISK_EXTENTS diskExtents;
DWORD i;
if (argc != 0)
{
printf( "usage: <device> EnumExtents\n" );
return ERROR_INVALID_NAME;
}
diskExtentSize = sizeof(VOLUME_DISK_EXTENTS);
diskExtents = LocalAlloc( LMEM_FIXED, diskExtentSize);
if ( !diskExtents ) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// Get volume information for disk extents.
//
success = DeviceIoControl( fileHandle,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
diskExtents,
diskExtentSize,
&bytesReturned,
FALSE );
status = GetLastError();
if ( !success ) {
if ( status == ERROR_MORE_DATA ) {
diskExtentSize = sizeof(VOLUME_DISK_EXTENTS) +
(sizeof(DISK_EXTENT) * diskExtents->NumberOfDiskExtents);
LocalFree( diskExtents );
diskExtents = LocalAlloc( LMEM_FIXED, diskExtentSize);
if ( !diskExtents ) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
status = ERROR_SUCCESS;
success = DeviceIoControl( fileHandle,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
diskExtents,
diskExtentSize,
&bytesReturned,
FALSE );
if ( !success ) {
status = GetLastError();
}
}
}
if ( NO_ERROR == status ) {
printf( "\n Starting offset Length DiskNumber\n");
printf( " --------------- ------ ----------\n");
for ( i = 0; i < diskExtents->NumberOfDiskExtents; i++ ) {
printf( " %08lx %08lx\t\t%08lx\t\t%u\n",
diskExtents->Extents[i].StartingOffset.HighPart,
diskExtents->Extents[i].StartingOffset.LowPart,
diskExtents->Extents[i].ExtentLength.LowPart,
diskExtents->Extents[i].DiskNumber );
}
}
return status;
} // EnumExtents
DWORD
EnumNodes(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD status;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA devInfoData;
DWORD index;
DWORD size;
LPDWORD dwGuid;
UCHAR devDesc[MAX_PATH];
UCHAR devID[MAX_PATH];
hDevInfo = SetupDiGetClassDevs( NULL,
NULL,
NULL,
DIGCF_ALLCLASSES | DIGCF_PRESENT );
if ( hDevInfo == INVALID_HANDLE_VALUE ) {
status = GetLastError();
printf( "SetupDiGetClassDevs failed with error %u\n", status );
return status;
}
memset( &devInfoData, 0, sizeof(SP_DEVINFO_DATA));
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
//
// First see if anything works...
//
success = SetupDiEnumDeviceInfo( hDevInfo, 0, &devInfoData );
if ( !success ) {
status = GetLastError();
printf( "SetupDiEnumDeviceInfo failed, status = %u\n", status );
return status;
}
index = 0;
while ( SetupDiEnumDeviceInfo( hDevInfo, index, &devInfoData ) ) {
devDesc[0] = '\0';
size = sizeof(devDesc);
printf( "Index = %u\n", index );
if ( CM_Get_DevNode_Registry_Property( devInfoData.DevInst,
CM_DRP_DEVICEDESC,
NULL,
devDesc,
&size,
0 ) == 0 ) {
printf( "Device description = %s\n", devDesc );
dwGuid = (LPDWORD)&devInfoData.ClassGuid;
printf( " GUID = %lx, %lx, %lx, %lx\n", dwGuid[0], dwGuid[1], dwGuid[2], dwGuid[3] );
devID[0] = '\0';
CM_Get_Device_ID( devInfoData.DevInst,
devID,
sizeof(devID),
0 );
if ( devID[0] ) {
printf( " Device Id = %s\n", devID );
}
}
index++;
}
return ERROR_SUCCESS;
} // EnumNodes
DWORD
EnumDisks(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
DWORD status;
BOOL success;
HDEVINFO DeviceInfoSet;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DWORD i;
PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData = NULL;
DWORD DeviceInterfaceDetailDataSize = 0;
DWORD RequiredSize;
SP_DEVINFO_DATA DeviceInfoData;
SP_PROPCHANGE_PARAMS PropChangeParams;
BOOL disable = FALSE;
BOOL parent = FALSE;
//GUID mountDevGuid;
GUID diskDevGuid;
HANDLE devHandle;
UCHAR driveLayoutBuf[sizeof(DRIVE_LAYOUT_INFORMATION) +
(sizeof(PARTITION_INFORMATION) * 64 )];
PDRIVE_LAYOUT_INFORMATION driveLayout = (PDRIVE_LAYOUT_INFORMATION)driveLayoutBuf;
if (argc > 1)
{
printf( "usage: <any_device> EnumDisks [DISABLE | PARENT]\n" );
return ERROR_INVALID_NAME;
}
if ( argc == 1 ) {
if (!_stricmp( *argv, "Disable" ))
disable = TRUE;
else if (!_stricmp( *argv, "Parent" ))
parent = TRUE;
else {
printf( "usage: <any_device> EnumDisks [DISABLE | PARENT]\n" );
return ERROR_INVALID_NAME;
}
}
memcpy( &diskDevGuid, &DiskClassGuid, sizeof(GUID) );
//memcpy( &mountDevGuid, &MOUNTDEV_MOUNTED_DEVICE_GUID, sizeof(GUID) );
DeviceInfoSet = SetupDiGetClassDevs(&diskDevGuid,
NULL,
NULL,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT
);
if ( INVALID_HANDLE_VALUE == DeviceInfoSet ) {
status = GetLastError();
printf("SetupDiGetClassDevs failed, error %u \n", status );
return status;
}
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for(i = 0;
SetupDiEnumDeviceInterfaces(DeviceInfoSet,
NULL,
&diskDevGuid,
i,
&DeviceInterfaceData);
i++) {
//
// To retrieve the device interface name (e.g., that you can call
// CreateFile() on...
//
while(!SetupDiGetDeviceInterfaceDetailW(DeviceInfoSet,
&DeviceInterfaceData,
DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize,
&RequiredSize,
&DeviceInfoData) ) {
//
// We failed to get the device interface detail data--was it because
// our buffer was too small? (Hopefully so!)
//
status = GetLastError();
//printf("Call to SetupDiGetDeviceInterfaceData failed status = %u, required size = %u\n",
// status, RequiredSize);
// Free our current buffer since we failed anyway.
free(DeviceInterfaceDetailData);
DeviceInterfaceDetailData = NULL;
if(status != ERROR_INSUFFICIENT_BUFFER) {
//
// Failure!
//
break;
}
DeviceInterfaceDetailData = malloc(RequiredSize);
if(DeviceInterfaceDetailData) {
DeviceInterfaceDetailDataSize = RequiredSize;
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
} else {
//
// Failure!
//
DeviceInterfaceDetailDataSize = 0;
break;
}
}
if(!DeviceInterfaceDetailData) {
//
// We encountered a failure above--abort.
//
break;
}
//
// Now we may use the device interface name contained in the
// DeviceInterfaceDetailData->DevicePath field (e.g., in a call to
// CreateFile).
//
printf("DevicePath = %ws\n", DeviceInterfaceDetailData->DevicePath );
devHandle = CreateFileW( DeviceInterfaceDetailData->DevicePath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( devHandle != INVALID_HANDLE_VALUE ) {
// Get signature
success = DeviceIoControl( devHandle,
IOCTL_DISK_GET_DRIVE_LAYOUT,
NULL,
0,
driveLayout,
sizeof(driveLayoutBuf),
&RequiredSize,
FALSE );
if ( success ) {
printf( " Signature for device = %08lx\n", driveLayout->Signature );
}
CloseHandle( devHandle );
}
//
// To open up the persistent storage registry key associated with this
// device interface (e.g., to retrieve it's FriendlyName value entry),
// use SetupDiCreateDeviceInterfaceRegKey or
// SetupDiOpenDeviceInterfaceRegKey.
//
//
// Notice that we retrieved the associated device information element
// in the above call to SetupDiGetDeviceInterfaceDetail. We can thus
// use this element in setupapi calls to effect changes to the devnode
// (including invoking the class installer and any co-installers that
// may be involved).
//
// For example, here's how we'd disable the device...
//
if ( disable ) {
// Perform following only if we are supposed to disable
#ifdef PERSISTENT
PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
PropChangeParams.StateChange = DICS_DISABLE;
PropChangeParams.Scope = DICS_FLAG_GLOBAL;
//
// No need to set PropChangeParams.HwProfile since we're doing global
// property change.
//
if( !SetupDiSetClassInstallParamsW(DeviceInfoSet,
&DeviceInfoData,
(PSP_CLASSINSTALL_HEADER)&PropChangeParams,
sizeof(PropChangeParams)
) ) {
status = GetLastError();
printf( "SetupDiSetClassInstallParams failed with %u\n", status );
continue;
}
if ( !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
DeviceInfoSet,
&DeviceInfoData
) ) {
status = GetLastError();
printf( "SetupDiCallClassInstaller failed with %u\n", status );
continue;
}
printf("Disabled!\n");
getchar();
//
// ...and here's how we'd re-enable it...
//
PropChangeParams.StateChange = DICS_ENABLE;
if ( !SetupDiSetClassInstallParamsW(DeviceInfoSet,
&DeviceInfoData,
(PSP_CLASSINSTALL_HEADER)&PropChangeParams,
sizeof(PropChangeParams)
) ) {
status = GetLastError();
printf( "SetupDiSetClassInstallParams failed with %u\n", status );
continue;
}
if ( !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
DeviceInfoSet,
&DeviceInfoData
) ) {
status = GetLastError();
printf( "SetupDiCallClassInstaller failed with %u\n", status );
}
#else
#if 0 // we don't support multiple switches together - this would need disable
// and parent set together!
//
// Try to find parent
//
if ( parent ) {
status = CM_Get_Parent( parentDev,
DeviceInfoData.DevInst,
0 );
if ( status != ERROR_SUCCESS ) {
printf( "CM_Get_Parent failed with %u\n", status );
continue;
}
}
#endif
//
// NOTE: The code above does a persistent disable/enable. If you only
// wanted this to be temporary (i.e., in effect till reboot), then you
// could retrieve the devnode handle from the DeviceInfoData.DevInst
// field and call CM_Disable_DevNode and CM_Enable_DevNode directly.
//
status = CM_Disable_DevNode( DeviceInfoData.DevInst, 0 );
if ( status != ERROR_SUCCESS ) {
printf( "CM_Disable_DevNode failed with %u\n", status );
continue;
}
printf("Disabled!\n");
getchar();
status = CM_Enable_DevNode( DeviceInfoData.DevInst, 0 );
if ( status != ERROR_SUCCESS ) {
printf( "CM_Enable_DevNode failed with %u\n", status );
}
#endif //PERSISTENT
} else { // If we are supposed to disable the disk
//
// Try to find parent
//
if ( parent ) {
DEVINST parentDev;
DEVINST pParentDev = 0;
WCHAR outBuffer[MAX_PATH];
HDEVINFO devInfoSet;
SP_DEVINFO_DATA devInfoData;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
do {
status = CM_Get_Parent( &parentDev,
DeviceInfoData.DevInst,
0 );
if ( status != ERROR_SUCCESS ) {
printf( "CM_Get_Parent failed with %u\n", status );
break;
}
if ( pParentDev == parentDev ) {
break;
}
pParentDev = parentDev;
status = CM_Get_Device_IDW( parentDev,
outBuffer,
sizeof(outBuffer)/sizeof(WCHAR),
0 );
if ( status != ERROR_SUCCESS ) {
printf( "CM_Get_Parent failed with %u\n", status );
//status = ERROR_SUCCESS;
} else {
printf( " ParentDev = %ws\n", outBuffer );
}
} while ( status == ERROR_SUCCESS );
}
}
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return ERROR_SUCCESS;
} // EnumDisks
DWORD
GetDiskGeometry(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
DISK_GEOMETRY diskGeometry;
if (argc != 0)
{
printf( "usage: <device> GetDiskGeometry\n" );
return ERROR_INVALID_NAME;
}
ZeroMemory( &diskGeometry, sizeof(DISK_GEOMETRY) );
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY),
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing GetDiskGeometry, error %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
if ( bytesReturned < sizeof(DISK_GEOMETRY) ) {
printf("Error reading DiskGeometry information. Expected %u bytes, got %u bytes.\n",
sizeof(DISK_GEOMETRY),
bytesReturned);
return(ERROR_INSUFFICIENT_BUFFER);
}
printf("GetDiskGeometry was successful, we got %d bytes returned.\n",
bytesReturned);
printf("Cylinders = %lx%lx, TracksPerCylinder = %lx, SectorsPerTrack = %lx, BytesPerSector = %lx\n",
diskGeometry.Cylinders.HighPart, diskGeometry.Cylinders.LowPart,
diskGeometry.TracksPerCylinder, diskGeometry.SectorsPerTrack,
diskGeometry.BytesPerSector);
return ERROR_SUCCESS;
} // GetDiskGeometry
DWORD
GetScsiAddress(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
SCSI_ADDRESS scsiAddress;
if (argc != 0)
{
printf( "usage: <device> GetScsiAddress\n" );
return ERROR_INVALID_NAME;
}
ZeroMemory( &scsiAddress, sizeof(scsiAddress) );
success = DeviceIoControl( fileHandle,
IOCTL_SCSI_GET_ADDRESS,
NULL,
0,
&scsiAddress,
sizeof(SCSI_ADDRESS),
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing GetScsiAddress, error %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
if ( bytesReturned < sizeof(scsiAddress) ) {
printf("Error reading ScsiAddress information. Expected %u bytes, got %u bytes.\n",
sizeof(scsiAddress),
bytesReturned);
return(ERROR_INSUFFICIENT_BUFFER);
}
printf("GetScsiAddress was successful, we got %d bytes returned.\n",
bytesReturned);
printf("PortNumber = %x, PathId = %x, TargetId = %x, Lun = %x\n",
scsiAddress.PortNumber, scsiAddress.PathId,
scsiAddress.TargetId, scsiAddress.Lun);
return ERROR_SUCCESS;
} // GetScsiAddress
DWORD
GetDriveLayout(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
DWORD harddiskNo;
DWORD i;
PDRIVE_LAYOUT_INFORMATION driveLayout;
PPARTITION_INFORMATION partInfo;
if (argc != 0)
{
printf( "usage: <device> GetDriveLayout\n" );
return ERROR_INVALID_NAME;
}
driveLayout = DoIoctlAndAllocate(fileHandle,
IOCTL_DISK_GET_DRIVE_LAYOUT,
NULL, 0, &bytesReturned);
if (!driveLayout) {
return GetLastError();
}
printf("GetDriveLayout was successful, %d bytes returned.\n",
bytesReturned);
printf("Partition Count = %u \n", driveLayout->PartitionCount);
printf("Signature = %lx\n", driveLayout->Signature);
printf("\n");
printf("Part# Type Recog BootInd PartOff PartLeng HidSect Rewrite \n");
printf("===== ==== ===== ======= ============ ============ ======= ======= \n");
for (i = 0; i < driveLayout->PartitionCount; i++ ) {
partInfo = &driveLayout->PartitionEntry[i];
printf(" %2u %2X %1u %1u %12I64X %12I64X %7u %s \n",
partInfo->PartitionNumber,
partInfo->PartitionType,
partInfo->RecognizedPartition,
partInfo->BootIndicator,
partInfo->StartingOffset.QuadPart,
partInfo->PartitionLength.QuadPart,
partInfo->HiddenSectors,
BooleanToString( partInfo->RewritePartition )
);
}
free( driveLayout );
return ERROR_SUCCESS;
} // GetDriveLayout
DWORD
GetDriveLayoutEx(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
PDRIVE_LAYOUT_INFORMATION_EX driveLayout = NULL;
PPARTITION_INFORMATION_EX partInfo;
DWORD errorCode = NO_ERROR;
DWORD bytesReturned;
DWORD harddiskNo;
DWORD idx;
DWORD nameIdx;
BOOL success;
TCHAR strGuid[MAX_PATH];
TCHAR strType[MAX_PATH];
if ( argc != 0 ) {
printf( "usage: <device> GetDriveLayoutEx \n" );
errorCode = ERROR_INVALID_NAME;
goto FnExit;
}
driveLayout = DoIoctlAndAllocate( fileHandle,
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
NULL, 0, &bytesReturned );
if ( !driveLayout ) {
errorCode = GetLastError();
printf("IOCTL_DISK_GET_DRIVE_LAYOUT_EX failed: %u \n", errorCode);
PrintError( errorCode );
goto FnExit;
}
printf("GetDriveLayoutEx was successful: %d bytes returned.\n",
bytesReturned);
printf("Partition style = ");
if ( PARTITION_STYLE_MBR == driveLayout->PartitionStyle ) {
printf("MBR \n");
} else if ( PARTITION_STYLE_GPT == driveLayout->PartitionStyle ) {
printf("GPT \n");
} else if ( PARTITION_STYLE_RAW == driveLayout->PartitionStyle ) {
printf("RAW \n");
goto FnExit;
} else {
printf("Unknown \n");
goto FnExit;
}
printf("Partition Count = %u \n", driveLayout->PartitionCount);
if ( PARTITION_STYLE_MBR == driveLayout->PartitionStyle ) {
printf("Signature = %lx \n", driveLayout->Mbr.Signature);
printf("\n");
printf("Part# Type Recog BootInd PartOff PartLeng HidSect Rewrite \n");
printf("===== ==== ===== ======= ============ ============ ======= ======= \n");
for ( idx = 0; idx < driveLayout->PartitionCount; idx++ ) {
partInfo = &driveLayout->PartitionEntry[idx];
if ( PARTITION_STYLE_MBR != partInfo->PartitionStyle ) {
printf("Skipping partition: style is not MBR (%u) \n", partInfo->PartitionStyle);
continue;
}
printf(" %2u %2X %1u %1u %12I64X %12I64X %7u %s \n",
partInfo->PartitionNumber,
partInfo->Mbr.PartitionType,
partInfo->Mbr.RecognizedPartition,
partInfo->Mbr.BootIndicator,
partInfo->StartingOffset.QuadPart,
partInfo->PartitionLength.QuadPart,
partInfo->Mbr.HiddenSectors,
BooleanToString( partInfo->RewritePartition )
);
}
} else {
FormatGuid( &(driveLayout->Gpt.DiskId), strGuid, RTL_NUMBER_OF(strGuid) );
printf("Signature (GUID) = %s \n", strGuid );
printf("Signature (hashed) = %08x \n", ClusterHashGuid( driveLayout->Gpt.DiskId ) );
printf("\n");
printf("Part# PartOff PartLeng Rewrite \n");
printf("===== ================ ================ ======= \n");
for ( idx = 0; idx < driveLayout->PartitionCount; idx++ ) {
partInfo = &driveLayout->PartitionEntry[idx];
if ( idx ) {
printf("\n");
}
if ( PARTITION_STYLE_GPT != partInfo->PartitionStyle ) {
printf("Skipping partition: style is not GPT (%u) \n", partInfo->PartitionStyle);
continue;
}
printf(" %2u %16I64X %16I64X %s \n",
partInfo->PartitionNumber,
partInfo->StartingOffset.QuadPart,
partInfo->PartitionLength.QuadPart,
BooleanToString( partInfo->RewritePartition )
);
FormatGuid( &(partInfo->Gpt.PartitionType), strGuid, RTL_NUMBER_OF(strGuid) );
if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_SYSTEM_GUID, sizeof(GUID) ) ) {
(VOID) StringCchPrintf(strType, RTL_NUMBER_OF(strType), "System");
} else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_MSFT_RESERVED_GUID, sizeof(GUID) ) ) {
(VOID) StringCchPrintf(strType, RTL_NUMBER_OF(strType), "Microsoft Reserved");
} else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_BASIC_DATA_GUID, sizeof(GUID) ) ) {
(VOID) StringCchPrintf(strType, RTL_NUMBER_OF(strType), "Basic Data");
} else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_LDM_METADATA_GUID, sizeof(GUID) ) ) {
(VOID) StringCchPrintf(strType, RTL_NUMBER_OF(strType), "LDM Metadata");
} else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_LDM_DATA_GUID, sizeof(GUID) ) ) {
(VOID) StringCchPrintf(strType, RTL_NUMBER_OF(strType), "LDM Data");
#if PARTITION_CLUSTER_GUID
} else if ( !memcmp( &(partInfo->Gpt.PartitionType), &PARTITION_CLUSTER_GUID, sizeof(GUID) ) ) {
(VOID) StringCchPrintf(strType, RTL_NUMBER_OF(strType), "Cluster Data");
#endif
} else {
(VOID) StringCchPrintf(strType, RTL_NUMBER_OF(strType), "Unknown partition type");
}
printf("\n");
printf(" PartitionType = %s \n", strGuid);
printf(" %s \n", strType);
FormatGuid(&(partInfo->Gpt.PartitionId), strGuid, RTL_NUMBER_OF(strGuid) );
printf(" PartitionId = %s \n", strGuid);
printf(" Attributes = %I64X \n", partInfo->Gpt.Attributes);
printf(" Name: ");
for ( nameIdx = 0; nameIdx < 36; nameIdx++ ) {
printf("%c", partInfo->Gpt.Name[nameIdx]);
}
printf("\n");
}
}
FnExit:
free( driveLayout );
return ERROR_SUCCESS;
} // GetDriveLayoutEx
LPTSTR
BooleanToString(
BOOLEAN Value
)
{
if ( Value ) {
return "TRUE ";
}
return "FALSE";
} // BooleanToString
void
FormatGuid(
GUID* Guid,
char* Str,
int StrCharMax
)
{
//
// Code from guidgen
//
(VOID) StringCchPrintf( Str,
StrCharMax,
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
// first copy...
Guid->Data1, Guid->Data2, Guid->Data3,
Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3],
Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7] );
}
DWORD
GetVolumeInfo(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
PCLUSPROP_PARTITION_INFO partInfo;
ANSI_STRING ansiName;
UNICODE_STRING unicodeName;
NTSTATUS ntStatus;
if (argc != 0) {
printf( "usage: <device> GetVolumeInfo\n" );
return ERROR_INVALID_NAME;
}
ntStatus = GetVolumeInformationFromHandle(fileHandle);
if ( !NT_SUCCESS(ntStatus) ) {
errorCode = RtlNtStatusToDosError( ntStatus );
printf( "GetVolumeInformationFromHandle failed with status %X, %u\n",
ntStatus, errorCode );
}
partInfo = LocalAlloc( LMEM_FIXED, sizeof(CLUSPROP_PARTITION_INFO) );
if ( !partInfo ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
ZeroMemory( partInfo, sizeof(CLUSPROP_PARTITION_INFO) );
RtlInitString(&ansiName, DeviceName);
errorCode = RtlAnsiStringToUnicodeString( &unicodeName,
&ansiName,
TRUE );
if ( !NT_SUCCESS(errorCode) ) {
return(errorCode);
}
// The following assumes a drive letter is used.
// wsprintfW( partInfo->szDeviceName, L"%c:\\", unicodeName.Buffer[0] );
wcsncpy( partInfo->szDeviceName, unicodeName.Buffer, unicodeName.Length );
RtlFreeUnicodeString( &unicodeName );
if ( !GetVolumeInformationW( partInfo->szDeviceName,
partInfo->szVolumeLabel,
RTL_NUMBER_OF(partInfo->szVolumeLabel),
&partInfo->dwSerialNumber,
&partInfo->rgdwMaximumComponentLength,
&partInfo->dwFileSystemFlags,
partInfo->szFileSystem,
RTL_NUMBER_OF(partInfo->szFileSystem) ) ) {
partInfo->szVolumeLabel[0] = L'\0';
errorCode = GetLastError();
printf("Error reading volume information for %ws. Error %u.\n",
partInfo->szDeviceName,
errorCode);
LocalFree( partInfo );
return( errorCode );
}
printf("DeviceName = %ws\n", partInfo->szDeviceName);
printf("VolumeLabel = %ws\n", partInfo->szVolumeLabel);
printf("FileSystemFlags = %lx, FileSystem = %ws\n",
partInfo->dwFileSystemFlags, partInfo->szFileSystem);
LocalFree( partInfo );
return ERROR_SUCCESS;
} // GetVolumeInfo
DWORD
SetDriveLayout(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
DWORD driveLayoutSize;
PDRIVE_LAYOUT_INFORMATION driveLayout;
PPARTITION_INFORMATION partInfo;
DWORD index;
DWORD partShift = 0;
if (argc != 0)
{
printf( "usage: <device> SetDriveLayout\n" );
return ERROR_INVALID_NAME;
}
driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
(sizeof(PARTITION_INFORMATION) * MAX_PARTITIONS);
driveLayout = LocalAlloc( LMEM_FIXED, driveLayoutSize );
if ( !driveLayout ) {
return(ERROR_OUTOFMEMORY);
}
ZeroMemory( driveLayout, driveLayoutSize );
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_DRIVE_LAYOUT,
NULL,
0,
driveLayout,
driveLayoutSize,
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing GetDriveLayout; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
LocalFree( driveLayout );
return errorCode;
}
driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
(sizeof(PARTITION_INFORMATION) *
(driveLayout->PartitionCount - 1));
if ( bytesReturned < driveLayoutSize ) {
printf("Error reading DriveLayout information. Expected %u bytes, got %u bytes.\n",
sizeof(DRIVE_LAYOUT_INFORMATION) + (sizeof(PARTITION_INFORMATION) *
(driveLayout->PartitionCount - 1)), bytesReturned);
LocalFree( driveLayout );
return(ERROR_INSUFFICIENT_BUFFER);
}
if ( driveLayout->PartitionCount > MAX_PARTITIONS ) {
printf("SetDriveLayout, exiting - too many partitions!\n");
LocalFree( driveLayout );
return(ERROR_TOO_MANY_LINKS);
}
for ( index = 0;
(index < driveLayout->PartitionCount) &&
(index < MAX_PARTITIONS );
index++ ) {
partInfo = &driveLayout->PartitionEntry[index];
if ( (partInfo->PartitionType == PARTITION_ENTRY_UNUSED) ||
!partInfo->RecognizedPartition ) {
continue;
}
if ( (index == 0) &&
(partInfo->PartitionNumber == 0) ) {
partShift = 1;
}
printf("Partition %u was %s\n", partInfo->PartitionNumber, (partShift? "incremented" : "left alone"));
partInfo->PartitionNumber += partShift;
}
success = DeviceIoControl( fileHandle,
IOCTL_DISK_SET_DRIVE_LAYOUT,
driveLayout,
driveLayoutSize,
NULL,
0,
&bytesReturned,
FALSE );
if ( !success ) {
printf("Error performing SetDriveLayout, error %u.\n",
errorCode = GetLastError());
PrintError(errorCode);
LocalFree( driveLayout );
return(errorCode);
}
LocalFree( driveLayout );
printf("SetDriveLayout was successful. Set %d bytes.\n", driveLayoutSize);
return ERROR_SUCCESS;
} // SetDriveLayout
static DWORD
Attach(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
DWORD signature;
STRING ansiString;
UNICODE_STRING numberString;
if (argc != 1)
{
printf( "usage: <device> Attach <device signature>\n" );
return ERROR_INVALID_NAME;
}
RtlInitAnsiString( &ansiString, *argv );
printf(" Ansi string for signature is %s\n",
ansiString.Buffer );
RtlAnsiStringToUnicodeString(
&numberString,
&ansiString,
TRUE );
errorCode = RtlUnicodeStringToInteger(
&numberString,
16,
&signature );
RtlFreeUnicodeString( &numberString );
if ( !NT_SUCCESS(errorCode) ) {
printf( "Error converting signature to hex number, NT status %u.\n",
errorCode );
return(errorCode);
}
success = DeviceIoControl( fileHandle,
IOCTL_DISK_CLUSTER_ATTACH,
&signature,
sizeof(DWORD),
NULL,
0,
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing ATTACH, error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
} // Attach
static DWORD
Detach(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
DWORD signature;
STRING ansiString;
UNICODE_STRING numberString;
if (argc != 1)
{
printf( "usage: <device> Detach <device signature>\n" );
return ERROR_INVALID_NAME;
}
RtlInitAnsiString( &ansiString, *argv );
printf(" Ansi string for signature is %s\n",
ansiString.Buffer );
RtlAnsiStringToUnicodeString(
&numberString,
&ansiString,
TRUE );
errorCode = RtlUnicodeStringToInteger(
&numberString,
16,
&signature );
RtlFreeUnicodeString( &numberString );
if ( !NT_SUCCESS(errorCode) ) {
printf( "Error converting signature to hex number, NT status %u.\n",
errorCode );
return(errorCode);
}
success = DeviceIoControl( fileHandle,
IOCTL_DISK_CLUSTER_DETACH,
&signature,
sizeof(DWORD),
NULL,
0,
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing DETACH, error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
return ERROR_SUCCESS;
} // Detach
static DWORD
GetPartitionInfo(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
PARTITION_INFORMATION partInfo;
if (argc != 0)
{
printf( "usage: <device> GetPartitionInfo\n" );
return ERROR_INVALID_NAME;
}
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
&partInfo,
sizeof(PARTITION_INFORMATION),
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing GetPartitionInfo; error was %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
printf("GetPartitionInfo was successful, we got %d bytes returned.\n\n",
bytesReturned);
printf("Part# Type Recog BootInd PartOff PartLeng HidSect\n");
#if 0
Part# Type Recog BootInd PartOff PartLeng HidSect
xx xx x x xxxxxxxxxxxx xxxxxxxxxxxx xxxxxxx
#endif
printf(" %2u %2X %1u %1u %12I64X %12I64X %7u\n",
partInfo.PartitionNumber,
partInfo.PartitionType,
partInfo.RecognizedPartition,
partInfo.BootIndicator,
partInfo.StartingOffset.QuadPart,
partInfo.PartitionLength.QuadPart,
partInfo.HiddenSectors);
return ERROR_SUCCESS;
} // GetPartitionInfo
DWORD
ReadSector(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD status;
DWORD bytesReturned;
DWORD bytesRead;
DWORD x,y;
DISK_GEOMETRY diskGeometry;
LPBYTE buf = 0;
INT sectorNo;
if (argc != 1)
{
printf( "usage: <device> ReadSector No\n" );
return ERROR_INVALID_NAME;
}
status = sscanf(argv[0], "%d", &sectorNo);
if ( 0 == status ) {
printf("Unable to get sector number from input \n");
return ERROR_INVALID_PARAMETER;
}
ZeroMemory( &diskGeometry, sizeof(DISK_GEOMETRY) );
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY),
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing GetDiskGeometry, error %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
if ( bytesReturned < sizeof(DISK_GEOMETRY) ) {
printf("Error reading DiskGeometry information. Expected %u bytes, got %u bytes.\n",
sizeof(DISK_GEOMETRY),
bytesReturned);
return(ERROR_INSUFFICIENT_BUFFER);
}
printf("GetDiskGeometry was successful, we got %d bytes returned.\n",
bytesReturned);
printf("Cylinders = %lx%lx, TracksPerCylinder = %lx, SectorsPerTrack = %lx, BytesPerSector = %lx\n",
diskGeometry.Cylinders.HighPart, diskGeometry.Cylinders.LowPart,
diskGeometry.TracksPerCylinder, diskGeometry.SectorsPerTrack,
diskGeometry.BytesPerSector);
errorCode = ERROR_SUCCESS;
__try {
buf = VirtualAlloc(0, diskGeometry.BytesPerSector, MEM_COMMIT, PAGE_READWRITE);
if(buf == 0) {
printf("Virtual Alloc failed\n");
errorCode = GetLastError();
__leave;
}
printf("Sector %d\n", sectorNo);
status = SetFilePointer(fileHandle,
diskGeometry.BytesPerSector * sectorNo,
NULL,
FILE_BEGIN);
if( 0xFFFFFFFF == status ) {
printf("Error setting file pointer to %lx \n", diskGeometry.BytesPerSector * sectorNo);
errorCode = GetLastError();
__leave;
}
status = ReadFile(fileHandle,
buf,
diskGeometry.BytesPerSector,
&bytesRead,
NULL);
if( status == 0 ) {
printf("Error reading sector %lx \n.", sectorNo);
errorCode = GetLastError();
__leave;
}
if ( bytesRead != diskGeometry.BytesPerSector ) {
printf("Error reading sector. Expected %ul bytes, got %ul bytes.\n",
diskGeometry.BytesPerSector,
bytesRead);
errorCode = ERROR_INSUFFICIENT_BUFFER;
__leave;
}
for(x = 0; x < diskGeometry.BytesPerSector; x += 16) {
for(y = 0; y < 16; ++y) {
BYTE ch = buf[x+y];
if (ch >= ' ' && ch <= '~') {
printf(" %c", ch);
} else {
printf(" %02x", ch);
}
}
printf("\n");
}
errorCode = ERROR_SUCCESS;
}
__finally {
if(buf) {
VirtualFree(buf, 0, MEM_RELEASE);
}
}
return errorCode;
} // ReadSector
DWORD
ReadSectorViaIoctl(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
BOOL success;
DWORD errorCode;
DWORD bytesReturned;
DISK_GEOMETRY diskGeometry;
DWORD bytesRead;
DWORD status;
DWORD x,y;
ARBITRATION_READ_WRITE_PARAMS params;
LPBYTE buf = 0;
INT sectorNo;
if (argc != 1)
{
printf( "usage: <device> rs No\n" );
return ERROR_INVALID_NAME;
}
status = sscanf(argv[0], "%d", &sectorNo);
if ( 0 == status ) {
printf("Unable to get sector number from input \n");
return ERROR_INVALID_PARAMETER;
}
ZeroMemory( &diskGeometry, sizeof(DISK_GEOMETRY) );
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY),
&bytesReturned,
FALSE );
if (!success) {
printf( "Error performing GetDiskGeometry, error %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return errorCode;
}
if ( bytesReturned < sizeof(DISK_GEOMETRY) ) {
printf("Error reading DiskGeometry information. Expected %u bytes, got %u bytes.\n",
sizeof(DISK_GEOMETRY),
bytesReturned);
return(ERROR_INSUFFICIENT_BUFFER);
}
printf("GetDiskGeometry was successful, we got %d bytes returned.\n",
bytesReturned);
printf("Cylinders = %lx%lx, TracksPerCylinder = %lx, SectorsPerTrack = %lx, BytesPerSector = %lx\n",
diskGeometry.Cylinders.HighPart, diskGeometry.Cylinders.LowPart,
diskGeometry.TracksPerCylinder, diskGeometry.SectorsPerTrack,
diskGeometry.BytesPerSector);
errorCode = ERROR_SUCCESS;
__try {
buf = VirtualAlloc(0, diskGeometry.BytesPerSector, MEM_COMMIT, PAGE_READWRITE);
if(buf == 0) {
printf("Virtual Alloc failed\n");
errorCode = GetLastError();
__leave;
}
printf("Sector %d\n", sectorNo);
params.Operation = AE_READ;
params.SectorSize = diskGeometry.BytesPerSector;
params.SectorNo = sectorNo;
params.Buffer = buf;
success = DeviceIoControl( fileHandle,
IOCTL_DISK_CLUSTER_ARBITRATION_ESCAPE,
&params,
sizeof(params),
NULL,
0,
&bytesReturned,
FALSE );
if(!success) {
printf("Error reading sector %lx\n.", sectorNo);
errorCode = GetLastError();
__leave;
}
for(x = 0; x < diskGeometry.BytesPerSector; x += 16) {
for(y = 0; y < 16; ++y) {
BYTE ch = buf[x+y];
if (ch >= ' ' && ch <= '~') {
printf(" %c", ch);
} else {
printf(" %02x", ch);
}
}
printf("\n");
}
errorCode = ERROR_SUCCESS;
}
__finally {
if(buf) {
VirtualFree(buf, 0, MEM_RELEASE);
}
}
return errorCode;
} // ReadSectorViaIoctl
#if 0
DWORD
FixDisk(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Fix the drive layout for the disk.
Arguments:
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
DWORD index;
DWORD driveLayoutSize;
DWORD bytesPerTrack;
DWORD bytesPerCylinder;
PDRIVE_LAYOUT_INFORMATION driveLayout;
PPARTITION_INFORMATION partInfo;
BOOL success;
BOOL reset = FALSE;
DWORD returnLength;
DISK_GEOMETRY diskGeometry;
LARGE_INTEGER partOffset;
LARGE_INTEGER partLength;
LARGE_INTEGER partSize;
LARGE_INTEGER modulo;
if (argc > 1)
{
printf( "usage: <device> FixDisk [RESET]\n" );
return ERROR_INVALID_NAME;
}
if ( argc != 0 ) {
if ( !_stricmp( *argv, "reset" ) ) {
reset = TRUE;
}
}
driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
(sizeof(PARTITION_INFORMATION) * (1 + MAX_PARTITIONS));
driveLayout = LocalAlloc( LMEM_FIXED, driveLayoutSize );
if ( !driveLayout ) {
printf("FixDisk, failed to allocate drive layout info.\n");
return(ERROR_OUTOFMEMORY);
}
//
// Read the drive capacity to get bytesPerSector and bytesPerCylinder.
//
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY),
&returnLength,
FALSE );
if ( !success ) {
printf("FixDriveLayout, error reading drive capacity. Error: %u \n",
status = GetLastError());
LocalFree( driveLayout );
return(status);
}
printf("FixDriveLayout, bps = %u, spt = %u, tpc = %u.\n",
diskGeometry.BytesPerSector, diskGeometry.SectorsPerTrack,
diskGeometry.TracksPerCylinder);
//
// If read of the partition table originally failed, then we rebuild
// it!
//
if ( reset ) {
driveLayout->PartitionCount = MAX_PARTITIONS;
driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
(MAX_PARTITIONS * sizeof(PARTITION_INFORMATION));
driveLayout->Signature = 2196277081;
bytesPerTrack = diskGeometry.SectorsPerTrack *
diskGeometry.BytesPerSector;
bytesPerCylinder = diskGeometry.TracksPerCylinder *
bytesPerTrack;
partInfo = &driveLayout->PartitionEntry[0];
partLength.QuadPart = bytesPerCylinder * diskGeometry.Cylinders.QuadPart;
//
// The partition offset is 1 track (in bytes).
// Size is media_size - offset, rounded down to cylinder boundary.
//
partOffset.QuadPart = bytesPerTrack;
partSize.QuadPart = partLength.QuadPart - partOffset.QuadPart;
modulo.QuadPart = (partOffset.QuadPart + partSize.QuadPart) %
bytesPerCylinder;
partSize.QuadPart -= modulo.QuadPart;
partInfo = driveLayout->PartitionEntry;
//
// Initialize first partition entry.
//
partInfo->RewritePartition = TRUE;
partInfo->PartitionType = PARTITION_IFS;
partInfo->BootIndicator = FALSE;
partInfo->StartingOffset.QuadPart = partOffset.QuadPart;
partInfo->PartitionLength.QuadPart = partSize.QuadPart;
partInfo->HiddenSectors = 0;
partInfo->PartitionNumber = 1;
//
// For now the remaining partition entries are unused.
//
for ( index = 1; index < driveLayout->PartitionCount; index++ ) {
partInfo = &driveLayout->PartitionEntry[index];
partInfo->PartitionType = PARTITION_ENTRY_UNUSED;
partInfo->RewritePartition = TRUE;
partInfo->BootIndicator = FALSE;
partInfo->StartingOffset.QuadPart = 0;
partInfo->PartitionLength.QuadPart = 0;
partInfo->HiddenSectors = 0;
partInfo->PartitionNumber = 0;
}
} else {
//
// For now, the remaining partition entries are unused.
//
for ( index = 0; index < driveLayout->PartitionCount; index++ ) {
partInfo = &driveLayout->PartitionEntry[index];
partInfo->RewritePartition = TRUE;
partInfo->PartitionNumber = index+1;
}
#if 0
//
// Recalculate the starting offset for the extended partitions.
//
for ( index = 0; index < driveLayout->PartitionCount; index++ ) {
LARGE_INTEGER extendedOffset;
LARGE_INTEGER bytesPerSector;
bytesPerSector.QuadPart = diskGeometry.BytesPerSector;
extendedOffset.QuadPart = 0;
partInfo = &driveLayout->PartitionEntry[index];
partInfo->RewritePartition = TRUE;
if ( IsContainerPartition(partInfo->PartitionType) ) {
//
// If this is the first extended partition, then remember
// the offset to added to the next partition.
//
if ( extendedOffset.QuadPart == 0 ) {
extendedOffset.QuadPart = bytesPerSector.QuadPart *
(LONGLONG)partInfo->HiddenSectors;
} else {
//
// We need to recalculate this extended partition's starting
// offset based on the current 'HiddenSectors' field and
// the first extended partition's offset.
//
partInfo->StartingOffset.QuadPart = extendedOffset.QuadPart
+ (bytesPerSector.QuadPart *
(LONGLONG)partInfo->HiddenSectors);
partInfo->HiddenSectors = 0;
}
}
}
#endif
}
//
// Now set the new partition information.
//
success = DeviceIoControl( fileHandle,
IOCTL_DISK_SET_DRIVE_LAYOUT,
driveLayout,
driveLayoutSize,
NULL,
0,
&returnLength,
FALSE );
if ( !success ) {
printf("FixDisk, error setting partition information. Error: %u \n",
status = GetLastError() );
LocalFree( driveLayout );
return(status);
}
LocalFree( driveLayout );
return(ERROR_SUCCESS);
} // FixDisk
static DWORD
FixDriveLayout(
HANDLE fileHandle,
int argc,
char *argv[]
)
/*++
Routine Description:
Fix the (broken) disk.
Arguments:
Return Value:
ERROR_SUCCESS if successful.
A Win32 error code on failure.
--*/
{
DWORD status;
DWORD index;
DWORD driveLayoutSize;
DWORD bytesPerTrack;
DWORD bytesPerCylinder;
PDRIVE_LAYOUT_INFORMATION driveLayout;
PPARTITION_INFORMATION partInfo;
BOOL success;
DWORD returnLength;
DISK_GEOMETRY diskGeometry;
LARGE_INTEGER partOffset;
LARGE_INTEGER partLength;
LARGE_INTEGER partSize;
LARGE_INTEGER modulo;
driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
(sizeof(PARTITION_INFORMATION) * 2 * MAX_PARTITIONS);
driveLayout = LocalAlloc( LMEM_FIXED, driveLayoutSize );
if ( !driveLayout ) {
printf("FixDriveLayout, failed to allocate drive layout info.\n");
return(ERROR_OUTOFMEMORY);
}
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_DRIVE_LAYOUT,
NULL,
0,
driveLayout,
driveLayoutSize,
&returnLength,
FALSE );
if ( !success ) {
printf("FixDriveLayout, error getting partition information. Error: %u \n",
status = GetLastError() );
LocalFree( driveLayout );
return(status);
}
printf("FixDriveLayout, disk signature is %u, partition count is %u.\n",
driveLayout->Signature, driveLayout->PartitionCount);
//
// Read the drive capacity to get bytesPerSector and bytesPerCylinder.
//
success = DeviceIoControl( fileHandle,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY),
&returnLength,
FALSE );
if ( !success ) {
printf("FixDriveLayout, error reading drive capacity. Error: %u \n",
status = GetLastError());
LocalFree( driveLayout );
return(status);
}
printf("FixDriveLayout, bps = %u, spt = %u, tpc = %u.\n",
diskGeometry.BytesPerSector, diskGeometry.SectorsPerTrack,
diskGeometry.TracksPerCylinder);
//
// If read of the partition table originally failed, then we rebuild
// it!
//
if ( !driveLayout->PartitionCount ) {
driveLayout->PartitionCount = MAX_PARTITIONS;
bytesPerTrack = diskGeometry.SectorsPerTrack *
diskGeometry.BytesPerSector;
bytesPerCylinder = diskGeometry.TracksPerCylinder *
bytesPerTrack;
partInfo = &driveLayout->PartitionEntry[0];
partLength.QuadPart = partInfo->PartitionLength.QuadPart;
//
// The partition offset is 1 track (in bytes).
// Size is media_size - offset, rounded down to cylinder boundary.
//
partOffset.QuadPart = bytesPerTrack;
partSize.QuadPart = partLength.QuadPart - partOffset.QuadPart;
modulo.QuadPart = (partOffset.QuadPart + partSize.QuadPart) %
bytesPerCylinder;
partSize.QuadPart -= modulo.QuadPart;
partInfo = driveLayout->PartitionEntry;
//
// Initialize first partition entry.
//
partInfo->RewritePartition = TRUE;
partInfo->PartitionType = PARTITION_HUGE;
partInfo->BootIndicator = FALSE;
partInfo->StartingOffset.QuadPart = partOffset.QuadPart;
partInfo->PartitionLength.QuadPart = partSize.QuadPart;
partInfo->HiddenSectors = 0;
partInfo->PartitionNumber = 0;
//
// For now, the remaining partition entries are unused.
//
for ( index = 1; index < MAX_PARTITIONS; index++ ) {
partInfo->RewritePartition = TRUE;
partInfo->PartitionType = PARTITION_ENTRY_UNUSED;
partInfo->BootIndicator = FALSE;
partInfo->StartingOffset.QuadPart = 0;
partInfo->PartitionLength.QuadPart = 0;
partInfo->HiddenSectors = 0;
partInfo->PartitionNumber = 0;
}
} else {
//
// Recalculate the starting offset for the extended partitions.
//
for ( index = 0; index < driveLayout->PartitionCount; index++ ) {
LARGE_INTEGER extendedOffset;
LARGE_INTEGER bytesPerSector;
bytesPerSector.QuadPart = diskGeometry.BytesPerSector;
extendedOffset.QuadPart = 0;
partInfo = &driveLayout->PartitionEntry[index];
partInfo->RewritePartition = TRUE;
if ( IsContainerPartition(partInfo->PartitionType) ) {
//
// If this is the first extended partition, then remember
// the offset to added to the next partition.
//
if ( extendedOffset.QuadPart == 0 ) {
extendedOffset.QuadPart = bytesPerSector.QuadPart *
(LONGLONG)partInfo->HiddenSectors;
} else {
//
// We need to recalculate this extended partition's starting
// offset based on the current 'HiddenSectors' field and
// the first extended partition's offset.
//
partInfo->StartingOffset.QuadPart = extendedOffset.QuadPart
+ (bytesPerSector.QuadPart *
(LONGLONG)partInfo->HiddenSectors);
partInfo->HiddenSectors = 0;
}
}
}
}
//
// Now set the new partition information.
//
success = DeviceIoControl( fileHandle,
IOCTL_DISK_SET_DRIVE_LAYOUT,
driveLayout,
driveLayoutSize,
NULL,
0,
&returnLength,
FALSE );
if ( !success ) {
printf("FixDriveLayout, error setting partition information. Error: %u \n",
status = GetLastError() );
LocalFree( driveLayout );
return(status);
}
LocalFree( driveLayout );
return(ERROR_SUCCESS);
} // FixDriveLayout
#endif
static DWORD
GetDriveLetter(
PUCHAR deviceNameString
)
{
UCHAR driveLetter;
WCHAR deviceName[MAX_PATH];
NTSTATUS status;
mbstowcs( deviceName, deviceNameString, strlen(deviceNameString) );
status = GetAssignedLetter(deviceName, &driveLetter);
if ( NT_SUCCESS(status) ) {
if (driveLetter) {
wprintf(L"%ws ----> %c:\n", deviceName, driveLetter);
} else {
wprintf(L"%ws has no drive letter\n", deviceName);
}
}
return RtlNtStatusToDosError( status );
}
NTSTATUS
GetVolumeInformationFromHandle(
HANDLE Handle
)
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
UCHAR VolumeInfoBuffer[ sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(WCHAR) * MAX_PATH ];
UCHAR AttrInfoBuffer[ sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + sizeof(WCHAR) * MAX_PATH ];
ULONG VolumeInfoLength = sizeof(VolumeInfoBuffer);
ULONG AttributeInfoLength = sizeof(AttrInfoBuffer);
PFILE_FS_VOLUME_INFORMATION VolumeInfo = (PFILE_FS_VOLUME_INFORMATION)VolumeInfoBuffer;
PFILE_FS_ATTRIBUTE_INFORMATION AttributeInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)AttrInfoBuffer;
ZeroMemory(VolumeInfoBuffer, (sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(WCHAR) * MAX_PATH));
ZeroMemory(AttrInfoBuffer, (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + sizeof(WCHAR) * MAX_PATH));
Status = NtQueryVolumeInformationFile(
Handle,
&IoStatusBlock,
VolumeInfo,
VolumeInfoLength,
FileFsVolumeInformation
);
if ( !NT_SUCCESS(Status) ) {
return Status;
}
Status = NtQueryVolumeInformationFile(
Handle,
&IoStatusBlock,
AttributeInfo,
AttributeInfoLength,
FileFsAttributeInformation
);
if ( !NT_SUCCESS(Status) ) {
return Status;
}
AttributeInfo->FileSystemName[AttributeInfo->FileSystemNameLength] = 0;
VolumeInfo->VolumeLabel[VolumeInfo->VolumeLabelLength] = 0;
printf("\nGetVolumeInformationFromHandle data: \n");
printf("Volume information: \n");
printf(" VolumeCreationTime 0x%lx : %lx \n",
VolumeInfo->VolumeCreationTime.HighPart,
VolumeInfo->VolumeCreationTime.LowPart);
printf(" VolumeSerialNumber 0x%lx \n", VolumeInfo->VolumeSerialNumber);
printf(" VolumeLabelLength 0x%lx \n", VolumeInfo->VolumeLabelLength);
printf(" SupportsObjects (BOOL) 0x%lx \n", VolumeInfo->SupportsObjects);
printf(" VolumeLabel %ws \n", VolumeInfo->VolumeLabel);
printf("Attribute Information: \n");
printf(" FileSystemAttributes (Flags) 0x%lx \n", AttributeInfo->FileSystemAttributes);
printf(" MaximumComponentNameLength 0x%lx \n", AttributeInfo->MaximumComponentNameLength);
printf(" FileSystemNameLength 0x%lx \n", AttributeInfo->FileSystemNameLength);
printf(" FileSystemName %ws \n\n", AttributeInfo->FileSystemName);
return STATUS_SUCCESS;
}
#define FIRST_SHOT_SIZE 512
PVOID
DoIoctlAndAllocate(
IN HANDLE FileHandle,
IN DWORD IoControlCode,
IN PVOID InBuf,
IN ULONG InBufSize,
OUT PDWORD BytesReturned
)
{
UCHAR firstShot[ FIRST_SHOT_SIZE ];
DWORD status = ERROR_SUCCESS;
BOOL success;
DWORD outBufSize;
PVOID outBuf = 0;
DWORD bytesReturned;
success = DeviceIoControl( FileHandle,
IoControlCode,
InBuf,
InBufSize,
firstShot,
sizeof(firstShot),
&bytesReturned,
(LPOVERLAPPED) NULL );
if ( success ) {
outBufSize = bytesReturned;
outBuf = malloc( outBufSize );
if (!outBuf) {
status = ERROR_OUTOFMEMORY;
} else {
RtlCopyMemory(outBuf, firstShot, outBufSize);
status = ERROR_SUCCESS;
}
} else {
outBufSize = sizeof(firstShot);
for(;;) {
status = GetLastError();
//
// If it is not a buffer size related error, then we cannot do much
//
if ( status != ERROR_INSUFFICIENT_BUFFER && status != ERROR_MORE_DATA) {
break;
}
//
// Otherwise, try an outbut buffer twice the previous size
//
outBufSize *= 2;
outBuf = malloc( outBufSize );
if ( !outBuf ) {
status = ERROR_OUTOFMEMORY;
break;
}
success = DeviceIoControl( FileHandle,
IoControlCode,
InBuf,
InBufSize,
outBuf,
outBufSize,
&bytesReturned,
(LPOVERLAPPED) NULL );
if (success) {
status = ERROR_SUCCESS;
break;
}
free( outBuf );
}
}
if (status != ERROR_SUCCESS) {
free( outBuf ); // free( 0 ) is legal //
outBuf = 0;
bytesReturned = 0;
}
SetLastError( status );
*BytesReturned = bytesReturned;
return outBuf;
}
#define OUTPUT_BUFFER_LEN (1024)
#define INPUT_BUFFER_LEN (sizeof(MOUNTMGR_MOUNT_POINT) + 2 * MAX_PATH * sizeof(WCHAR))
static
NTSTATUS
GetAssignedLetterM (
IN HANDLE MountMgrHandle,
IN PWCHAR deviceName,
OUT PCHAR driveLetter )
/*++
Routine Description:
Get an assigned drive letter from MountMgr, if any
Inputs:
MountMgrHandle -
deviceName -
driveLetter - receives drive letter
Return value:
STATUS_SUCCESS - on success
NTSTATUS code - on failure
--*/
{
DWORD status = STATUS_SUCCESS;
PMOUNTMGR_MOUNT_POINT input = NULL;
PMOUNTMGR_MOUNT_POINTS output = NULL;
PMOUNTMGR_MOUNT_POINT out;
DWORD len = wcslen( deviceName ) * sizeof(WCHAR);
DWORD bytesReturned;
DWORD idx;
DWORD outputLen;
DWORD inputLen;
WCHAR wc;
inputLen = INPUT_BUFFER_LEN;
input = LocalAlloc( LPTR, inputLen );
if ( !input ) {
goto FnExit;
}
input->SymbolicLinkNameOffset = 0;
input->SymbolicLinkNameLength = 0;
input->UniqueIdOffset = 0;
input->UniqueIdLength = 0;
input->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
input->DeviceNameLength = (USHORT) len;
RtlCopyMemory((PCHAR)input + input->DeviceNameOffset,
deviceName, len );
if (len > sizeof(WCHAR) && deviceName[1] == L'\\') {
// convert Dos name to NT name
((PWCHAR)(input + input->DeviceNameOffset))[1] = L'?';
}
outputLen = OUTPUT_BUFFER_LEN;
output = LocalAlloc( LPTR, outputLen );
if ( !output ) {
goto FnExit;
}
status = DevfileIoctl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
input, inputLen, output, outputLen, &bytesReturned);
if ( STATUS_BUFFER_OVERFLOW == status ) {
outputLen = output->Size;
LocalFree( output );
output = LocalAlloc( LPTR, outputLen );
if ( !output ) {
goto FnExit;
}
status = DevfileIoctl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
input, inputLen, output, outputLen, &bytesReturned);
}
if ( !NT_SUCCESS(status) ) {
goto FnExit;
}
if (driveLetter) {
*driveLetter = 0;
}
for ( idx = 0; idx < output->NumberOfMountPoints; ++idx ) {
out = &output->MountPoints[idx];
if (out->SymbolicLinkNameLength/sizeof(WCHAR) == 14 &&
(ClRtlStrNICmp((PWCHAR)((PCHAR)output + out->SymbolicLinkNameOffset), L"\\DosDevices\\", 12) == 0) &&
L':' == *((PCHAR)output + out->SymbolicLinkNameOffset + 13*sizeof(WCHAR)) )
{
wc = *((PCHAR)output + out->SymbolicLinkNameOffset + 12*sizeof(WCHAR));
if (driveLetter && out->UniqueIdLength) {
*driveLetter = (CHAR)toupper((UCHAR)wc);
break;
}
}
}
FnExit:
if ( output ) {
LocalFree( output );
}
if ( input ) {
LocalFree( input );
}
return status;
}
NTSTATUS
GetAssignedLetter (
PWCHAR deviceName,
PCHAR driveLetter )
{
HANDLE MountMgrHandle;
DWORD status = DevfileOpen( &MountMgrHandle, MOUNTMGR_DEVICE_NAME );
if (driveLetter) {
*driveLetter = 0;
}
if ( NT_SUCCESS(status) ) {
status = GetAssignedLetterM(MountMgrHandle, deviceName, driveLetter);
DevfileClose(MountMgrHandle);
}
return status;
}
DWORD
PokeMountMgr (
VOID
)
{
HANDLE MountMgrHandle;
NTSTATUS ntStatus = DevfileOpen( &MountMgrHandle, MOUNTMGR_DEVICE_NAME );
DWORD status = ERROR_SUCCESS;
if ( NT_SUCCESS(ntStatus) ) {
BOOL success;
DWORD bytesReturned;
printf("About to call MOUNTMGR_CHECK_UNPROCESSED_VOLUMES...");
success = DeviceIoControl( MountMgrHandle,
IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES,
NULL,
0,
NULL,
0,
&bytesReturned,
FALSE );
printf("complete.\n");
if (!success) {
status = GetLastError();
}
DevfileClose(MountMgrHandle);
} else {
status = RtlNtStatusToDosError(ntStatus);
}
return status;
}
VOID
PrintError(
IN DWORD ErrorCode
)
{
LPVOID lpMsgBuf;
ULONG count;
count = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ErrorCode,
0,
(LPTSTR) &lpMsgBuf,
0,
NULL
);
if (count != 0) {
printf(" (%d) %s\n", ErrorCode, (LPCTSTR) lpMsgBuf);
LocalFree( lpMsgBuf );
} else {
printf("Format message failed. Error: %d \n", GetLastError());
}
} // PrintError
DWORD
GetSerialNumber(
HANDLE FileHandle
)
{
PSTORAGE_DEVICE_DESCRIPTOR descriptor = NULL;
PCHAR sigString;
DWORD dwError = NO_ERROR;
DWORD descriptorSize;
DWORD bytesReturned;
STORAGE_PROPERTY_QUERY propQuery;
descriptorSize = sizeof( STORAGE_DEVICE_DESCRIPTOR) + 2048;
descriptor = LocalAlloc( LPTR, descriptorSize );
if ( !descriptor ) {
dwError = GetLastError();
printf("Unable to allocate output buffer: %d \n", dwError);
PrintError( dwError );
goto FnExit;
}
ZeroMemory( &propQuery, sizeof( propQuery ) );
propQuery.PropertyId = StorageDeviceProperty;
propQuery.QueryType = PropertyStandardQuery;
if ( !DeviceIoControl( FileHandle,
IOCTL_STORAGE_QUERY_PROPERTY,
&propQuery,
sizeof(propQuery),
descriptor,
descriptorSize,
&bytesReturned,
NULL ) ) {
dwError = GetLastError();
printf("IOCTL_STORAGE_QUERY_PROPERTY failed: %d \n", dwError);
PrintError( dwError );
goto FnExit;
}
if ( !bytesReturned || bytesReturned < sizeof( STORAGE_DEVICE_DESCRIPTOR ) ) {
printf("Invalid byte length returned: %d \n", bytesReturned);
goto FnExit;
}
//
// IA64 sometimes returns -1 for SerialNumberOffset.
//
if ( 0 == descriptor->SerialNumberOffset ||
descriptor->SerialNumberOffset > descriptor->Size ) {
printf("No serial number information available \n");
goto FnExit;
}
//
// Serial number string is a zero terminated ASCII string.
//
// The header ntddstor.h says the for devices with no serial number,
// the offset will be zero. This doesn't seem to be true.
//
// For devices with no serial number, it looks like a string with a single
// null character '\0' is returned.
//
sigString = (PCHAR)descriptor + (DWORD)descriptor->SerialNumberOffset;
if ( strlen(sigString) == 0) {
printf("Serial number: NULL string returned \n");
} else {
printf("Serial number: %s \n", sigString);
}
FnExit:
if ( descriptor ) {
LocalFree( descriptor );
}
return dwError;
} // GetSerialNumber
DWORD
UpdateDiskProperties(
HANDLE fileHandle
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
DWORD dwError = ERROR_SUCCESS;
DWORD bytesReturned;
BOOL success;
if ( INVALID_HANDLE_VALUE == fileHandle ) {
printf( "usage: <device> UpdateDiskProperties \n" );
dwError = ERROR_INVALID_NAME;
goto FnExit;
}
success = DeviceIoControl( fileHandle,
IOCTL_DISK_UPDATE_PROPERTIES,
NULL,
0,
NULL,
0,
&bytesReturned,
FALSE );
if ( !success ) {
dwError = GetLastError();
printf( "IOCTL_DISK_UPDATE_PROPERTIES failed, error %d \n", dwError);
PrintError( dwError );
goto FnExit;
}
printf("IOCTL_DISK_UPDATE_PROPERTIES succeeded \n");
FnExit:
return dwError;
} // UpdateDiskProperties
BOOL
IsDeviceClustered(
HANDLE Device
)
/*++
Routine Description:
Determine if the specified device is on a clustered disk.
Arguments:
Device - physical disk (partition0) or any disk volume.
Return Value:
TRUE if disk is clustered.
FALSE if disk is not clustered, or cannot determine state.
--*/
{
DWORD bytesReturned;
DWORD dwError;
BOOL retValue;
if ( !DeviceIoControl( Device,
IOCTL_VOLUME_IS_CLUSTERED,
NULL,
0,
NULL,
0,
&bytesReturned,
NULL )) {
dwError = GetLastError();
printf("IOCTL_VOLUME_IS_CLUSTERED failed (%d) - ", dwError);
if ( ERROR_INVALID_FUNCTION == dwError ) {
printf("device is not clustered \n");
} else if ( ERROR_GEN_FAILURE == dwError ) {
printf("clustered device is possibly offline \n");
} else {
printf("expected error returned \n");
}
retValue = FALSE;
} else {
printf("IOCTL_VOLUME_IS_CLUSTERED succeeded - device is clustered \n");
retValue = TRUE;
}
return retValue;
} // IsDeviceClustered
DWORD
GetReserveInfo(
HANDLE FileHandle
)
{
PDRIVE_LAYOUT_INFORMATION driveLayout = NULL;
NTSTATUS ntStatus;
DWORD dwError;
DWORD bytesReturned;
HANDLE hClusDisk0;
UNICODE_STRING unicodeName;
ANSI_STRING objName;
OBJECT_ATTRIBUTES objAttributes;
IO_STATUS_BLOCK ioStatusBlock;
RESERVE_INFO params;
BOOL success;
//
// Get the signature.
//
success = ClRtlGetDriveLayoutTable( FileHandle, &driveLayout, NULL );
if ( !success || !driveLayout ) {
printf(" Unable to read drive layout \n");
dwError = ERROR_GEN_FAILURE;
goto FnExit;
}
RtlInitString( &objName, DEVICE_CLUSDISK0 );
ntStatus = RtlAnsiStringToUnicodeString( &unicodeName,
&objName,
TRUE );
if ( !NT_SUCCESS(ntStatus) ) {
dwError = RtlNtStatusToDosError(ntStatus);
printf( "Error converting string to unicode; error was %d \n", dwError);
PrintError(dwError);
goto FnExit;
}
InitializeObjectAttributes( &objAttributes,
&unicodeName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
ntStatus = NtCreateFile( &hClusDisk0,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0 );
RtlFreeUnicodeString( &unicodeName );
if ( !NT_SUCCESS(ntStatus) ) {
dwError = RtlNtStatusToDosError(ntStatus);
printf( "Error opening ClusDisk0 device; error was %d \n", dwError);
PrintError(dwError);
goto FnExit;
}
params.Signature = driveLayout->Signature;
success = DeviceIoControl( hClusDisk0,
IOCTL_DISK_CLUSTER_RESERVE_INFO,
&params,
sizeof(params),
&params,
sizeof(params),
&bytesReturned,
FALSE);
NtClose( hClusDisk0 );
if ( !success ) {
printf( "Error retrieving ReserveInfo; error was %d\n",
dwError = GetLastError() );
PrintError(dwError);
} else {
printf( "Signature: %08x ReserveFailure: %08x \n",
params.Signature,
params.ReserveFailure );
printf( "LastReserveEnd: %x:%x CurrentTime: %x:%x \n",
params.LastReserveEnd.HighPart,
params.LastReserveEnd.LowPart,
params.CurrentTime.HighPart,
params.CurrentTime.LowPart );
printf( "*** Last reserve completed %d milliseconds ago *** \n",
( params.CurrentTime.QuadPart - params.LastReserveEnd.QuadPart ) / 10000 );
printf( "ArbWriteCount: %x ReserveCount: %x \n",
params.ArbWriteCount,
params.ReserveCount);
printf("\n");
dwError = NO_ERROR;
}
FnExit:
LocalFree( driveLayout );
return dwError;
} // GetReserveInfo
static void
usage(
char *programName
)
/*++
Routine Description:
Description
Arguments:
None
Return Value:
None
--*/
{
printf( "usage: %s target_device command\n", programName );
printf( "commands:\n" );
printf( "\tReset\n" );
printf( "\tReserve\n" );
printf( "\tRelease\n" );
printf( "\tBreakReserve\n" );
printf( "\tOnline\n" );
printf( "\tOffline\n" );
printf( "\tGetState \n");
printf( "\tCheckUnclaimedPartitions\n" );
printf( "\tEjectVolumes\n");
printf( "\tPokeMountMgr\n" );
printf( "\tEnumMounts\n" );
printf( "\tEnumExtents\n" );
printf( "\tEnumNodes\n" );
printf( "\tEnumDisks\n" );
printf( "\tGetDiskGeometry\n" );
printf( "\tGetScsiAddress\n" );
printf( "\tGetDriveLayout\n" );
printf( "\tGetDriveLayoutEx\n");
printf( "\tSetDriveLayout\n" );
printf( "\tGetPartitionInfo\n" );
printf( "\tGetVolumeInfo\n" );
printf( "\tGetDriveLetter\n" );
printf( "\tGetSerialNumber\n");
printf( "\tGetReserveInfo\n");
printf( "\tReadSector\n" );
printf( "\tReadSectorIoctl\n" );
printf( "\tTest\n" );
printf( "\tUpdateDiskProperties\n");
printf( "\tIsClustered \n");
printf( "\tCapable\n" );
printf( "\tAttach [ClusDisk0 device] \n" );
printf( "\tDetach [ClusDisk0 device] \n" );
printf( "\tStartReserve [ClusDisk0 device] \n" );
printf( "\tStopReserve [ClusDisk0 device] \n" );
printf( "\tActive [ClusDisk0 device] \n" );
printf( "\ntarget_device wildcards: \n" );
printf( "\tAll physical devices: use p* \n" );
printf( "\tAll logical devices: use l* or * \n" );
}