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.

771 lines
25 KiB

  1. /*
  2. (C) Copyright 1998
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1994 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the same terms
  7. outlined in the Microsoft Windows Device Driver Development Kit.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL TpiParam TpiParam_c
  12. @module TpiParam.c |
  13. This module, along with <f TpiParam\.h>, implements a table driven parser
  14. for the NDIS registry parameters.
  15. @comm
  16. See <f Keywords\.h> for details of how to add new parameters.<nl>
  17. This is a driver independent module which can be re-used, without
  18. change, by any NDIS3 driver.
  19. @head3 Contents |
  20. @index class,mfunc,func,msg,mdata,struct,enum | TpiParam_c
  21. @end
  22. */
  23. #define __FILEID__ TPI_MODULE_PARAMS // Unique file ID for error logging
  24. #include <ndis.h>
  25. #include "TpiDebug.h"
  26. #include "TpiParam.h"
  27. #if defined(_VXD_) && !defined(NDIS_LCODE)
  28. # define NDIS_LCODE code_seg("_LTEXT", "LCODE")
  29. # define NDIS_LDATA data_seg("_LDATA", "LCODE")
  30. #endif
  31. #if defined(NDIS_LCODE)
  32. # pragma NDIS_LCODE // Windows 95 wants this code locked down!
  33. # pragma NDIS_LDATA
  34. #endif
  35. static NDIS_PHYSICAL_ADDRESS g_HighestAcceptableAddress =
  36. NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
  37. static NDIS_STRING g_NullString =
  38. NDIS_STRING_CONST("\0");
  39. /* @doc INTERNAL TpiParam TpiParam_c ustrlen
  40. @func
  41. <f ustrlen> counts the number of characters in
  42. a UNICODE (wide) string.
  43. @comm
  44. @rdesc
  45. <f ustrlen> returns the length of the UNICODE string
  46. pointed to by <p string>. The terminating NULL character is not
  47. counted.
  48. */
  49. USHORT ustrlen(
  50. IN PUSHORT string // @parm
  51. // Pointer to the beginning of a UNICODE string ending
  52. // with a 0x0000 value.
  53. )
  54. {
  55. USHORT ct;
  56. for (ct = 0; *string != 0x0000; string++, ct++)
  57. ;
  58. return(ct);
  59. }
  60. /* @doc INTERNAL TpiParam TpiParam_c ParamUnicodeStringToAnsiString
  61. @func
  62. <f ParamUnicodeStringToAnsiString> converts a double byte string to a
  63. single byte string.
  64. @comm
  65. The original release of the NDIS Wrapper for Windows 95 and 3.1 does not
  66. return UNICODE strings from the NdisReadConfiguration routine. So this
  67. routine attempts to auto detect this situation by examining the first
  68. character of the string. If the second byte of the first character is
  69. a zero, the string is assumed to be UNICODE, and it is converted to an
  70. ANSI string; otherwise the ANSI string is just copied.
  71. <nl>
  72. <f Note>: This also assumes that the first character of any UNICODE
  73. string will not use the second byte (i.e. not an extended character).
  74. This routine will only successfully convert non-extended character
  75. strings anyway.
  76. @xref
  77. <f ParamParseRegistry>
  78. */
  79. VOID ParamUnicodeStringToAnsiString(
  80. OUT PANSI_STRING out, // @parm
  81. // A pointer to where the converted ANSI string is to be stored.
  82. IN PUNICODE_STRING in // @parm
  83. // A pointer to the UNICODE string to be converted.
  84. )
  85. {
  86. DBG_FUNC("ParamUnicodeStringToAnsiString")
  87. UINT Index;
  88. /* CAVEAT - NDIS_BUG
  89. // NDIS driver for Windows 95 does not return UNICODE from
  90. // registry parser, so we need to kludge it up here.
  91. */
  92. if (in->Length > 1)
  93. {
  94. if (((PUCHAR)(in->Buffer))[1] == 0)
  95. {
  96. /*
  97. // Probably a UNICODE string since all our parameters are ASCII
  98. // strings.
  99. */
  100. DBG_FILTER(DbgInfo, DBG_TRACE_ON,
  101. ("UNICODE STRING IN @%x#%d='%ls'\n",
  102. in->Buffer, in->Length, in->Buffer));
  103. for (Index = 0; Index < (in->Length / sizeof(WCHAR)) &&
  104. Index < out->MaximumLength; Index++)
  105. {
  106. out->Buffer[Index] = (UCHAR) in->Buffer[Index];
  107. }
  108. }
  109. else
  110. {
  111. /*
  112. // Probably an ANSI string since all our parameters are more
  113. // than 1 byte long and should not be zero in the second byte.
  114. */
  115. PANSI_STRING in2 = (PANSI_STRING) in;
  116. DBG_FILTER(DbgInfo, DBG_TRACE_ON,
  117. ("ANSI STRING IN @%x#%d='%s'\n",
  118. in2->Buffer, in2->Length, in2->Buffer));
  119. for (Index = 0; Index < in2->Length &&
  120. Index < out->MaximumLength; Index++)
  121. {
  122. out->Buffer[Index] = in2->Buffer[Index];
  123. }
  124. }
  125. }
  126. else
  127. {
  128. DBG_WARNING(DbgInfo,("1 BYTE STRING IN @%x=%04x\n",
  129. in->Buffer, in->Buffer[0]));
  130. out->Buffer[0] = (UCHAR) in->Buffer[0];
  131. Index = 1;
  132. }
  133. out->Length = (USHORT) Index; // * sizeof(UCHAR);
  134. // NULL terminate the string if there's room.
  135. if (out->Length <= (out->MaximumLength - sizeof(UCHAR)))
  136. {
  137. out->Buffer[Index] = 0;
  138. }
  139. ASSERT(out->Length <= out->MaximumLength);
  140. }
  141. /* @doc INTERNAL TpiParam TpiParam_c ParamUnicodeCopyString
  142. @func
  143. <f ParamUnicodeCopyString> copies a double byte string to a double byte
  144. string.
  145. @comm
  146. The original release of the NDIS Wrapper for Windows 95 and 3.1 does not
  147. return UNICODE strings from the NdisReadConfiguration routine. So this
  148. routine attempts to auto detect this situation by examining the first
  149. character of the string. If the second byte of the first character is
  150. a zero, the string is assumed to be UNICODE, and it just copied;
  151. otherwise the ANSI string is converted to UNICODE.
  152. <nl>
  153. <f Note>: This also assumes that the first character of any UNICODE
  154. string will not use the second byte (i.e. not an extended character).
  155. This routine will only successfully convert non-extended character
  156. strings anyway.
  157. @xref
  158. <f ParamParseRegistry>
  159. */
  160. VOID ParamUnicodeCopyString(
  161. OUT PUNICODE_STRING out, // @parm
  162. // A pointer to where the new UNICODE string is to be stored.
  163. IN PUNICODE_STRING in // @parm
  164. // A pointer to the UNICODE string to be copied.
  165. )
  166. {
  167. DBG_FUNC("ParamUnicodeCopyString")
  168. UINT Index;
  169. /* CAVEAT - NDIS_BUG
  170. // NDIS driver for Windows 95 does not return UNICODE from
  171. // registry parser, so we need to kludge it up here.
  172. */
  173. if (in->Length > 1)
  174. {
  175. if (((PUCHAR)(in->Buffer))[1] == 0)
  176. {
  177. /*
  178. // Probably a UNICODE string since all our parameters are ASCII
  179. // strings.
  180. */
  181. DBG_FILTER(DbgInfo, DBG_TRACE_ON,
  182. ("UNICODE STRING IN @%x#%d='%ls'\n",
  183. in->Buffer, in->Length, in->Buffer));
  184. for (Index = 0; Index < (in->Length / sizeof(WCHAR)) &&
  185. Index < (out->MaximumLength / sizeof(WCHAR)); Index++)
  186. {
  187. out->Buffer[Index] = in->Buffer[Index];
  188. }
  189. }
  190. else
  191. {
  192. /*
  193. // Probably an ANSI string since all our parameters are more
  194. // than 1 byte long and should not be zero in the second byte.
  195. */
  196. PANSI_STRING in2 = (PANSI_STRING) in;
  197. DBG_FILTER(DbgInfo, DBG_TRACE_ON,
  198. ("ANSI STRING IN @%x#%d='%s'\n",
  199. in2->Buffer, in2->Length, in2->Buffer));
  200. for (Index = 0; Index < in2->Length &&
  201. Index < (out->MaximumLength / sizeof(WCHAR)); Index++)
  202. {
  203. out->Buffer[Index] = (WCHAR) in2->Buffer[Index];
  204. }
  205. }
  206. }
  207. else
  208. {
  209. DBG_WARNING(DbgInfo,("1 BYTE STRING IN @%x=%04x\n",
  210. in->Buffer, in->Buffer[0]));
  211. out->Buffer[0] = (WCHAR) in->Buffer[0];
  212. Index = 1;
  213. }
  214. out->Length = Index * sizeof(WCHAR);
  215. // NULL terminate the string if there's room.
  216. if (out->Length <= (out->MaximumLength - sizeof(WCHAR)))
  217. {
  218. out->Buffer[Index] = 0;
  219. }
  220. ASSERT(out->Length <= out->MaximumLength);
  221. }
  222. /* @doc INTERNAL TpiParam TpiParam_c ParamGetNumEntries
  223. @func
  224. <f ParamGetNumEntries> counts the number of records in the registry
  225. parameter table.
  226. @rdesc
  227. <f ParamGetNumEntries> returns the number of entries in the parameter
  228. table.
  229. @xref
  230. <f ParamParseRegistry>
  231. */
  232. DBG_STATIC UINT ParamGetNumEntries(
  233. IN PPARAM_TABLE Parameters // @parm
  234. // A pointer to an array of registry parameter records.
  235. )
  236. {
  237. UINT NumRecs = 0;
  238. /*
  239. // Scan the parameter array until we find an entry with zero length name.
  240. */
  241. if (Parameters)
  242. {
  243. while (Parameters->RegVarName.Length)
  244. {
  245. NumRecs++;
  246. Parameters++;
  247. }
  248. }
  249. return(NumRecs);
  250. }
  251. /* @doc INTERNAL TpiParam TpiParam_c ParamParseRegistry
  252. @func
  253. <f ParamParseRegistry> parses the registry parameter table and attempts
  254. to read a value from the registry for each parameter record.
  255. @rdesc
  256. <f ParamParseRegistry> returns one of the following values:
  257. @flag NDIS_STATUS_SUCCESS |
  258. If this function is successful.
  259. <f Note>: A non-zero return value indicates one of the following error codes:
  260. @iex
  261. NDIS_STATUS_FAILURE
  262. @xref
  263. <f MiniportInitialize>
  264. <f ParamGetNumEntries>
  265. <f NdisOpenConfiguration>
  266. <f NdisWriteErrorLogEntry>
  267. <f NdisReadConfiguration>
  268. <f NdisCloseConfiguration>
  269. <f NdisAllocateMemory>
  270. <f NdisZeroMemory>
  271. <f ParamUnicodeStringToAnsiString>
  272. <f ParamUnicodeCopyString>
  273. */
  274. NDIS_STATUS ParamParseRegistry(
  275. IN NDIS_HANDLE AdapterHandle, // @parm
  276. // Handle to pass to NdisWriteErrorLogEntry if any errors are encountered.
  277. IN NDIS_HANDLE WrapperConfigurationContext,// @parm
  278. // Handle to pass to NdisOpenConfiguration.
  279. IN PUCHAR BaseContext, // @parm
  280. // References the base of the structure where the values read from the
  281. // registry are written. Typically, this will be a pointer to the first
  282. // byte of the adapter information structure.
  283. IN PPARAM_TABLE Parameters // @parm
  284. // A pointer to an array of registry parameter records <t PARAM_TABLE>.
  285. )
  286. {
  287. DBG_FUNC("ParamParseRegistry")
  288. PNDIS_CONFIGURATION_PARAMETER pReturnedValue;
  289. NDIS_CONFIGURATION_PARAMETER ReturnedValue;
  290. NDIS_PARAMETER_TYPE ParamType;
  291. /*
  292. // The handle for reading from the registry.
  293. */
  294. NDIS_HANDLE ConfigHandle;
  295. UINT NumRecs = ParamGetNumEntries(Parameters);
  296. UINT i;
  297. PPARAM_TABLE pParameter;
  298. NDIS_STATUS Status;
  299. UINT Value;
  300. PANSI_STRING pAnsi;
  301. UINT Length;
  302. /*
  303. // Open the configuration registry so we can get our config values.
  304. */
  305. NdisOpenConfiguration(
  306. &Status,
  307. &ConfigHandle,
  308. WrapperConfigurationContext
  309. );
  310. if (Status != NDIS_STATUS_SUCCESS)
  311. {
  312. /*
  313. // Log error message and exit.
  314. */
  315. DBG_ERROR(DbgInfo,("NdisOpenConfiguration failed (Status=%X)\n",Status));
  316. NdisWriteErrorLogEntry(
  317. AdapterHandle,
  318. NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
  319. 3,
  320. Status,
  321. __FILEID__,
  322. __LINE__
  323. );
  324. return NDIS_STATUS_FAILURE;
  325. }
  326. /*
  327. // Walk through all the parameters in the table.
  328. */
  329. for (i = 0, pParameter = Parameters; i < NumRecs; i++, pParameter++)
  330. {
  331. #if DBG
  332. ANSI_STRING ansiRegString;
  333. char ansiRegName[64];
  334. /*
  335. // Get a printable parameter name.
  336. */
  337. ansiRegString.Length = 0;
  338. ansiRegString.MaximumLength = sizeof(ansiRegName);
  339. ansiRegString.Buffer = (PCHAR)ansiRegName;
  340. NdisZeroMemory(ansiRegName, sizeof(ansiRegName));
  341. ParamUnicodeStringToAnsiString(
  342. &ansiRegString,
  343. (PUNICODE_STRING)&pParameter->RegVarName
  344. );
  345. #endif // DBG
  346. ASSERT(pParameter->Type <= (UINT) NdisParameterMultiString);
  347. /*
  348. // Attempt to read the parameter value from the registry.
  349. */
  350. ParamType = (NDIS_PARAMETER_TYPE) pParameter->Type;
  351. NdisReadConfiguration(&Status,
  352. &pReturnedValue,
  353. ConfigHandle,
  354. &pParameter->RegVarName,
  355. ParamType
  356. );
  357. /*
  358. // If value is not present, and it is mandatory, return failure code.
  359. */
  360. if (Status != NDIS_STATUS_SUCCESS && pParameter->Mandantory)
  361. {
  362. /*
  363. // Log error message and exit.
  364. */
  365. DBG_ERROR(DbgInfo,("%s: NOT IN REGISTRY!\n",
  366. ansiRegName));
  367. NdisWriteErrorLogEntry(
  368. AdapterHandle,
  369. NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
  370. 4,
  371. i,
  372. Status,
  373. __FILEID__,
  374. __LINE__
  375. );
  376. NdisCloseConfiguration(ConfigHandle);
  377. return NDIS_STATUS_FAILURE;
  378. }
  379. /*
  380. // Determine how the caller wants to interpret this parameter.
  381. */
  382. if (ParamType == NdisParameterInteger ||
  383. ParamType == NdisParameterHexInteger)
  384. {
  385. ASSERT(pParameter->Size <= sizeof(ULONG));
  386. /*
  387. // If value read, use it, otherwise use default.
  388. */
  389. if (Status == NDIS_STATUS_SUCCESS)
  390. {
  391. Value = pReturnedValue->ParameterData.IntegerData;
  392. }
  393. else
  394. {
  395. Value = (UINT) (LONG_PTR)(pParameter->Default);
  396. }
  397. /*
  398. // If there are min/max boundaries, verify that value is in range.
  399. */
  400. if (pParameter->Min || pParameter->Max)
  401. {
  402. if (Value < pParameter->Min)
  403. {
  404. DBG_ERROR(DbgInfo,("%s: Value=%X < Min=%X\n",
  405. ansiRegName, Value, pParameter->Min));
  406. Value = pParameter->Min;
  407. }
  408. else if (Value > pParameter->Max)
  409. {
  410. DBG_ERROR(DbgInfo,("%s: Value=%X > Max=%X\n",
  411. ansiRegName, Value, pParameter->Max));
  412. Value = pParameter->Max;
  413. }
  414. }
  415. /*
  416. // Size of destination in bytes 1, 2, or 4 (default==INT).
  417. */
  418. switch (pParameter->Size)
  419. {
  420. case 0:
  421. *(PUINT)(BaseContext+pParameter->Offset) = (UINT) Value;
  422. break;
  423. case 1:
  424. if (Value & 0xFFFFFF00)
  425. {
  426. DBG_WARNING(DbgInfo,("%s: OVERFLOWS UCHAR\n",
  427. ansiRegName));
  428. }
  429. *(PUCHAR)(BaseContext+pParameter->Offset) = (UCHAR) Value;
  430. break;
  431. case 2:
  432. if (Value & 0xFFFF0000)
  433. {
  434. DBG_WARNING(DbgInfo,("%s: OVERFLOWS USHORT\n",
  435. ansiRegName));
  436. }
  437. *(PUSHORT)(BaseContext+pParameter->Offset) = (USHORT) Value;
  438. break;
  439. case 4:
  440. *(PULONG)(BaseContext+pParameter->Offset) = (ULONG) Value;
  441. break;
  442. default:
  443. DBG_ERROR(DbgInfo,("%s: Invalid ParamSize=%d\n",
  444. ansiRegName, pParameter->Size));
  445. NdisCloseConfiguration(ConfigHandle);
  446. return NDIS_STATUS_FAILURE;
  447. break;
  448. }
  449. if (ParamType == NdisParameterInteger)
  450. {
  451. DBG_PARAMS(DbgInfo,("%s: Value=%d Size=%d (%s)\n",
  452. ansiRegName, Value, pParameter->Size,
  453. (Status == NDIS_STATUS_SUCCESS) ?
  454. "Registry" : "Default"));
  455. }
  456. else
  457. {
  458. DBG_PARAMS(DbgInfo,("%s: Value=0x%X Size=%d (%s)\n",
  459. ansiRegName, Value, pParameter->Size,
  460. (Status == NDIS_STATUS_SUCCESS) ?
  461. "Registry" : "Default"));
  462. }
  463. }
  464. else if (ParamType == NdisParameterString ||
  465. ParamType == NdisParameterMultiString)
  466. {
  467. ASSERT(pParameter->Size == sizeof(ANSI_STRING));
  468. /*
  469. // If value not read from registry.
  470. */
  471. if (Status != NDIS_STATUS_SUCCESS)
  472. {
  473. /*
  474. // Use our own temporary ReturnedValue.
  475. */
  476. pReturnedValue = &ReturnedValue;
  477. pReturnedValue->ParameterType = ParamType;
  478. /*
  479. // If default non-zero, use default value.
  480. */
  481. if (pParameter->Default != 0)
  482. {
  483. NdisMoveMemory(&pReturnedValue->ParameterData.StringData,
  484. (PANSI_STRING) pParameter->Default,
  485. sizeof(ANSI_STRING));
  486. }
  487. else
  488. {
  489. /*
  490. // Otherwise, use null string value.
  491. */
  492. NdisMoveMemory(&pReturnedValue->ParameterData.StringData,
  493. &g_NullString,
  494. sizeof(g_NullString));
  495. }
  496. }
  497. /*
  498. // Assume the string is ANSI and points to the string data
  499. // structure. We can get away with this because ANSI and
  500. // UNICODE strings have a common structure header. An extra
  501. // character is allocated to make room for a null terminator.
  502. */
  503. pAnsi = (PANSI_STRING) (BaseContext+pParameter->Offset);
  504. Length = pReturnedValue->ParameterData.StringData.Length+1;
  505. /*
  506. // The caller wants a UNICODE string returned, we have to
  507. // allocated twice as many bytes to hold the result.
  508. // NOTE:
  509. // This wouldn't be necessary if NDIS would always return
  510. // a UNICODE string, but some Win95 versions of NDIS return
  511. // an ANSI string, so Length will be too small for UNICODE.
  512. // The down-side is that we may allocate twice as much as
  513. // we need to hold the string. (oh well)
  514. */
  515. if (pParameter->Flags == PARAM_FLAGS_UNICODESTRING)
  516. {
  517. Length *= sizeof(WCHAR);
  518. }
  519. /*
  520. // Allocate memory for the string.
  521. */
  522. #if !defined(NDIS50_MINIPORT)
  523. Status = NdisAllocateMemory(
  524. (PVOID *) &(pAnsi->Buffer),
  525. Length,
  526. 0,
  527. g_HighestAcceptableAddress
  528. );
  529. #else // NDIS50_MINIPORT
  530. Status = NdisAllocateMemoryWithTag(
  531. (PVOID *) &(pAnsi->Buffer),
  532. Length,
  533. __FILEID__
  534. );
  535. #endif // NDIS50_MINIPORT
  536. if (Status != NDIS_STATUS_SUCCESS)
  537. {
  538. /*
  539. // Log error message and exit.
  540. */
  541. DBG_ERROR(DbgInfo,("NdisAllocateMemory(Size=%d, File=%s, Line=%d) failed (Status=%X)\n",
  542. Length, __FILE__, __LINE__, Status));
  543. NdisWriteErrorLogEntry(
  544. AdapterHandle,
  545. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  546. 4,
  547. Status,
  548. Length,
  549. __FILEID__,
  550. __LINE__
  551. );
  552. NdisCloseConfiguration(ConfigHandle);
  553. return NDIS_STATUS_FAILURE;
  554. }
  555. else
  556. {
  557. DBG_FILTER(DbgInfo, DBG_MEMORY_ON,
  558. ("NdisAllocateMemory(Size=%d, Ptr=0x%x)\n",
  559. Length, pAnsi->Buffer));
  560. }
  561. /*
  562. // Zero the string buffer to start with.
  563. */
  564. ASSERT(pAnsi->Buffer);
  565. NdisZeroMemory(pAnsi->Buffer, Length);
  566. pAnsi->MaximumLength = (USHORT) Length;
  567. if (pParameter->Flags == PARAM_FLAGS_ANSISTRING)
  568. {
  569. /*
  570. // The caller wants an ANSI string returned, so we convert
  571. // it from UNICODE to ANSI.
  572. */
  573. ParamUnicodeStringToAnsiString(
  574. pAnsi,
  575. (PUNICODE_STRING) &(pReturnedValue->ParameterData.StringData)
  576. );
  577. #if DBG
  578. if (ParamType == NdisParameterMultiString)
  579. {
  580. USHORT ct = 0;
  581. while (ct < pAnsi->Length)
  582. {
  583. DBG_PARAMS(DbgInfo,("%s: ANSI='%s' Len=%d of %d\n",
  584. ansiRegName,
  585. &(pAnsi->Buffer[ct]),
  586. (strlen(&(pAnsi->Buffer[ct]))),
  587. pAnsi->Length));
  588. ct = ct + (strlen(&(pAnsi->Buffer[ct])) + 1);
  589. }
  590. }
  591. else
  592. {
  593. DBG_PARAMS(DbgInfo,("%s: ANSI='%s' Len=%d\n",
  594. ansiRegName, pAnsi->Buffer, pAnsi->Length));
  595. }
  596. #endif
  597. }
  598. else // PARAM_FLAGS_UNICODESTRING
  599. {
  600. /*
  601. // The caller wants a UNICODE string returned, so we can
  602. // just copy it. The pAnsi buffer was allocated large
  603. // enough to hold the UNICODE string.
  604. */
  605. ParamUnicodeCopyString(
  606. (PUNICODE_STRING) pAnsi,
  607. (PUNICODE_STRING) &(pReturnedValue->ParameterData.StringData)
  608. );
  609. #if DBG
  610. if (ParamType == NdisParameterMultiString)
  611. {
  612. USHORT ct = 0;
  613. BREAKPOINT;
  614. while (ct < (pAnsi->Length / 2))
  615. {
  616. DBG_PARAMS(DbgInfo,("%s: UNICODE='%ls' Len=%d of %d\n",
  617. ansiRegName,
  618. &((PUSHORT)pAnsi->Buffer)[ct],
  619. (ustrlen(&((PUSHORT)pAnsi->Buffer)[ct]) * 2),
  620. pAnsi->Length));
  621. ct = ct + (ustrlen(&((PUSHORT)pAnsi->Buffer)[ct]) + 1);
  622. }
  623. }
  624. else
  625. {
  626. DBG_PARAMS(DbgInfo,("%s: UNICODE='%ls' Len=%d\n",
  627. ansiRegName, pAnsi->Buffer, pAnsi->Length));
  628. }
  629. #endif
  630. }
  631. }
  632. else
  633. {
  634. /*
  635. // Report a bogus parameter type in the caller's table.
  636. */
  637. DBG_ERROR(DbgInfo,("Invalid ParamType=%d '%s'\n",
  638. ParamType, ansiRegName));
  639. NdisCloseConfiguration(ConfigHandle);
  640. return NDIS_STATUS_FAILURE;
  641. }
  642. }
  643. NdisCloseConfiguration(ConfigHandle);
  644. return(NDIS_STATUS_SUCCESS);
  645. }