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.
 
 
 
 
 
 

729 lines
17 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
pcmcmd.c
Abstract:
This program converses with the PCMCIA support driver to display
tuple and other information.
Author:
Bob Rinne
Environment:
User process.
Notes:
Revision History:
Ravisankar Pudipeddi (ravisp) June 27 1997
- command line options & support for multiple controllers
Neil Sandlin (neilsa) Sept 20, 1998
- more commands
Neil Sandlin (neilsa) Apr 15, 2002
- rewrote it to use setupapi
--*/
#include <pch.h>
BOOL
ProcessCommands(
HDEVINFO hDevInfo,
PHOST_INFO HostInfo
);
BOOL
EnumerateHostControllers(
HDEVINFO hInfoList
);
VOID
DumpSocketInfo(
PHOST_INFO HostInfo
);
VOID
HideDevice(
PHOST_INFO HostInfo
);
VOID
RevealDevice(
PHOST_INFO HostInfo
);
VOID
PrintHelp(
VOID
);
PHOST_INFO hostInfoList = NULL;
PHOST_INFO hostInfoListTail = NULL;
ULONG Commands = 0;
PUCHAR specifiedInstanceID = NULL;
LONG specifiedDeviceNumber = -1;
LONG specifiedSlotNumber = -1;
#define CMD_DUMP_TUPLES 0x00000001
#define CMD_DUMP_CONFIGURATION 0x00000002
#define CMD_DUMP_REGISTERS 0x00000004
#define CMD_DUMP_SOCKET_INFO 0x00000008
#define CMD_DUMP_IRQ_SCAN_INFO 0x00000010
#define CMD_HIDE_DEVICE 0x00000020
#define CMD_REVEAL_DEVICE 0x00000040
//
// Procedures
//
int __cdecl
main(
int argc,
char *argv[]
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
ULONG deviceNumber = 0;
ULONG slotNumber = 0;
NTSTATUS status;
CHAR c;
extern PUCHAR optarg;
PHOST_INFO hostInfo;
HDEVINFO hDevInfo;
BOOL bRet;
ULONG requiredSize = 0;
GUID classGuid;
//
// Scan command line
//
while ((c = getopt(argc, argv, "d:s:p:hrti?")) != EOF) {
switch (c) {
case 'd':
specifiedDeviceNumber = atoi(optarg);
break;
case 's':
specifiedSlotNumber = atoi(optarg);
break;
case 'p':
specifiedInstanceID = optarg;
break;
case 't':
Commands |= CMD_DUMP_TUPLES;
break;
case 'i':
Commands |= CMD_DUMP_IRQ_SCAN_INFO;
break;
case 'h':
Commands |= CMD_HIDE_DEVICE;
break;
case 'r':
Commands |= CMD_REVEAL_DEVICE;
break;
default:
PrintHelp();
return(1);
}
}
//
// Dump IRQscan info from registry, if requested
//
if (Commands & CMD_DUMP_IRQ_SCAN_INFO) {
DumpIrqScanInfo();
//
// if there were no other commands, then exit
//
if (!(Commands & ~CMD_DUMP_IRQ_SCAN_INFO)) {
return(0);
}
Commands &= ~CMD_DUMP_IRQ_SCAN_INFO;
}
//
// Build a list of devices from the class GUID for pcmcia
//
bRet = SetupDiClassGuidsFromName("PCMCIA", &classGuid, 1, &requiredSize);
if (!bRet || (requiredSize == 0)) {
printf("error: couldn't find class GUID for PCMCIA\n");
return;
}
hDevInfo = SetupDiGetClassDevs(&classGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
if (hDevInfo == INVALID_HANDLE_VALUE) {
printf("error(%d): couldn't create info list\n", GetLastError());
return;
}
try{
BOOL bProcessedAtLeastOne = FALSE;
//
// Build the list of pcmcia controllers
//
if (!EnumerateHostControllers(hDevInfo)) {
leave;
}
//
// Loop through the list of controllers
//
for (hostInfo = hostInfoList; hostInfo != NULL; hostInfo = hostInfo->Next) {
if (ProcessCommands(hDevInfo, hostInfo)) {
bProcessedAtLeastOne = TRUE;
}
}
if (!bProcessedAtLeastOne) {
printf("controller not found\n");
}
} finally {
SetupDiDestroyDeviceInfoList(hDevInfo);
}
return (0);
}
BOOL
GetDeviceRegistryDword(
HDEVINFO hDevInfo,
PSP_DEVINFO_DATA devInfoData,
PUCHAR ValueName,
ULONG KeyType,
PULONG pData
)
{
HKEY hDeviceKey;
LONG status;
ULONG sizeOfUlong = sizeof(ULONG);
hDeviceKey = SetupDiOpenDevRegKey(hDevInfo,
devInfoData,
DICS_FLAG_GLOBAL,
0,
KeyType,
KEY_READ);
if (hDeviceKey == INVALID_HANDLE_VALUE) {
printf("error: unable to open DevRegKey\n");
return FALSE;
}
status = RegQueryValueEx(hDeviceKey,
ValueName,
NULL,
NULL,
(PUCHAR) pData,
&sizeOfUlong);
RegCloseKey(hDeviceKey);
return (status == ERROR_SUCCESS);
}
BOOL
EnumerateHostControllers(
HDEVINFO hDevInfo
)
/*++
Routine Description:
Build a linked list of HOST_INFO data structures, one for each PCMCIA controller
Arguments:
Return Value:
--*/
{
BOOL bRet;
ULONG requiredSize = 0;
GUID classGuid;
ULONG index = 0;
SP_DEVINFO_DATA devInfoData;
PHOST_INFO hostInfo;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
//
// Loop through all instances of pcmcia host controllers
//
while(1) {
bRet = SetupDiEnumDeviceInfo(hDevInfo, index, &devInfoData);
if (!bRet) {
if (index == 0) {
printf("error(%d): no pcmcia host controllers found\n", GetLastError());
return FALSE;
}
break;
}
//
// Found a controller. Create a host info structure and chain it to the global list
//
hostInfo = malloc(sizeof(HOST_INFO));
if (hostInfo == NULL) {
printf("malloc error - out of memory\n");
return FALSE;
}
memset(hostInfo, 0, sizeof(HOST_INFO));
hostInfo->DeviceIndex = index;
if (hostInfoListTail == NULL) {
hostInfoListTail = hostInfo;
hostInfoList = hostInfo;
} else {
hostInfoListTail->Next = hostInfo;
}
//
// get the device instance string for our host_info structure
//
requiredSize = 0;
bRet = SetupDiGetDeviceInstanceId(hDevInfo,
&devInfoData,
NULL,
0,
&requiredSize);
if (!requiredSize) {
printf("error: found DeviceInfo with no instance ID\n");
return FALSE;
}
hostInfo->InstanceID = malloc(requiredSize);
if (hostInfo->InstanceID == NULL) {
printf("malloc error - out of memory\n");
return FALSE;
}
bRet = SetupDiGetDeviceInstanceId(hDevInfo,
&devInfoData,
hostInfo->InstanceID,
requiredSize,
&requiredSize);
if (!bRet) {
printf("error: couldn't retrieve instance ID\n");
return FALSE;
}
//
// Get the "CompatibleControllerType", so we know how many sockets there are
//
bRet = GetDeviceRegistryDword(hDevInfo,
&devInfoData,
"CompatibleControllerType",
DIREG_DRV,
&hostInfo->ControllerType);
if (!bRet) {
hostInfo->ControllerType = 0xFFFFFFFF;
}
index++;
}
return TRUE;
}
BOOL
ProcessCommands(
HDEVINFO hDevInfo,
PHOST_INFO hostInfo
)
{
NTSTATUS status;
ULONG slotNumber;
ULONG numberOfSlots = 1;
if (specifiedInstanceID && strcmp(specifiedInstanceID, hostInfo->InstanceID)) {
return FALSE;
}
if ((specifiedDeviceNumber != -1) && (specifiedDeviceNumber != hostInfo->DeviceIndex)) {
return FALSE;
}
// NEED TO IMPLEMENT: there are more types of controllers with 2 slots
if (hostInfo->ControllerType == 0) {
numberOfSlots = 2;
}
printf("\n**---- PC-CARD host controller %d ----**\n\n", hostInfo->DeviceIndex);
printf(" %s\n", hostInfo->InstanceID);
for (slotNumber = 0; slotNumber < numberOfSlots; slotNumber++) {
if ((specifiedSlotNumber != -1) && (specifiedSlotNumber != slotNumber)) {
continue;
}
hostInfo->SocketNumber = slotNumber;
if (Commands & CMD_DUMP_TUPLES) {
DumpCIS(hostInfo);
}
if (Commands & CMD_HIDE_DEVICE) {
HideDevice(hostInfo);
}
if (Commands & CMD_REVEAL_DEVICE) {
RevealDevice(hostInfo);
}
if (!Commands || (Commands & CMD_DUMP_SOCKET_INFO)) {
DumpSocketInfo(hostInfo);
}
}
return TRUE;
}
HANDLE
GetHandleForIoctl(
IN PHOST_INFO hostInfo
)
/*++
Routine Description:
This routine will open the device.
Arguments:
DeviceName - ASCI string of device path to open.
HandlePtr - A pointer to a location for the handle returned on a
successful open.
Return Value:
NTSTATUS
--*/
{
OBJECT_ATTRIBUTES objectAttributes;
STRING NtFtName;
IO_STATUS_BLOCK status_block;
UNICODE_STRING unicodeDeviceName;
NTSTATUS status;
UCHAR deviceName[128];
HANDLE handle;
sprintf(deviceName, "%s%d", PCMCIA_DEVICE_NAME, hostInfo->DeviceIndex);
RtlInitString(&NtFtName, deviceName);
(VOID)RtlAnsiStringToUnicodeString(&unicodeDeviceName,
&NtFtName,
TRUE);
memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes(&objectAttributes,
&unicodeDeviceName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtOpenFile(&handle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objectAttributes,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT );
RtlFreeUnicodeString(&unicodeDeviceName);
if (!NT_SUCCESS(status)) {
printf("error: Unable to OpenFile on %s\n", deviceName);
handle = INVALID_HANDLE_VALUE;
}
return handle;
} // OpenDevice
PUCHAR Controllers[] = {
"PcmciaIntelCompatible",
"PcmciaCardBusCompatible",
"PcmciaElcController",
"PcmciaDatabook",
"PcmciaPciPcmciaBridge",
"PcmciaCirrusLogic",
"PcmciaTI",
"PcmciaTopic",
"PcmciaRicoh",
"PcmciaDatabookCB",
"PcmciaOpti",
"PcmciaTrid",
"PcmciaO2Micro",
"PcmciaNEC",
"PcmciaNEC_98",
};
VOID
DumpSocketInfo(
IN PHOST_INFO hostInfo
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK statusBlock;
PCMCIA_SOCKET_INFORMATION commandBlock;
ULONG ctlClass, ctlModel, ctlRev;
HANDLE handle;
handle = GetHandleForIoctl(hostInfo);
if (handle == INVALID_HANDLE_VALUE) {
return;
}
memset(&commandBlock, 0, sizeof(commandBlock));
commandBlock.Socket = (USHORT) hostInfo->SocketNumber;
status = NtDeviceIoControlFile(handle,
NULL,
NULL,
NULL,
&statusBlock,
IOCTL_SOCKET_INFORMATION,
&commandBlock,
sizeof(commandBlock),
&commandBlock,
sizeof(commandBlock));
if (!NT_SUCCESS(status)) {
printf(" error: %08x on DumpSocketInfo ioctl\n", status);
NtClose(handle);
return;
}
printf(" Basic Information for Socket %d:\n", hostInfo->SocketNumber);
printf(" Manufacturer = %s\n", commandBlock.Manufacturer);
printf(" Identifier = %s\n", commandBlock.Identifier);
printf(" TupleCRC = %x\n", commandBlock.TupleCrc);
printf(" DriverName = %s\n", commandBlock.DriverName);
printf(" Function ID = %d\n", commandBlock.DeviceFunctionId);
ctlClass = PcmciaClassFromControllerType(commandBlock.ControllerType);
if (ctlClass >= sizeof(Controllers)/sizeof(PUCHAR)) {
printf(" ControllerType = Unknown (%x)\n", commandBlock.ControllerType);
} else {
printf(" ControllerType(%x) = %s", commandBlock.ControllerType,
Controllers[ctlClass]);
ctlModel = PcmciaModelFromControllerType(commandBlock.ControllerType);
ctlRev = PcmciaRevisionFromControllerType(commandBlock.ControllerType);
if (ctlModel) {
printf("%d", ctlModel);
}
if (ctlRev) {
printf(", rev(%d)", ctlRev);
}
printf("\n");
}
if (commandBlock.CardInSocket) {
printf(" Card In Socket\n");
}
if (commandBlock.CardEnabled) {
printf(" Card Enabled\n");
}
NtClose(handle);
}
VOID
HideDevice(
IN PHOST_INFO hostInfo
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK statusBlock;
PCMCIA_SOCKET_REQUEST commandBlock;
HANDLE handle;
handle = GetHandleForIoctl(hostInfo);
if (handle == INVALID_HANDLE_VALUE) {
return;
}
memset(&commandBlock, 0, sizeof(commandBlock));
commandBlock.Socket = (USHORT) hostInfo->SocketNumber;
status = NtDeviceIoControlFile(handle, NULL, NULL, NULL,
&statusBlock,
IOCTL_PCMCIA_HIDE_DEVICE,
&commandBlock, sizeof(commandBlock),
NULL, 0);
if (NT_SUCCESS(status)) {
printf("OK\n");
} else {
printf("Failed - %x\n", status);
}
NtClose(handle);
}
VOID
RevealDevice(
IN PHOST_INFO hostInfo
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK statusBlock;
PCMCIA_SOCKET_REQUEST commandBlock;
HANDLE handle;
handle = GetHandleForIoctl(hostInfo);
if (handle == INVALID_HANDLE_VALUE) {
return;
}
memset(&commandBlock, 0, sizeof(commandBlock));
commandBlock.Socket = (USHORT) hostInfo->SocketNumber;
status = NtDeviceIoControlFile(handle, NULL, NULL, NULL,
&statusBlock,
IOCTL_PCMCIA_REVEAL_DEVICE,
&commandBlock, sizeof(commandBlock),
NULL, 0);
if (NT_SUCCESS(status)) {
printf("OK\n");
} else {
printf("Failed - %x\n", status);
}
NtClose(handle);
}
VOID
PrintHelp(
VOID
)
{
printf("pcmcmd.exe - Command line interface to the PCCARD (pcmcia, cardbus) bus driver\n");
printf("\n");
printf("Usage: PCMCMD [-d <arg>] [-s <arg>] [-p <arg>] [-t] [-i]\n");
printf("\n");
printf(" -p \"PnP instance ID\" specifies PCMCIA host by PnP instance ID\n");
printf(" -d ControllerNumber specifies PCMCIA host by number (zero-based)\n");
printf(" -s SocketNumber specifies PCMCIA socket number (zero-based)\n");
printf(" Note: cardbus hosts have only one socket\n");
printf(" -t Dumps the CIS tuples of the PC-Card\n");
printf(" -i Dumps irq detection info\n");
printf("\n");
}