#define DRIVER #include "wdm.h" #include "stdarg.h" #include "stdio.h" #include "deviceid.h" #include #include #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> 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); }