Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
DriverGestaltExplorer.c
/* |
File: DriverGestaltExplorer.c |
Description:DriverGestaltExplorer is both sample code showing how to call Driver |
Gestalt and a useful tool for testing your block device driverÕs support |
of Driver Gestalt. |
Author: Quinn |
Copyright: Copyright: © 1998-1999 by Apple Computer, Inc. |
all rights reserved. |
Disclaimer: You may incorporate this sample code into your applications without |
restriction, though the sample code has been provided "AS IS" and the |
responsibility for its operation is 100% yours. However, what you are |
not permitted to do is to redistribute the source as "DSC Sample Code" |
after having made changes. If you're going to re-distribute the source, |
we require that you make it clear in the source that the code was |
descended from Apple Sample Code, but that you've made changes. |
Change History (most recent first): |
6/23/99 Updated for Metrowerks Codewarrior Pro 2.1(KG) |
*/ |
///////////////////////////////////////////////////////////////// |
// Standard Mac OS Interfaces |
#include <DriverGestalt.h> |
///////////////////////////////////////////////////////////////// |
// Standard C Libraries |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
///////////////////////////////////////////////////////////////// |
// We use some of the utility routines from TradDriverLoaderLib, |
// which prevents us having to reinvent the wheel. |
#include "TradDriverLoaderLib.h" |
///////////////////////////////////////////////////////////////// |
#pragma mark ----- Utility Routines ----- |
static void QAssert(Boolean mustBeTrue) |
// Stardard Assert functionality. How many times have |
// I written this? How much time would I save if it was |
// built into the OS? |
{ |
if ( ! mustBeTrue ) { |
DebugStr("\pQAssert: Assertion failure"); |
} |
} |
static DriverRefNum MapDriveToRefNum(SInt16 drive) |
// Walks the drive queue looking for the given drive |
// and returns the driver reference number of the driver |
// controlling the drive. |
// |
// I would have used UTFindDrive for this, but calling |
// it from PowerPC is tricky. |
{ |
DrvQElPtr thisDrv; |
thisDrv = (DrvQElPtr) GetDrvQHdr()->qHead; |
while (thisDrv != nil) { |
if (thisDrv->dQDrive == drive) { |
return thisDrv->dQRefNum; |
} |
thisDrv = (DrvQElPtr) thisDrv->qLink; |
} |
return 0; |
} |
static Boolean DriveSupportsDriverGestalt(SInt16 drive) |
// Returns true if the driver controlling the |
// supplied drive supports Driver Gestalt. |
{ |
OSErr junk; |
DriverRefNum refNum; |
DriverFlags driverFlags; |
refNum = MapDriveToRefNum(drive); |
junk = TradGetDriverInformation(refNum, nil, &driverFlags, nil, nil); |
QAssert(junk == noErr); |
return TradDriverGestaltIsOn(driverFlags); |
} |
static StringPtr RefNumToName(DriverRefNum refNum) |
// Returns the (Pascal string) name of the driver with the supplied |
// refNum. Basically a wrapper around TradDriverLoaderLib. |
// |
// Note that the routine returns the address of a static |
// buffer, so you don't have to dispose it but you must |
// be careful not to call the routine again until you're |
// done with the result. |
{ |
static Str255 nonReentrantBuffer; |
OSErr junk; |
junk = TradGetDriverInformation(refNum, nil, nil, nonReentrantBuffer, nil); |
QAssert(junk == noErr); |
return nonReentrantBuffer; |
} |
static char *OSTypeToString(OSType selector) |
// Returns a C string for the supplied selector. |
// |
// Note that the routine returns the address of a static |
// buffer, so you don't have to dispose it but you must |
// be careful not to call the routine again until you're |
// done with the result. |
{ |
static char nonReentrantBuffer[5]; |
*((OSType*) nonReentrantBuffer) = selector; |
nonReentrantBuffer[4] = 0; |
return nonReentrantBuffer; |
} |
///////////////////////////////////////////////////////////////// |
#pragma mark ----- Data Table Types ----- |
// An array of OSTypeElement's is passed as the argument |
// to OSTypeDisplay. The array is terminated by an element |
// whose name is nil. This array allows OSTypeDisplay to |
// map an OSType to its string description. |
struct OSTypeElement { |
OSType value; |
char* name; |
}; |
typedef struct OSTypeElement OSTypeElement; |
// The address of a BooleanTable is passed as the argument |
// to BooleanDisplay. The table allows BooleanDisplay to |
// map a Boolean result to a string description. |
struct BooleanTable { |
char *trueString; |
char *falseString; |
}; |
typedef struct BooleanTable BooleanTable; |
// An array of FlagElement's is passed as the argument |
// to Flags16Display and Flags32Display, and hence on |
// to PrintFlags. The array is terminated by an element |
// whose mask is 0. This array allows PrintFlags to |
// test for the known flags in a flags UInt32 and print |
// out the corresponding textual descriptions. |
struct FlagElement { |
UInt32 mask; |
char *trueString; |
char *falseString; |
}; |
typedef struct FlagElement FlagElement; |
// A GestaltElement holds information about a single |
// DriverGestalt selector, including the selector itself, |
// a textual description of the selector (name), the address |
// of a routine that can print the response, and the argument |
// for that routine. |
// |
// The primary use of this type is in gGestaltList, |
// an array of these elements (terminated by an entry with |
// a selector of 0) which describes all the Driver Gestalt |
// selectors documented at the time this sample was last updated. |
typedef void (*ResponseDisplayProc)(DriverGestaltParam *pb, void *arg); |
struct GestaltElement { |
OSType selector; |
char* name; |
ResponseDisplayProc responseDisplayRoutine; |
void* responseDisplayArg; |
}; |
typedef struct GestaltElement GestaltElement; |
///////////////////////////////////////////////////////////////// |
#pragma mark ----- Response Printing ----- |
// The routines in this section are responsible for taking a |
// Driver Gestalt response and printing it to stdout. They |
// all conform to the ResponseDisplayProc type and are referenced |
// by gGestaltList table. |
// |
// The routines are given in the order of most generic to most |
// specific. |
static void DefaultDisplay(DriverGestaltParam *pb, void *arg) |
// Prints a Driver Gestalt response for a selector we |
// don't know about. All we can do is print the four |
// standard response fields as hex. |
{ |
#pragma unused(arg) |
printf(" driverGestaltResponse = %08lx\n", pb->driverGestaltResponse); |
printf(" driverGestaltResponse1 = %08lx\n", pb->driverGestaltResponse1); |
printf(" driverGestaltResponse2 = %08lx\n", pb->driverGestaltResponse2); |
printf(" driverGestaltResponse3 = %08lx\n", pb->driverGestaltResponse3); |
} |
static void OSTypeDisplay(DriverGestaltParam *pb, void *arg) |
// Prints a Driver Gestalt response in driverGestaltResponse |
// whose value is an OSType. arg is a pointer to an array |
// of OSTypeElements that describes the expected values |
// and their textual descriptions. |
{ |
OSType response; |
OSTypeElement *responseList; |
Boolean found; |
ItemCount thisIndex; |
response = (OSType) pb->driverGestaltResponse; |
responseList = (OSTypeElement *) arg; |
// Search for response in the responseList. |
found = false; |
thisIndex = 0; |
while ( ! found && responseList[thisIndex].name != nil ) { |
found = (responseList[thisIndex].value == response); |
if ( ! found ) { |
thisIndex += 1; |
} |
} |
// If we found it, print the response with its textual description, |
// otherwise just print the response. |
if (found) { |
printf(" Response = '%s' Ò%sÓ\n", OSTypeToString(response), responseList[thisIndex].name); |
} else { |
printf(" Response = '%s'\n", OSTypeToString(response)); |
} |
} |
static void BooleanDisplay(DriverGestaltParam *pb, void *arg) |
// Prints a Driver Gestalt response which is a Boolean in the |
// first byte of driverGestaltResponse. arg is a pointer to |
// an array of BooleanElements that gives the textual descriptions |
// for true and false. |
{ |
BooleanTable *booleanTable; |
Boolean value; |
booleanTable = (BooleanTable *) arg; |
value = *GetDriverGestaltBooleanResponse(pb); |
switch (value) { |
case true: |
printf(" Response = %d Ò%sÓ\n", value, booleanTable->trueString); |
break; |
case false: |
printf(" Response = %d Ò%sÓ\n", value, booleanTable->falseString); |
break; |
default: |
printf(" Response = %d (Weird)\n", value); |
break; |
} |
} |
static void PrintFlags(UInt32 flags, FlagElement flagList[]) |
// A utility routine called by Flags16Display and Flags32Display. |
// flags is the response flags to be printed. The routine |
// prints both the value of flags and a textual description |
// of the flags based on flagList, an array of FlagElements |
// which describes the known flag masks and the textual |
// descriptions for those masks. |
{ |
ItemCount thisIndex; |
printf(" Response = %08lx\n", flags); |
thisIndex = 0; |
while ( flagList[thisIndex].mask != 0 ) { |
if ( (flags & flagList[thisIndex].mask) != 0 ) { |
printf(" %s\n", flagList[thisIndex].trueString); |
} else { |
printf(" %s\n", flagList[thisIndex].falseString); |
} |
thisIndex += 1; |
} |
} |
static void Flags16Display(DriverGestaltParam *pb, void *arg) |
// Prints a Driver Gestalt response which is a UInt32 in the |
// first two bytes of driverGestaltResponse. arg is a pointer to |
// an array of FlagElements which describes the known flag masks and |
// the textual descriptions for those masks. |
{ |
UInt32 flags; |
flags = *((UInt16 *) &pb->driverGestaltResponse); |
PrintFlags(flags, arg); |
} |
static void Flags32Display(DriverGestaltParam *pb, void *arg) |
// Prints a Driver Gestalt response which is a UInt32 in the |
// driverGestaltResponse. arg is a pointer to an array of |
// FlagElements which describes the known flag masks and |
// the textual descriptions for those masks. |
{ |
UInt32 flags; |
flags = *((UInt32 *) &pb->driverGestaltResponse); |
PrintFlags(flags, arg); |
} |
static void PowerDisplay(DriverGestaltParam *pb, void *arg) |
// Prints a Driver Gestalt power response, used by the |
// various power rating selectors to return the |
// power in microWatts. arg is unused. |
{ |
#pragma unused(arg) |
DriverGestaltPowerResponse* response; |
response = GetDriverGestaltPowerResponse(pb); |
printf(" Response = %ld microWatts\n", response->powerValue); |
} |
static void VersionDisplay(DriverGestaltParam *pb, void *arg) |
// Prints a Driver Gestalt response which is a NumVersion in |
// driverGestaltResponse. arg is unused. |
{ |
#pragma unused(arg) |
NumVersion version; |
char versionString[256]; |
char tmpString[256]; |
char stageChar; |
version = *((NumVersion *) &pb->driverGestaltResponse); |
sprintf(versionString, "%d.%d", version.majorRev, (version.minorAndBugRev >> 4) & 0x0f); |
if ( (version.minorAndBugRev & 0x0f) != 0 ) { |
sprintf(tmpString, ".%d", version.minorAndBugRev & 0x0f); |
strcat(versionString, tmpString); |
} |
if ( version.stage != finalStage || version.nonRelRev != 0 ) { |
switch (version.stage) { |
case finalStage: |
stageChar = 'f'; |
break; |
case betaStage: |
stageChar = 'b'; |
break; |
case alphaStage: |
stageChar = 'a'; |
break; |
case developStage: |
stageChar = 'd'; |
break; |
default: |
stageChar = '?'; |
break; |
} |
sprintf(tmpString, "%c%d", stageChar, version.nonRelRev); |
strcat(versionString, tmpString); |
} |
printf(" Response = %s (%08lx)\n", versionString, pb->driverGestaltResponse); |
} |
static void BootDisplay(DriverGestaltParam *pb, void *arg) |
// Prints the response to the Driver Gestalt kdgBoot selector, |
// which is a DriverGestaltBootResponse. arg is unused. |
{ |
#pragma unused(arg) |
DriverGestaltBootResponse* response; |
response = GetDriverGestaltBootResponse(pb); |
printf(" extDev = %d\n", response->extDev); |
printf(" partition = %d\n", response->partition); |
printf(" SIMSlot = %d\n", response->SIMSlot); |
printf(" SIMsRSRC = %d\n", response->SIMsRSRC); |
} |
static void PurgeDisplay(DriverGestaltParam *pb, void *arg) |
// Prints the response to the Driver Gestalt kdgPurge selector, |
// which is a DriverGestaltBootResponse. arg is unused. |
{ |
#pragma unused(arg) |
DriverGestaltPurgeResponse *response; |
response = GetDriverGestaltPurgeResponse(pb); |
PrintFlags(response->purgePermission, arg); |
printf(" purgeDriverPointer = %08lx\n", response->purgeDriverPointer); |
} |
static void FlushDisplay(DriverGestaltParam *pb, void *arg) |
// Prints the response to the Driver Gestalt kdgFlush selector, |
// which is a GetDriverGestaltFlushResponse. arg is unused. |
{ |
#pragma unused(arg) |
DriverGestaltFlushResponse* response; |
char *tmpStr; |
response = GetDriverGestaltFlushResponse(pb); |
if (response->canFlush) { |
tmpStr = "Driver supports kdcFlush Driver Configure call"; |
} else { |
tmpStr = "Driver does not support kdcFlush Driver Configure call"; |
} |
printf(" canFlush = %d Ò%sÓ\n", response->canFlush, tmpStr); |
if (response->needsFlush) { |
tmpStr = "Driver needs flush when volume flushed"; |
} else { |
tmpStr = "Driver does not need flush when volume flushed"; |
} |
printf(" needsFlush = %d Ò%sÓ\n", response->needsFlush, tmpStr); |
} |
static void MediaInfoDisplay(DriverGestaltParam *pb, void *arg) |
// Prints the response to the Driver Gestalt kdgMediaInfo selector, |
// which is a DriverGestaltMediaInfoResponse. arg is unused. |
{ |
#pragma unused(arg) |
DriverGestaltMediaInfoResponse* response; |
response = GetDriverGestaltMediaInfoResponse(pb); |
printf(" numberBlocks = %ld\n", response->numberBlocks); |
printf(" blockSize = %ld\n", response->blockSize); |
switch (response->mediaType) { |
case kMediaTypeUnknown: |
printf(" mediaType = ÒunknownÓ\n"); |
break; |
case kMediaTypeCDROM: |
printf(" mediaType = ÒCD-ROMÓ\n"); |
break; |
case kMediaTypeDVDROM: |
printf(" mediaType = ÒDVD-ROMÓ\n"); |
break; |
case kMediaTypeNoMedia: |
printf(" mediaType = Òno mediaÓ\n"); |
break; |
} |
} |
///////////////////////////////////////////////////////////////// |
#pragma mark ----- Data Tables ----- |
#pragma mark OSType Tables |
// gInterfaceTypeList describes the expected results |
// from the kdgInterface selector. |
static OSTypeElement gInterfaceTypeList[] = { |
{kdgScsiIntf, "SCSI"}, |
{kdgPcmciaIntf, "PC Card"}, |
{kdgATAIntf, "ATA"}, |
{kdgFireWireIntf, "Firewire"}, |
{kdgExtBus, "External Bus"}, |
{0, nil} |
}; |
// gDeviceTypeList describes the expected results |
// from the kdgDeviceType selector. |
static OSTypeElement gDeviceTypeList[] = { |
{kdgDiskType, "Disk"}, |
{kdgTapeType, "Tape"}, |
{kdgPrinterType, "Printer"}, |
{kdgProcessorType, "Processor"}, |
{kdgWormType, "Write-Once, Read Many"}, |
{kdgCDType, "CD-ROM"}, |
{kdgFloppyType, "Floppy"}, |
{kdgScannerType, "Scanner"}, |
{kdgFileType, "File (ie disk image)"}, |
{kdgRemovableType, "Removable Disk"}, |
{0, nil} |
}; |
#pragma mark Boolean Tables |
// Boolean results from various selectors. |
static BooleanTable gSyncBooleanTable = { "Synchronous", "Asynchronous" }; |
static BooleanTable gWideBooleanTable = { "Supports wide ioPosMode", "No support for wide ioPosMode" }; |
static BooleanTable gPowerSwitchBooleanTable = { "Supports power switching", "No support for power switching" }; |
static BooleanTable gHighPowerBooleanTable = { "In high power mode", "In low power mode" }; |
static BooleanTable gSupportsPowerControlBooleanTable = { "Supports power control", "No support for power control" }; |
#pragma mark Flag Tables |
// Flag results from various selectors. |
static FlagElement gPCXFlags[] = { |
{ 0x01, "Supports PC Exchange calls", "No support for PC Exchange" }, |
{ 0, nil, nil} |
}; |
static FlagElement gEjectFlags[] = { |
{ kRestartDontEject_Mask, "Don't want eject at Restart", "Wants eject at Restart" }, |
{ kShutDownDontEject_Mask, "Don't want eject at Shutdown", "Wants eject at Shutdown" }, |
{ 0, nil, nil} |
}; |
static FlagElement gVMOptionsFlags[] = { |
{ kAllowVMNoneMask, "VM should never use this drive", "VM may use this drive" }, |
{ kAllowVMReadOnlyMask, "VM may use this drive read-only", "VM may not use this drive for read-only" }, |
{ kAllowVMReadWriteMask, "VM may use this drive read/write", "VM may not use this drive for read/write" }, |
{ 0, nil, nil} |
}; |
static FlagElement gPurgeFlags[] = { |
{ 1 << kbCloseOk, "Close OK", "Close not allowed" }, |
{ 1 << kbRemoveOk, "RemoveDriver OK", "RemoveDriver not allowed" }, |
{ 1 << kbPurgeOk, "DisposePtr OK", "DisposePtr not allowed" }, |
{ 0, nil, nil} |
}; |
#pragma mark gGestaltList |
// The primary list of Driver Gestalt selectors that we understand. |
// This table allows us to map selectors to their textual descriptions, |
// and allows us to print a Driver Gestalt response by dispatching |
// to the appropriate display routines. |
static GestaltElement gGestaltList[] = { |
{kdgVersion, "Version", VersionDisplay, nil }, |
{kdgDeviceType, "Device Type", OSTypeDisplay, gDeviceTypeList }, |
{kdgInterface, "Interface Type", OSTypeDisplay, gInterfaceTypeList }, |
{kdgSync, "Synchronous", BooleanDisplay, &gSyncBooleanTable }, |
{kdgBoot, "Boot", BootDisplay, nil }, |
{kdgWide, "Wide", BooleanDisplay, &gWideBooleanTable }, |
{kdgPurge, "Purge Permission", PurgeDisplay, gPurgeFlags }, |
{kdgSupportsSwitching, "Power Management", BooleanDisplay, &gPowerSwitchBooleanTable }, |
{kdgMin3VPower, "Min 3.3 V Power", PowerDisplay, nil }, |
{kdgMin5VPower, "Min 5 V Power", PowerDisplay, nil }, |
{kdgMax3VPower, "Max 3.3 V Power", PowerDisplay, nil }, |
{kdgMax5VPower, "Max 5 V Power", PowerDisplay, nil }, |
{kdgInHighPower, "High Power Mode", BooleanDisplay, &gHighPowerBooleanTable }, |
{kdgSupportsPowerCtl, "Power API Support", BooleanDisplay, &gSupportsPowerControlBooleanTable }, |
{kdgAPI, "PC Exchange API Support", Flags16Display, gPCXFlags }, |
{kdgEject, "Shutdown Eject Options", Flags32Display, gEjectFlags }, |
{kdgFlush, "Flush Options", FlushDisplay, nil }, |
{kdgVMOptions, "VM Options", Flags32Display, gVMOptionsFlags }, |
{kdgMediaInfo, "Media Information", MediaInfoDisplay, nil}, |
{0, nil, nil, nil } |
}; |
///////////////////////////////////////////////////////////////// |
#pragma mark ----- User Interface Code ----- |
static void PrintListOfDrives(void) |
// Prints a nicely formatted list of the drives |
// available on this machine by walking the drive |
// queue. |
{ |
DrvQElPtr thisDrv; |
printf("Drive List\n"); |
printf(" 0) <<<all drives>>>\n"); |
thisDrv = (DrvQElPtr) GetDrvQHdr()->qHead; |
while (thisDrv != nil) { |
printf(" %d) with driver %d Ò%#sÓ\n", thisDrv->dQDrive, thisDrv->dQRefNum, RefNumToName(thisDrv->dQRefNum)); |
thisDrv = (DrvQElPtr) thisDrv->qLink; |
} |
} |
static void PrintListOfSelectors(void) |
// Prints a nicely formatted list of Driver Gestalt |
// selectors that we know about by walking our |
// gGestaltList table. |
{ |
ItemCount thisElement; |
printf("Selector List\n"); |
thisElement = 0; |
while ( gGestaltList[thisElement].selector != 0 ) { |
printf(" '%s' Ò%sÓ\n", |
OSTypeToString(gGestaltList[thisElement].selector), |
gGestaltList[thisElement].name |
); |
thisElement += 1; |
} |
} |
static SInt16 GetDriveNumber(void) |
// Asks the user to enter a drive number, returning |
// a negative value on error, a positive value for a specific |
// drive number, and 0 if the user wants to query all drives. |
{ |
SInt16 result; |
char driveStr[256]; |
PrintListOfDrives(); |
printf("Enter a drive number:\n"); |
gets(driveStr); |
if (driveStr[0] == 0) { |
result = -1; |
} else { |
result = atoi(driveStr); |
} |
return result; |
} |
typedef void (*ForEachDriveProc)(UInt32 refcon, SInt16 drive); |
static void ForEachDriveDo(SInt16 drive, ForEachDriveProc proc, UInt32 refcon) |
// This routine provides support for the users |
// desire to issue a Driver Gestalt query on all drives, |
// as specified by typing "0" in response to GetDriveNumber. |
// That drive number is passed in as the drive parameter |
// to this routine. If it's non-zero, this routine calls |
// the supplied proc with that drive as a parameter. If drive |
// is 0, this routine walks the drive queue, repeatedly calling |
// proc, once for each drive. |
{ |
DrvQElPtr thisDrv; |
if (drive != 0) { |
proc(refcon, drive); |
} else { |
thisDrv = (DrvQElPtr) GetDrvQHdr()->qHead; |
while (thisDrv != nil) { |
proc(refcon, thisDrv->dQDrive); |
printf("\n"); |
thisDrv = (DrvQElPtr) thisDrv->qLink; |
} |
} |
} |
static void SingleQuery(SInt16 drive, GestaltElement *element) |
// Perform a single Driver Gestalt query on a single |
// drive. element is typically an entry from gGestaltList, |
// which specifies which selector to query and how to print |
// the result. |
{ |
OSErr err; |
DriverGestaltParam pb; |
// Set up the parameter block. |
pb.ioVRefNum = drive; |
pb.ioCRefNum = MapDriveToRefNum(drive); |
pb.csCode = kDriverGestaltCode; |
pb.driverGestaltSelector = element->selector; |
// Print out the query we're about to do. |
printf("'%s' (%s) on drive %d with driver %d Ò%#sÓ\n", |
OSTypeToString(element->selector), |
element->name, |
drive, |
pb.ioCRefNum, |
RefNumToName(pb.ioCRefNum) |
); |
// Check that the driver support Driver Gestalt. If it doesn't, |
// don't send the driver the query otherwise we might accidentally |
// trigger some action we didn't expect. |
if ( DriveSupportsDriverGestalt(drive) ) { |
// The drive support Driver Gestalt. Let's do the query |
// and print out the result. |
err = PBStatusSync((ParmBlkPtr) &pb); |
if (err == noErr) { |
QAssert(element->responseDisplayRoutine != nil); |
element->responseDisplayRoutine(&pb, element->responseDisplayArg); |
} else { |
printf(" Failed with error %d.\n", err); |
} |
} else { |
printf(" Driver %d does not support Driver Gestalt.\n", pb.ioCRefNum); |
} |
} |
static void OneQueryOnOneDrive(OSType selector, SInt16 drive) |
// This routine issues one specific Drive Gestalt query, |
// specified by selector, on one specific drive. The basic |
// operation is to search the gGestaltList array for the |
// selector. If we find it, we can pass the GestaltElement |
// to SingleQuery, which uses it to format the response. |
// If we can't find the query, we cook up our own local |
// GestaltElement (which indicates that the response should |
// be displayed by the DefaultDisplay routine) and use |
// that instead. |
{ |
ItemCount thisElement; |
Boolean found; |
GestaltElement localElement; |
// Search gGestaltList for selector. |
thisElement = 0; |
found = false; |
while ( gGestaltList[thisElement].selector != 0 && ! found ) { |
found = (gGestaltList[thisElement].selector == selector); |
if ( ! found ) { |
thisElement += 1; |
} |
} |
// If we found it, use it to issue the query, otherwise |
// build our own local GestaltElement and issue the query |
// with that. |
if (found) { |
SingleQuery(drive, &gGestaltList[thisElement]); |
} else { |
localElement.selector = selector; |
localElement.name = "Unknown"; |
localElement.responseDisplayRoutine = DefaultDisplay; |
localElement.responseDisplayArg = nil; |
SingleQuery(drive, &localElement); |
} |
} |
static void AllQueriesOnOneDrive(UInt32 refcon, SInt16 drive) |
// This routine queries all known Driver Gestalt selectors |
// on a specific drive. The refcon parameter is unused |
// but it's required because this routine is a callback |
// ForEachDriveDo. |
{ |
#pragma unused(refcon) |
UInt32 thisElement; |
DriverRefNum refNum; |
if ( DriveSupportsDriverGestalt(drive) ) { |
// Walk our global list of known Driver Gestalt selectors |
// (gGestaltList) and call SingleQuery on each one. |
thisElement = 0; |
while ( gGestaltList[thisElement].selector != 0 ) { |
SingleQuery(drive, &gGestaltList[thisElement]); |
thisElement += 1; |
} |
} else { |
// The driver does not support Driver Gestalt. Stop now before |
// generating a huge cascade of "Driver does not support Driver Gestalt" |
// messages. |
refNum = MapDriveToRefNum(drive); |
printf("Drive %d with driver %d Ò%#sÓ does not support Driver Gestalt.\n", |
drive, |
refNum, |
RefNumToName(refNum) |
); |
} |
} |
static void DoOneQuery(void) |
// This is a primary user interface entry point. Ask |
// the user for a drive and selector and then issue |
// the query. |
{ |
SInt16 drive; |
char selectorStr[256]; |
OSType selector; |
drive = GetDriveNumber(); |
if (drive >= 0) { |
do { |
printf("Enter a selector (Ò?Ó for a list):\n"); |
gets(selectorStr); |
if ( strcmp(selectorStr, "?") == 0 ) { |
PrintListOfSelectors(); |
} |
} while ( strcmp(selectorStr, "?") == 0 ); |
if (selectorStr[0] != 0) { |
selector = *((OSType *) &selectorStr[0]); |
ForEachDriveDo(drive, OneQueryOnOneDrive, selector); |
} |
} |
} |
static void DoAllQueries(void) |
// This is a primary user interface entry point. |
// Ask the user for a drive and then query all |
// known Driver Gestalt selectors on that drive. |
{ |
SInt16 drive; |
char selectorStr[256]; |
OSType selector; |
drive = GetDriveNumber(); |
if (drive >= 0) { |
selector = *((OSType *) &selectorStr[0]); |
ForEachDriveDo(drive, AllQueriesOnOneDrive, 0); |
} |
} |
static void PrintHelp(void) |
// This is a primary user interface entry point. |
// Print the list of supported commands. |
{ |
printf("g) Issue a Driver Gestalt query\n"); |
printf("G) Query all known Driver Gestalt selectors\n"); |
printf("?) Help\n"); |
printf("q) Quit\n"); |
} |
void main(void) |
// The main entry point. A trivial console application |
// that waits for a command to be typed and then performs |
// the command. |
{ |
Boolean quitNow; |
char command[256]; |
printf("Hello Cruel World!\n"); |
printf("\n"); |
printf("Driver Gestalt Explorer\n"); |
printf("-- A simple command line program for exploring\n"); |
printf("-- the Drive Gestalt values returned by block\n"); |
printf("-- device drivers\n"); |
printf("\n"); |
PrintHelp(); |
quitNow = false; |
do { |
printf("\n"); |
printf("Enter a command:\n"); |
gets(command); |
switch (command[0]) { |
case 'g': |
DoOneQuery(); |
break; |
case 'G': |
DoAllQueries(); |
break; |
case '?': |
PrintHelp(); |
break; |
case 'q': |
quitNow = true; |
break; |
default: |
printf("Huh?\n"); |
break; |
} |
} while ( ! quitNow ); |
printf("Done. Press command-Q to Quit.\n"); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14