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.

422 lines
12 KiB

  1. #define DRIVER
  2. #include "wdm.h"
  3. #include "stdarg.h"
  4. #include "stdio.h"
  5. #include "deviceid.h"
  6. #include <usb.h>
  7. #include <usbdrivr.h>
  8. #include "usbdlib.h"
  9. #include "usbprint.h"
  10. VOID StringSubst
  11. (
  12. PUCHAR lpS,
  13. UCHAR chTargetChar,
  14. UCHAR chReplacementChar,
  15. USHORT cbS
  16. )
  17. {
  18. USHORT iCnt = 0;
  19. while ((lpS != '\0') && (iCnt++ < cbS))
  20. if (*lpS == chTargetChar)
  21. *lpS++ = chReplacementChar;
  22. else
  23. ++lpS;
  24. }
  25. VOID
  26. FixupDeviceId(
  27. IN OUT PUCHAR DeviceId
  28. )
  29. /*++
  30. Routine Description:
  31. This routine parses the NULL terminated string and replaces any invalid
  32. characters with an underscore character.
  33. Invalid characters are:
  34. c <= 0x20 (' ')
  35. c > 0x7F
  36. c == 0x2C (',')
  37. Arguments:
  38. DeviceId - specifies a device id string (or part of one), must be
  39. null-terminated.
  40. Return Value:
  41. None.
  42. --*/
  43. {
  44. PUCHAR p;
  45. for( p = DeviceId; *p; ++p ) {
  46. if( (*p <= ' ') || (*p > (UCHAR)0x7F) || (*p == ',') ) {
  47. *p = '_';
  48. }
  49. }
  50. }
  51. NTSTATUS
  52. ParPnpGetId
  53. (
  54. IN PUCHAR DeviceIdString,
  55. IN ULONG Type,
  56. OUT PUCHAR resultString
  57. )
  58. /*
  59. Description:
  60. Creates Id's from the device id retrieved from the printer
  61. Parameters:
  62. DeviceId - String with raw device id
  63. Type - What of id we want as a result
  64. Id - requested id
  65. Return Value:
  66. NTSTATUS
  67. */
  68. {
  69. NTSTATUS status;
  70. USHORT checkSum=0; // A 16 bit check sum
  71. // The following are used to generate sub-strings from the Device ID string
  72. // to get the DevNode name, and to update the registry
  73. PUCHAR MFG = NULL; // Manufature name
  74. PUCHAR MDL = NULL; // Model name
  75. PUCHAR CLS = NULL; // Class name
  76. PUCHAR AID = NULL; // Hardare ID
  77. PUCHAR CID = NULL; // Compatible IDs
  78. PUCHAR DES = NULL; // Device Description
  79. USBPRINT_KdPrint2 (("'USBPRINT.SYS: Enter ParPnpGetId\n"));
  80. status = STATUS_SUCCESS;
  81. switch(Type) {
  82. case BusQueryDeviceID:
  83. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Inside case BusQueryID, DeviceIdString==%s\n",DeviceIdString));
  84. // Extract the usefull fields from the DeviceID string. We want
  85. // MANUFACTURE (MFG):
  86. // MODEL (MDL):
  87. // AUTOMATIC ID (AID):
  88. // COMPATIBLE ID (CID):
  89. // DESCRIPTION (DES):
  90. // CLASS (CLS):
  91. ParPnpFindDeviceIdKeys(&MFG, &MDL, &CLS, &DES, &AID, &CID, DeviceIdString);
  92. USBPRINT_KdPrint3 (("'USBPRINT.SYS: After FindDeviceIdKeys\n"));
  93. // Check to make sure we got MFG and MDL as absolute minimum fields. If not
  94. // we cannot continue.
  95. if (!MFG || !MDL)
  96. {
  97. status = STATUS_NOT_FOUND;
  98. USBPRINT_KdPrint2 (("'USBPRINT.SYS: STATUS_NOT_FOUND\n"));
  99. goto ParPnpGetId_Cleanup;
  100. }
  101. //
  102. // Concatenate the provided MFG and MDL P1284 fields
  103. // Checksum the entire MFG+MDL string
  104. //
  105. sprintf(resultString, "%s%s\0",MFG,MDL);
  106. break;
  107. case BusQueryHardwareIDs:
  108. GetCheckSum(DeviceIdString, (USHORT)strlen(DeviceIdString), &checkSum);
  109. sprintf(resultString,"%.20s%04X",DeviceIdString,checkSum);
  110. break;
  111. case BusQueryCompatibleIDs:
  112. //
  113. // return only 1 id
  114. //
  115. GetCheckSum(DeviceIdString, (USHORT)strlen(DeviceIdString), &checkSum);
  116. sprintf(resultString,"%.20s%04X",DeviceIdString,checkSum);
  117. break;
  118. }
  119. if (Type!=BusQueryDeviceID) {
  120. //
  121. // Convert and spaces in the Hardware ID to underscores
  122. //
  123. StringSubst ((PUCHAR) resultString, ' ', '_', (USHORT)strlen(resultString));
  124. }
  125. ParPnpGetId_Cleanup:
  126. return(status);
  127. }
  128. VOID
  129. ParPnpFindDeviceIdKeys
  130. (
  131. PUCHAR *lppMFG,
  132. PUCHAR *lppMDL,
  133. PUCHAR *lppCLS,
  134. PUCHAR *lppDES,
  135. PUCHAR *lppAID,
  136. PUCHAR *lppCID,
  137. PUCHAR lpDeviceID
  138. )
  139. /*
  140. Description:
  141. This function will parse a P1284 Device ID string looking for keys
  142. of interest to the LPT enumerator. Got it from win95 lptenum
  143. Parameters:
  144. lppMFG Pointer to MFG string pointer
  145. lppMDL Pointer to MDL string pointer
  146. lppMDL Pointer to CLS string pointer
  147. lppDES Pointer to DES string pointer
  148. lppCIC Pointer to CID string pointer
  149. lppAID Pointer to AID string pointer
  150. lpDeviceID Pointer to the Device ID string
  151. Return Value:
  152. no return VALUE.
  153. If found the lpp parameters are set to the approprate portions
  154. of the DeviceID string, and they are NULL terminated.
  155. The actual DeviceID string is used, and the lpp Parameters just
  156. reference sections, with appropriate null thrown in.
  157. */
  158. {
  159. PUCHAR lpKey = lpDeviceID; // Pointer to the Key to look at
  160. PUCHAR lpValue; // Pointer to the Key's value
  161. USHORT wKeyLength; // Length for the Key (for stringcmps)
  162. // While there are still keys to look at.
  163. while (lpKey!=NULL)
  164. {
  165. while (*lpKey == ' ')
  166. ++lpKey;
  167. // Is there a terminating COLON character for the current key?
  168. if (!(lpValue = StringChr(lpKey, ':')) )
  169. {
  170. // N: OOPS, somthing wrong with the Device ID
  171. return;
  172. }
  173. // The actual start of the Key value is one past the COLON
  174. ++lpValue;
  175. //
  176. // Compute the Key length for Comparison, including the COLON
  177. // which will serve as a terminator
  178. //
  179. wKeyLength = (USHORT)(lpValue - lpKey);
  180. //
  181. // Compare the Key to the Know quantities. To speed up the comparison
  182. // a Check is made on the first character first, to reduce the number
  183. // of strings to compare against.
  184. // If a match is found, the appropriate lpp parameter is set to the
  185. // key's value, and the terminating SEMICOLON is converted to a NULL
  186. // In all cases lpKey is advanced to the next key if there is one.
  187. //
  188. switch (*lpKey)
  189. {
  190. case 'M':
  191. // Look for MANUFACTURE (MFG) or MODEL (MDL)
  192. if ((RtlCompareMemory(lpKey, "MANUFACTURER", wKeyLength)>5) ||
  193. (RtlCompareMemory(lpKey, "MFG", wKeyLength)==3) )
  194. {
  195. *lppMFG = lpValue;
  196. if ((lpKey = StringChr(lpValue, ';'))!=NULL)
  197. {
  198. *lpKey = '\0';
  199. ++lpKey;
  200. }
  201. }
  202. else if ((RtlCompareMemory(lpKey, "MODEL", wKeyLength)==5) ||
  203. (RtlCompareMemory(lpKey, "MDL", wKeyLength)==3) )
  204. {
  205. *lppMDL = lpValue;
  206. if ((lpKey = StringChr(lpValue, ';'))!=0)
  207. {
  208. *lpKey = '\0';
  209. ++lpKey;
  210. }
  211. }
  212. else
  213. {
  214. if ((lpKey = StringChr(lpValue, ';'))!=0)
  215. {
  216. *lpKey = '\0';
  217. ++lpKey;
  218. }
  219. }
  220. break;
  221. case 'C':
  222. // Look for CLASS (CLS)
  223. if ((RtlCompareMemory(lpKey, "CLASS", wKeyLength)==5) ||
  224. (RtlCompareMemory(lpKey, "CLS", wKeyLength)==3) )
  225. {
  226. *lppCLS = lpValue;
  227. if ((lpKey = StringChr(lpValue, ';'))!=0)
  228. {
  229. *lpKey = '\0';
  230. ++lpKey;
  231. }
  232. }
  233. else if ((RtlCompareMemory(lpKey, "COMPATIBLEID", wKeyLength)>5) ||
  234. (RtlCompareMemory(lpKey, "CID", wKeyLength)==3) )
  235. {
  236. *lppCID = lpValue;
  237. if ((lpKey = StringChr(lpValue, ';'))!=0)
  238. {
  239. *lpKey = '\0';
  240. ++lpKey;
  241. }
  242. }
  243. else
  244. {
  245. if ((lpKey = StringChr(lpValue,';'))!=0)
  246. {
  247. *lpKey = '\0';
  248. ++lpKey;
  249. }
  250. }
  251. break;
  252. case 'D':
  253. // Look for DESCRIPTION (DES)
  254. if (RtlCompareMemory(lpKey, "DESCRIPTION", wKeyLength) ||
  255. RtlCompareMemory(lpKey, "DES", wKeyLength) )
  256. {
  257. *lppDES = lpValue;
  258. if ((lpKey = StringChr(lpValue, ';'))!=0)
  259. {
  260. *lpKey = '\0';
  261. ++lpKey;
  262. }
  263. }
  264. else
  265. {
  266. if ((lpKey = StringChr(lpValue, ';'))!=0)
  267. {
  268. *lpKey = '\0';
  269. ++lpKey;
  270. }
  271. }
  272. break;
  273. case 'A':
  274. // Look for AUTOMATIC ID (AID)
  275. if (RtlCompareMemory(lpKey, "AUTOMATICID", wKeyLength) ||
  276. RtlCompareMemory(lpKey, "AID", wKeyLength) )
  277. {
  278. *lppAID = lpValue;
  279. if ((lpKey = StringChr(lpValue, ';'))!=0)
  280. {
  281. *lpKey = '\0';
  282. ++lpKey;
  283. }
  284. }
  285. else
  286. {
  287. if ((lpKey = StringChr(lpValue, ';'))!=0)
  288. {
  289. *lpKey = '\0';
  290. ++lpKey;
  291. }
  292. }
  293. break;
  294. default:
  295. // The key is uninteresting. Go to the next Key
  296. if ((lpKey = StringChr(lpValue, ';'))!=0)
  297. {
  298. *lpKey = '\0';
  299. ++lpKey;
  300. }
  301. break;
  302. }
  303. }
  304. }
  305. VOID
  306. GetCheckSum(
  307. PUCHAR Block,
  308. USHORT Len,
  309. PUSHORT CheckSum
  310. )
  311. {
  312. USHORT i;
  313. USHORT crc = 0;
  314. unsigned short crc16a[] = {
  315. 0000000, 0140301, 0140601, 0000500,
  316. 0141401, 0001700, 0001200, 0141101,
  317. 0143001, 0003300, 0003600, 0143501,
  318. 0002400, 0142701, 0142201, 0002100,
  319. };
  320. unsigned short crc16b[] = {
  321. 0000000, 0146001, 0154001, 0012000,
  322. 0170001, 0036000, 0024000, 0162001,
  323. 0120001, 0066000, 0074000, 0132001,
  324. 0050000, 0116001, 0104001, 0043000,
  325. };
  326. //
  327. // Calculate CRC using tables.
  328. //
  329. UCHAR tmp;
  330. for ( i=0; i<Len; i++) {
  331. tmp = Block[i] ^ (UCHAR)crc;
  332. crc = (crc >> 8) ^ crc16a[tmp & 0x0f] ^ crc16b[tmp >> 4];
  333. }
  334. *CheckSum = crc;
  335. }
  336. PUCHAR
  337. StringChr(PCHAR string, CHAR c)
  338. {
  339. ULONG i=0;
  340. if (!string)
  341. return(NULL);
  342. while (*string) {
  343. if (*string==c)
  344. return(string);
  345. string++;
  346. i++;
  347. }
  348. return(NULL);
  349. }