Source code of Windows XP (NT5)
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.

946 lines
20 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. STRING.C
  5. Abstract:
  6. This module contains the functions used to parse the PNP COM ID
  7. and save it in the appropriate UNICODE STRINGS. The main function
  8. that is called is Serenum_ParseData. All other functions are called
  9. by this main function.
  10. @@BEGIN_DDKSPLIT
  11. Author:
  12. Jay Senior
  13. @@END_DDKSPLIT
  14. Environment:
  15. kernel mode only
  16. Notes:
  17. @@BEGIN_DDKSPLIT
  18. Revision History:
  19. Louis J. Giliberto, Jr. 22-Mar-1998 Cleanup
  20. @@END_DDKSPLIT
  21. --*/
  22. #include "pch.h"
  23. #define MAX_DEVNODE_NAME 256 // Total size of Device ID
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text (PAGE, Serenum_ParseData)
  26. // Called by ParseData:
  27. #pragma alloc_text (PAGE, Serenum_GetDevDesc)
  28. #pragma alloc_text (PAGE, Serenum_GetDevCompId)
  29. #pragma alloc_text (PAGE, Serenum_GetDevClass)
  30. #pragma alloc_text (PAGE, Serenum_GetDevSerialNo)
  31. #pragma alloc_text (PAGE, Serenum_GetDevName)
  32. #pragma alloc_text (PAGE, Serenum_GetDevPnPRev)
  33. #pragma alloc_text (PAGE, Serenum_GetDevOtherID)
  34. #pragma alloc_text (PAGE, Serenum_InitMultiString)
  35. #pragma alloc_text (PAGE, Serenum_SzCopy)
  36. #pragma alloc_text (PAGE, Serenum_StrLen)
  37. // Called by the above functions:
  38. #pragma alloc_text (PAGE, Serenum_FixptToAscii)
  39. #pragma alloc_text (PAGE, Serenum_HToI)
  40. #endif
  41. NTSTATUS
  42. Serenum_ParseData(PFDO_DEVICE_DATA FdoData, PCHAR ReadBuffer, ULONG BufferLen,
  43. PUNICODE_STRING hardwareIDs, PUNICODE_STRING compIDs,
  44. PUNICODE_STRING deviceIDs, PUNICODE_STRING PDeviceDesc,
  45. PUNICODE_STRING serialNo, PUNICODE_STRING pnpRev)
  46. /*++
  47. Routine Description:
  48. Parses the PNP COM ID out of the buffer which is passed as the
  49. first parameter and then saves the appropriate IDs as
  50. UNICODE_STRINGS in the other passed parameters.
  51. Return value:
  52. NTSTATUS
  53. --*/
  54. {
  55. PCHAR pOtherId;
  56. PCHAR pPnpRev;
  57. PCHAR pDevNodeName;
  58. PCHAR pSerNo;
  59. PCHAR pClass;
  60. PCHAR pCompIdStar;
  61. PCHAR pDesc;
  62. PCHAR pStrBuffer = NULL;
  63. NTSTATUS status;
  64. PCHAR pDevName;
  65. PCHAR pCompId;
  66. int OtherIDLen;
  67. int start;
  68. BOOLEAN isMouse = FALSE;
  69. PCHAR pMouseID = NULL;
  70. UNREFERENCED_PARAMETER(BufferLen);
  71. //
  72. // Allocate the string buffers
  73. //
  74. pStrBuffer = ExAllocatePool(PagedPool, MAX_DEVNODE_NAME * 7 + 1);
  75. if (pStrBuffer == NULL) {
  76. status = STATUS_INSUFFICIENT_RESOURCES;
  77. goto DoneParsingErr;
  78. } else {
  79. PCHAR pCurBuffer = pStrBuffer;
  80. pOtherId = pCurBuffer;
  81. *pOtherId = '\0';
  82. pCurBuffer += MAX_DEVNODE_NAME;
  83. pPnpRev = pCurBuffer;
  84. *pPnpRev = '\0';
  85. pCurBuffer += MAX_DEVNODE_NAME;
  86. pDevNodeName = pCurBuffer;
  87. *pDevNodeName = '\0';
  88. pCurBuffer += MAX_DEVNODE_NAME;
  89. pSerNo = pCurBuffer;
  90. *pSerNo = '\0';
  91. pCurBuffer += MAX_DEVNODE_NAME;
  92. pClass = pCurBuffer;
  93. *pClass = '\0';
  94. pCurBuffer += MAX_DEVNODE_NAME;
  95. pCompIdStar = pCurBuffer;
  96. pCompId = pCompIdStar + 1;
  97. *pCompIdStar = '\0';
  98. pCurBuffer += MAX_DEVNODE_NAME + 1;
  99. pDesc = pCurBuffer;
  100. *pDesc = '\0';
  101. pCurBuffer += MAX_DEVNODE_NAME;
  102. }
  103. start = Serenum_SzCopy ("SERENUM\\", pDevNodeName);
  104. pDevName = pDevNodeName + start;
  105. start = 0;
  106. RtlInitUnicodeString(hardwareIDs, NULL);
  107. RtlInitUnicodeString(compIDs, NULL);
  108. RtlInitUnicodeString(deviceIDs, NULL);
  109. RtlInitUnicodeString(pnpRev, NULL);
  110. RtlInitUnicodeString(serialNo, NULL);
  111. //
  112. // OtherID
  113. //
  114. start = Serenum_GetDevOtherID(ReadBuffer, pOtherId);
  115. if (start > 16) {
  116. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  117. ("Other ID string too long\n"));
  118. status = STATUS_UNSUCCESSFUL;
  119. goto DoneParsingErr;
  120. }
  121. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Other ID: %s\n", pOtherId));
  122. //
  123. // See if this is a mouse
  124. //
  125. SerenumScanOtherIdForMouse(ReadBuffer, BufferLen, &pMouseID);
  126. if (pMouseID != NULL && (*pMouseID == 'M' || *pMouseID == 'B')) {
  127. isMouse = TRUE;
  128. }
  129. //
  130. // PNP revision number
  131. //
  132. status = Serenum_GetDevPnPRev(FdoData, ReadBuffer, pPnpRev, &start);
  133. if (!NT_SUCCESS(status)) {
  134. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("PNP ID string bad\n"));
  135. goto DoneParsingErr;
  136. }
  137. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("PNP Revision: %s\n", pPnpRev));
  138. //
  139. // PNP device node name
  140. // EISA ID followed by Product ID
  141. //
  142. Serenum_GetDevName(ReadBuffer, pDevName, &start);
  143. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Device Node name: %s\n",
  144. pDevNodeName));
  145. //
  146. // Device serial number
  147. //
  148. Serenum_GetDevSerialNo(ReadBuffer, pSerNo, &start);
  149. if (Serenum_StrLen(pSerNo)) {
  150. //
  151. // This field exists - Make sure it is correct length.
  152. //
  153. if (Serenum_StrLen(pSerNo) != 8) {
  154. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Serial number wrong"
  155. " length\n"));
  156. *pSerNo = '\0';
  157. status = STATUS_UNSUCCESSFUL;
  158. goto DoneParsingErr;
  159. }
  160. }
  161. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Serial Number: %s\n", pSerNo));
  162. //
  163. // PNP class identifier
  164. //
  165. Serenum_GetDevClass(ReadBuffer, pClass, &start);
  166. if (Serenum_StrLen(pClass) > 32) {
  167. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Class ID string too long\n"
  168. ));
  169. status = STATUS_UNSUCCESSFUL;
  170. goto DoneParsingErr;
  171. }
  172. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Class: %s\n", pClass));
  173. if (_stricmp(pClass, "MOUSE") == 0) {
  174. strcpy(pClass, "SERIAL_MOUSE");
  175. }
  176. //
  177. // Compatible device ID
  178. //
  179. *pCompIdStar = '*';
  180. Serenum_GetDevCompId(ReadBuffer, pCompId, &start);
  181. if (Serenum_StrLen(pCompId) > 40) {
  182. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Compatible driver ID"
  183. " string too long\n"));
  184. status = STATUS_UNSUCCESSFUL;
  185. goto DoneParsingErr;
  186. }
  187. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Compatible driver ID: %s\n",
  188. pCompId));
  189. //
  190. // End-user legible Product Description
  191. //
  192. Serenum_GetDevDesc (ReadBuffer, pDesc, &start);
  193. if (Serenum_StrLen(pDesc) > 40) {
  194. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Device Description too"
  195. " long\n"));
  196. status = STATUS_UNSUCCESSFUL;
  197. goto DoneParsingErr;
  198. }
  199. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Device Description: %s\n",
  200. pDesc));
  201. DoneParsingErr:
  202. if (pStrBuffer != NULL) {
  203. //
  204. // send back the good bits so that routine knows what driver to load
  205. //
  206. Serenum_InitMultiString (FdoData, hardwareIDs, pDevNodeName, pDevName,
  207. NULL);
  208. if (Serenum_StrLen(pCompId) > 0) {
  209. if (!isMouse) {
  210. Serenum_InitMultiString(FdoData, compIDs, pCompIdStar, pClass,
  211. NULL);
  212. } else {
  213. Serenum_InitMultiString(FdoData, compIDs, pCompIdStar, pClass,
  214. "SERIAL_MOUSE", NULL);
  215. }
  216. } else {
  217. if (isMouse) {
  218. Serenum_InitMultiString(FdoData, compIDs, "SERIAL_MOUSE", NULL);
  219. }
  220. }
  221. Serenum_InitMultiString(FdoData, deviceIDs, pDevNodeName, NULL);
  222. Serenum_InitMultiString(FdoData, PDeviceDesc, pDesc, NULL);
  223. if (Serenum_StrLen(pSerNo)) {
  224. Serenum_InitMultiString(FdoData, serialNo, pSerNo, NULL);
  225. }
  226. if (Serenum_StrLen(pPnpRev)) {
  227. Serenum_InitMultiString(FdoData, pnpRev, pPnpRev, NULL);
  228. }
  229. ExFreePool(pStrBuffer);
  230. }
  231. return status;
  232. }
  233. NTSTATUS
  234. Serenum_InitMultiString(PFDO_DEVICE_DATA FdoData, PUNICODE_STRING MultiString,
  235. ...)
  236. /*++
  237. This routine will take a null terminated list of ascii strings and combine
  238. them together to generate a unicode multi-string block
  239. Arguments:
  240. MultiString - a unicode structure in which a multi-string will be built
  241. ... - a null terminated list of narrow strings which will be
  242. combined together. This list must contain at least a
  243. trailing NULL
  244. Return Value:
  245. NTSTATUS
  246. --*/
  247. {
  248. ANSI_STRING ansiString;
  249. NTSTATUS status;
  250. PCSTR rawString;
  251. PWSTR unicodeLocation;
  252. ULONG multiLength = 0;
  253. UNICODE_STRING unicodeString;
  254. va_list ap;
  255. ULONG i;
  256. PAGED_CODE();
  257. #if !DBG
  258. UNREFERENCED_PARAMETER(FdoData);
  259. #endif
  260. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  261. ("Entering Serenum_InitMultiString\n"));
  262. va_start(ap,MultiString);
  263. //
  264. // Make sure that we won't leak memory
  265. //
  266. ASSERT(MultiString->Buffer == NULL);
  267. rawString = va_arg(ap, PCSTR);
  268. while (rawString != NULL) {
  269. RtlInitAnsiString(&ansiString, rawString);
  270. multiLength += RtlAnsiStringToUnicodeSize(&(ansiString));
  271. rawString = va_arg(ap, PCSTR);
  272. }
  273. va_end( ap );
  274. if (multiLength == 0) {
  275. //
  276. // Done
  277. //
  278. RtlInitUnicodeString(MultiString, NULL);
  279. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  280. ("Leaving Serenum_InitMultiString (1)\n"));
  281. return STATUS_SUCCESS;
  282. }
  283. //
  284. // We need an extra null
  285. //
  286. multiLength += sizeof(WCHAR);
  287. MultiString->MaximumLength = (USHORT)multiLength;
  288. MultiString->Buffer = ExAllocatePool(PagedPool, multiLength);
  289. MultiString->Length = 0;
  290. if (MultiString->Buffer == NULL) {
  291. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  292. ("Leaving Serenum_InitMultiString (2)\n"));
  293. return STATUS_INSUFFICIENT_RESOURCES;
  294. }
  295. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  296. ("Allocated %lu bytes for buffer\n", multiLength));
  297. #if DBG
  298. RtlFillMemory(MultiString->Buffer, multiLength, 0xff);
  299. #endif
  300. unicodeString.Buffer = MultiString->Buffer;
  301. unicodeString.MaximumLength = (USHORT) multiLength;
  302. va_start(ap, MultiString);
  303. rawString = va_arg(ap, PCSTR);
  304. while (rawString != NULL) {
  305. RtlInitAnsiString(&ansiString,rawString);
  306. status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
  307. //
  308. // We don't allocate memory, so if something goes wrong here,
  309. // its the function that's at fault
  310. //
  311. ASSERT(NT_SUCCESS(status));
  312. //
  313. // Check for any commas and replace them with NULLs
  314. //
  315. ASSERT(unicodeString.Length % sizeof(WCHAR) == 0);
  316. for (i = 0; i < (unicodeString.Length / sizeof(WCHAR)); i++) {
  317. if (unicodeString.Buffer[i] == L'\x2C' ||
  318. unicodeString.Buffer[i] == L'\x0C' ) {
  319. unicodeString.Buffer[i] = L'\0';
  320. }
  321. }
  322. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("unicode buffer: %ws\n",
  323. unicodeString.Buffer));
  324. //
  325. // Move the buffers along
  326. //
  327. unicodeString.Buffer += ((unicodeString.Length / sizeof(WCHAR)) + 1);
  328. unicodeString.MaximumLength -= (unicodeString.Length + sizeof(WCHAR));
  329. unicodeString.Length = 0;
  330. //
  331. // Next
  332. //
  333. rawString = va_arg(ap, PCSTR);
  334. } // while
  335. va_end(ap);
  336. ASSERT(unicodeString.MaximumLength == sizeof(WCHAR));
  337. //
  338. // Stick the final null there
  339. //
  340. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("unicode buffer last addr: "
  341. "%x\n", unicodeString.Buffer));
  342. unicodeString.Buffer[0] = L'\0';
  343. //
  344. // Include the nulls in the length of the string
  345. //
  346. MultiString->Length = (USHORT)multiLength;
  347. MultiString->MaximumLength = MultiString->Length;
  348. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  349. ("Leaving Serenum_InitMultiString (3)\n"));
  350. return STATUS_SUCCESS;
  351. }
  352. int
  353. Serenum_StrLen (
  354. PCHAR string)
  355. // Measures the length of a string
  356. {
  357. int i;
  358. if (string == NULL) {
  359. return 0;
  360. }
  361. for (i=0; string[i] != '\0'; i++) {
  362. }
  363. return i;
  364. }
  365. int
  366. Serenum_SzCopy (
  367. PCHAR source,
  368. PCHAR dest)
  369. // Copies a string
  370. // Assumes the buffer is already allocated to be copied into
  371. {
  372. int i;
  373. ASSERT (source);
  374. ASSERT (dest);
  375. for (i=0; source[i] != '\0'; i++) {
  376. *dest++ = source[i];
  377. }
  378. return i;
  379. }
  380. //
  381. // String extraction functions:
  382. //
  383. int
  384. Serenum_GetDevOtherID(
  385. PCHAR input,
  386. PCHAR output)
  387. {
  388. int tail;
  389. CHAR c;
  390. tail = 0;
  391. c = input[tail++];
  392. while((tail < 17 ) && (c != '(') && (c != '(' - 0x20)) {
  393. *output++ = c;
  394. c = input[tail++];
  395. }
  396. *output = '\0';
  397. return(tail-1);
  398. }
  399. /****************************************************************************
  400. *
  401. *
  402. ***************************************************************************/
  403. int
  404. Serenum_HToI(char c) {
  405. if('0' <= c && c <= '9')
  406. return(c - '0');
  407. if('A' <= c && c <= 'F')
  408. return(c - 'A' + 10);
  409. if('a' <= c && c <= 'f')
  410. return(c - 'a' + 10);
  411. return(-1);
  412. }
  413. void
  414. Serenum_FixptToAscii(
  415. int n,
  416. PCHAR output)
  417. /****************************************************************************
  418. *
  419. *
  420. ***************************************************************************/
  421. {
  422. int tmp;
  423. tmp = n / 100;
  424. if(tmp >= 10)
  425. *output++ = (CHAR)('0' + (tmp / 10));
  426. *output++ = (CHAR)('0' + (tmp % 10));
  427. *output++ = '.';
  428. tmp = n % 100;
  429. *output++ = (CHAR)('0' + (tmp / 10));
  430. *output++ = (CHAR)('0' + (tmp % 10));
  431. *output = '\0';
  432. }
  433. /****************************************************************************
  434. *
  435. *
  436. ***************************************************************************/
  437. NTSTATUS
  438. Serenum_GetDevPnPRev(PFDO_DEVICE_DATA FdoData, PCHAR input, PCHAR output,
  439. int *start)
  440. {
  441. int tail;
  442. int i;
  443. char delta;
  444. char c, begin_PnP, end_PnP_pos;
  445. int sum, chk_sum, msd, lsd;
  446. UNREFERENCED_PARAMETER(FdoData);
  447. if (output == NULL || input == NULL) {
  448. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  449. ("GetDevPnPRev Failed, NULL pointer!\n"));
  450. return STATUS_UNSUCCESSFUL;
  451. }
  452. *output = '\0';
  453. tail = *start;
  454. if (input[tail] == 0) {
  455. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  456. ("GetDevPnPRev Failed, input buffer empty!\n"));
  457. return STATUS_UNSUCCESSFUL;
  458. }
  459. c = input[tail++];
  460. while ((tail < 256) && (c != '(') && (c != '(' - 0x20)) {
  461. c = input[tail++];
  462. }
  463. if (c != '(' && c != '(' - 0x20) {
  464. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  465. ("GetDevPnPRev Failed, no Begin PnP char!\n"));
  466. return STATUS_UNSUCCESSFUL;
  467. }
  468. begin_PnP = c;
  469. delta = '(' - begin_PnP;
  470. if (input[tail + 9] != ')' - delta) {
  471. //
  472. // compute checksum
  473. //
  474. sum = c;
  475. i = tail;
  476. while ( (i < 256) && (c != ( ')' - delta)) ) {
  477. c = input[i++];
  478. sum += c;
  479. }
  480. msd = input[i-3];
  481. lsd = input[i-2];
  482. sum -= msd;
  483. sum -= lsd;
  484. msd += delta;
  485. lsd += delta;
  486. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  487. ("checksum from device (chars) = %c%c\n", (char)msd,
  488. (char)lsd));
  489. msd = Serenum_HToI((char)msd);
  490. if (msd < 0) {
  491. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  492. ("Bad msd checksum digit\n"));
  493. return STATUS_UNSUCCESSFUL;
  494. }
  495. lsd = Serenum_HToI((char)lsd);
  496. if (lsd < 0) {
  497. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  498. ("Bad lsd checksum digit\n"));
  499. return STATUS_UNSUCCESSFUL;
  500. }
  501. chk_sum = (msd << 4) + lsd;
  502. sum &= 0xff;
  503. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  504. ("checksum read from device = %0x\n", chk_sum));
  505. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
  506. ("Computed checksum = %0x\n", sum));
  507. end_PnP_pos = (char)i;
  508. if ( c - begin_PnP != ')' - '(' ) {
  509. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  510. ("GetDevPnPRev Failed,BeginPnP didn't match "
  511. "EndPnP\n"));
  512. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  513. ("begin_PnP = %02x end_PnP = %02x\n", begin_PnP, c));
  514. return STATUS_UNSUCCESSFUL;
  515. }
  516. //
  517. // check the checksum
  518. //
  519. if (chk_sum != sum) {
  520. Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
  521. ("checksum Failed! Continuing...\n"));
  522. // return STATUS_UNSUCCESSFUL; // Commented out in Memphis
  523. }
  524. i = end_PnP_pos;
  525. input[i-3] = ')' - delta; // trash the checksum
  526. input[i-2] = '\0'; // since we are done with it
  527. }
  528. if (input[tail] > 0x3f ||
  529. input[tail+1] > 0x3f) {
  530. Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Bad PnP Rev digits\n"));
  531. return STATUS_UNSUCCESSFUL;
  532. }
  533. i = (input[tail++] & 0x3f) << 6;
  534. i |= (input[tail++]) & 0x3f;
  535. Serenum_FixptToAscii(i, output);
  536. i = tail;
  537. //
  538. // get ride of Mouse'output 0x20 bias in the string
  539. //
  540. while ( (i < 256) && delta ) {
  541. input[i] += delta;
  542. c = input[i++];
  543. if ( c == ')' ) {
  544. delta = 0; // indicate we are done
  545. }
  546. }
  547. *start = tail;
  548. return STATUS_SUCCESS;
  549. }
  550. /****************************************************************************
  551. *
  552. *
  553. ***************************************************************************/
  554. void Serenum_GetDevName(
  555. PCHAR input,
  556. PCHAR output,
  557. int *start)
  558. {
  559. int tail;
  560. char c;
  561. if(output == NULL || input == NULL)
  562. return;
  563. tail = *start;
  564. // EISA ID
  565. *output++ = input[tail++];
  566. *output++ = input[tail++];
  567. *output++ = input[tail++];
  568. // Product ID
  569. c = input[tail++];
  570. if(Serenum_HToI(c) >= 0)
  571. *output++ = c;
  572. c = input[tail++];
  573. if(Serenum_HToI(c) >= 0)
  574. *output++ = c;
  575. c = input[tail++];
  576. if(Serenum_HToI(c) >= 0)
  577. *output++ = c;
  578. c = input[tail++];
  579. if(Serenum_HToI(c) >= 0)
  580. *output++ = c;
  581. *output = '\0';
  582. *start = tail;
  583. return;
  584. }
  585. /****************************************************************************
  586. *
  587. *
  588. ***************************************************************************/
  589. void Serenum_GetDevSerialNo(
  590. PCHAR input,
  591. PCHAR output,
  592. int *start)
  593. {
  594. int tail, cnt;
  595. char c;
  596. if(output == NULL || input == NULL)
  597. return;
  598. *output = '\0';
  599. tail = *start;
  600. if( input[tail++] != '\\')
  601. return;
  602. c = input[tail++];
  603. cnt = 0;
  604. while(cnt < 8 && tail < 256 && ( c != '\\') && ( c != ')') ) {
  605. cnt++;
  606. if(Serenum_HToI(c) < 0)
  607. break;
  608. *output++ = c;
  609. c = input[tail++];
  610. }
  611. *output = '\0';
  612. *start = tail - 1;
  613. return;
  614. }
  615. /****************************************************************************
  616. *
  617. *
  618. ***************************************************************************/
  619. void Serenum_GetDevClass(
  620. PCHAR input,
  621. PCHAR output,
  622. int *start)
  623. {
  624. int tail;
  625. char c;
  626. if(output == NULL || input == NULL)
  627. return;
  628. *output = '\0';
  629. tail = *start;
  630. if( input[tail++] != '\\')
  631. return;
  632. c = input[tail++];
  633. while(tail < 256 && ( c != '\\') && ( c != ')') ) {
  634. *output++ = c;
  635. c = input[tail++];
  636. }
  637. *output = '\0';
  638. *start = tail - 1;
  639. return;
  640. }
  641. void Serenum_GetDevCompId(
  642. PCHAR input,
  643. PCHAR output,
  644. int *start)
  645. /****************************************************************************
  646. *
  647. *
  648. ***************************************************************************/
  649. {
  650. int tail;
  651. char c;
  652. if(output == NULL || input == NULL)
  653. return;
  654. *output = '\0';
  655. tail = *start;
  656. if( input[tail++] != '\\')
  657. return;
  658. c = input[tail++];
  659. while(tail < 256 && ( c != '\\') && ( c != ')') ) {
  660. *output++ = c;
  661. //
  662. // Put a * after every comma
  663. //
  664. if ('\x0C' == c || '\x2C' == c) {
  665. *output++ = '*';
  666. }
  667. c = input[tail++];
  668. }
  669. *output = '\0';
  670. *start = tail - 1;
  671. }
  672. void
  673. Serenum_GetDevDesc(
  674. PCHAR input,
  675. PCHAR output,
  676. int *start)
  677. /****************************************************************************
  678. *
  679. *
  680. ***************************************************************************/
  681. {
  682. int tail;
  683. char c;
  684. if(output == NULL || input == NULL)
  685. return;
  686. *output = '\0';
  687. tail = *start;
  688. if( input[tail++] != '\\')
  689. return;
  690. c = input[tail++];
  691. while(tail < 256 && ( c != '\\') && ( c != ')') ) {
  692. *output++ = c;
  693. c = input[tail++];
  694. }
  695. *output = '\0';
  696. *start = tail - 1;
  697. }