windows-nt/Source/XPSP1/NT/printscan/print/drivers/kernelmode/usbprint/deviceid.c
2020-09-26 16:20:57 +08:00

423 lines
11 KiB
C

#define DRIVER
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "deviceid.h"
#include <usb.h>
#include <usbdrivr.h>
#include "usbdlib.h"
#include "usbprint.h"
VOID StringSubst
(
PUCHAR lpS,
UCHAR chTargetChar,
UCHAR chReplacementChar,
USHORT cbS
)
{
USHORT iCnt = 0;
while ((lpS != '\0') && (iCnt++ < cbS))
if (*lpS == chTargetChar)
*lpS++ = chReplacementChar;
else
++lpS;
}
VOID
FixupDeviceId(
IN OUT PUCHAR DeviceId
)
/*++
Routine Description:
This routine parses the NULL terminated string and replaces any invalid
characters with an underscore character.
Invalid characters are:
c <= 0x20 (' ')
c > 0x7F
c == 0x2C (',')
Arguments:
DeviceId - specifies a device id string (or part of one), must be
null-terminated.
Return Value:
None.
--*/
{
PUCHAR p;
for( p = DeviceId; *p; ++p ) {
if( (*p <= ' ') || (*p > (UCHAR)0x7F) || (*p == ',') ) {
*p = '_';
}
}
}
NTSTATUS
ParPnpGetId
(
IN PUCHAR DeviceIdString,
IN ULONG Type,
OUT PUCHAR resultString
)
/*
Description:
Creates Id's from the device id retrieved from the printer
Parameters:
DeviceId - String with raw device id
Type - What of id we want as a result
Id - requested id
Return Value:
NTSTATUS
*/
{
NTSTATUS status;
USHORT checkSum=0; // A 16 bit check sum
// The following are used to generate sub-strings from the Device ID string
// to get the DevNode name, and to update the registry
PUCHAR MFG = NULL; // Manufature name
PUCHAR MDL = NULL; // Model name
PUCHAR CLS = NULL; // Class name
PUCHAR AID = NULL; // Hardare ID
PUCHAR CID = NULL; // Compatible IDs
PUCHAR DES = NULL; // Device Description
USBPRINT_KdPrint2 (("'USBPRINT.SYS: Enter ParPnpGetId\n"));
status = STATUS_SUCCESS;
switch(Type) {
case BusQueryDeviceID:
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Inside case BusQueryID, DeviceIdString==%s\n",DeviceIdString));
// Extract the usefull fields from the DeviceID string. We want
// MANUFACTURE (MFG):
// MODEL (MDL):
// AUTOMATIC ID (AID):
// COMPATIBLE ID (CID):
// DESCRIPTION (DES):
// CLASS (CLS):
ParPnpFindDeviceIdKeys(&MFG, &MDL, &CLS, &DES, &AID, &CID, DeviceIdString);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: After FindDeviceIdKeys\n"));
// Check to make sure we got MFG and MDL as absolute minimum fields. If not
// we cannot continue.
if (!MFG || !MDL)
{
status = STATUS_NOT_FOUND;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: STATUS_NOT_FOUND\n"));
goto ParPnpGetId_Cleanup;
}
//
// Concatenate the provided MFG and MDL P1284 fields
// Checksum the entire MFG+MDL string
//
sprintf(resultString, "%s%s\0",MFG,MDL);
break;
case BusQueryHardwareIDs:
GetCheckSum(DeviceIdString, (USHORT)strlen(DeviceIdString), &checkSum);
sprintf(resultString,"%.20s%04X",DeviceIdString,checkSum);
break;
case BusQueryCompatibleIDs:
//
// return only 1 id
//
GetCheckSum(DeviceIdString, (USHORT)strlen(DeviceIdString), &checkSum);
sprintf(resultString,"%.20s%04X",DeviceIdString,checkSum);
break;
}
if (Type!=BusQueryDeviceID) {
//
// Convert and spaces in the Hardware ID to underscores
//
StringSubst ((PUCHAR) resultString, ' ', '_', (USHORT)strlen(resultString));
}
ParPnpGetId_Cleanup:
return(status);
}
VOID
ParPnpFindDeviceIdKeys
(
PUCHAR *lppMFG,
PUCHAR *lppMDL,
PUCHAR *lppCLS,
PUCHAR *lppDES,
PUCHAR *lppAID,
PUCHAR *lppCID,
PUCHAR lpDeviceID
)
/*
Description:
This function will parse a P1284 Device ID string looking for keys
of interest to the LPT enumerator. Got it from win95 lptenum
Parameters:
lppMFG Pointer to MFG string pointer
lppMDL Pointer to MDL string pointer
lppMDL Pointer to CLS string pointer
lppDES Pointer to DES string pointer
lppCIC Pointer to CID string pointer
lppAID Pointer to AID string pointer
lpDeviceID Pointer to the Device ID string
Return Value:
no return VALUE.
If found the lpp parameters are set to the approprate portions
of the DeviceID string, and they are NULL terminated.
The actual DeviceID string is used, and the lpp Parameters just
reference sections, with appropriate null thrown in.
*/
{
PUCHAR lpKey = lpDeviceID; // Pointer to the Key to look at
PUCHAR lpValue; // Pointer to the Key's value
USHORT wKeyLength; // Length for the Key (for stringcmps)
// While there are still keys to look at.
while (lpKey!=NULL)
{
while (*lpKey == ' ')
++lpKey;
// Is there a terminating COLON character for the current key?
if (!(lpValue = StringChr(lpKey, ':')) )
{
// N: OOPS, somthing wrong with the Device ID
return;
}
// The actual start of the Key value is one past the COLON
++lpValue;
//
// Compute the Key length for Comparison, including the COLON
// which will serve as a terminator
//
wKeyLength = (USHORT)(lpValue - lpKey);
//
// Compare the Key to the Know quantities. To speed up the comparison
// a Check is made on the first character first, to reduce the number
// of strings to compare against.
// If a match is found, the appropriate lpp parameter is set to the
// key's value, and the terminating SEMICOLON is converted to a NULL
// In all cases lpKey is advanced to the next key if there is one.
//
switch (*lpKey)
{
case 'M':
// Look for MANUFACTURE (MFG) or MODEL (MDL)
if ((RtlCompareMemory(lpKey, "MANUFACTURER", wKeyLength)>5) ||
(RtlCompareMemory(lpKey, "MFG", wKeyLength)==3) )
{
*lppMFG = lpValue;
if ((lpKey = StringChr(lpValue, ';'))!=NULL)
{
*lpKey = '\0';
++lpKey;
}
}
else if ((RtlCompareMemory(lpKey, "MODEL", wKeyLength)==5) ||
(RtlCompareMemory(lpKey, "MDL", wKeyLength)==3) )
{
*lppMDL = lpValue;
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
else
{
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
break;
case 'C':
// Look for CLASS (CLS)
if ((RtlCompareMemory(lpKey, "CLASS", wKeyLength)==5) ||
(RtlCompareMemory(lpKey, "CLS", wKeyLength)==3) )
{
*lppCLS = lpValue;
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
else if ((RtlCompareMemory(lpKey, "COMPATIBLEID", wKeyLength)>5) ||
(RtlCompareMemory(lpKey, "CID", wKeyLength)==3) )
{
*lppCID = lpValue;
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
else
{
if ((lpKey = StringChr(lpValue,';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
break;
case 'D':
// Look for DESCRIPTION (DES)
if (RtlCompareMemory(lpKey, "DESCRIPTION", wKeyLength) ||
RtlCompareMemory(lpKey, "DES", wKeyLength) )
{
*lppDES = lpValue;
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
else
{
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
break;
case 'A':
// Look for AUTOMATIC ID (AID)
if (RtlCompareMemory(lpKey, "AUTOMATICID", wKeyLength) ||
RtlCompareMemory(lpKey, "AID", wKeyLength) )
{
*lppAID = lpValue;
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
else
{
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
}
break;
default:
// The key is uninteresting. Go to the next Key
if ((lpKey = StringChr(lpValue, ';'))!=0)
{
*lpKey = '\0';
++lpKey;
}
break;
}
}
}
VOID
GetCheckSum(
PUCHAR Block,
USHORT Len,
PUSHORT CheckSum
)
{
USHORT i;
USHORT crc = 0;
unsigned short crc16a[] = {
0000000, 0140301, 0140601, 0000500,
0141401, 0001700, 0001200, 0141101,
0143001, 0003300, 0003600, 0143501,
0002400, 0142701, 0142201, 0002100,
};
unsigned short crc16b[] = {
0000000, 0146001, 0154001, 0012000,
0170001, 0036000, 0024000, 0162001,
0120001, 0066000, 0074000, 0132001,
0050000, 0116001, 0104001, 0043000,
};
//
// Calculate CRC using tables.
//
UCHAR tmp;
for ( i=0; i<Len; i++) {
tmp = Block[i] ^ (UCHAR)crc;
crc = (crc >> 8) ^ crc16a[tmp & 0x0f] ^ crc16b[tmp >> 4];
}
*CheckSum = crc;
}
PUCHAR
StringChr(PCHAR string, CHAR c)
{
ULONG i=0;
if (!string)
return(NULL);
while (*string) {
if (*string==c)
return(string);
string++;
i++;
}
return(NULL);
}