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.

953 lines
22 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // iasparms.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines functions for storing and retrieving (name, value) pairs from
  12. // the SAM UserParameters field.
  13. //
  14. // MODIFICATION HISTORY
  15. //
  16. // 10/16/1998 Original version.
  17. // 02/11/1999 Add RasUser0 functions.
  18. // 02/24/1999 Treat invalid UserParameters as no dialin.
  19. // 03/16/1999 Truncate callback number if too long.
  20. //
  21. ///////////////////////////////////////////////////////////////////////////////
  22. #include <nt.h>
  23. #include <ntrtl.h>
  24. #include <nturtl.h>
  25. #include <windows.h>
  26. #include <stdio.h>
  27. #define IASSAMAPI
  28. #include <iasapi.h>
  29. #include <iasparms.h>
  30. //////////
  31. // I included the Netp function declarations here to avoid dependency on
  32. // the net project.
  33. //////////
  34. DECLSPEC_IMPORT
  35. NTSTATUS
  36. NTAPI
  37. NetpParmsSetUserProperty (
  38. IN LPWSTR UserParms,
  39. IN LPWSTR Property,
  40. IN UNICODE_STRING PropertyValue,
  41. IN WCHAR PropertyFlag,
  42. OUT LPWSTR * pNewUserParms,
  43. OUT BOOL * Update
  44. );
  45. DECLSPEC_IMPORT
  46. NTSTATUS
  47. NTAPI
  48. NetpParmsQueryUserProperty (
  49. IN LPWSTR UserParms,
  50. IN LPWSTR Property,
  51. OUT PWCHAR PropertyFlag,
  52. OUT PUNICODE_STRING PropertyValue
  53. );
  54. DECLSPEC_IMPORT
  55. VOID
  56. NTAPI
  57. NetpParmsUserPropertyFree (
  58. LPWSTR NewUserParms
  59. );
  60. //////////
  61. // Concatenates two BSTR's and returns the result. The caller is responsible
  62. // for freeing the returned string.
  63. //////////
  64. BSTR
  65. WINAPI
  66. ConcatentateBSTRs(
  67. IN CONST OLECHAR *bstr1,
  68. IN CONST OLECHAR *bstr2
  69. )
  70. {
  71. UINT len1, len2;
  72. BSTR retval;
  73. // Compute the lengths of the two strings.
  74. len1 = bstr1 ? SysStringByteLen((BSTR)bstr1) : 0;
  75. len2 = bstr2 ? SysStringByteLen((BSTR)bstr2) : 0;
  76. // Allocate memory for the result.
  77. retval = SysAllocStringByteLen(NULL, len1 + len2);
  78. if (retval)
  79. {
  80. // Copy in the first string.
  81. if (bstr1)
  82. {
  83. memcpy(retval, bstr1, len1 + sizeof(WCHAR));
  84. }
  85. // Copy in the second string.
  86. if (bstr2)
  87. {
  88. memcpy((PBYTE)retval + len1, bstr2, len2 + sizeof(WCHAR));
  89. }
  90. }
  91. return retval;
  92. }
  93. //////////
  94. // Saves a single-valued VARIANT (i.e., not a SAFEARRAY) to a string.
  95. //////////
  96. HRESULT
  97. WINAPI
  98. SaveSingleVariantToString(
  99. IN CONST VARIANT *pvarSrc,
  100. OUT BSTR *pbstrDest
  101. )
  102. {
  103. HRESULT hr;
  104. VARIANT v;
  105. UINT len;
  106. OLECHAR tag[18]; // 5 + 1 + 10 + 1 + 1
  107. // Coerce the VARIANT to a BSTR.
  108. VariantInit(&v);
  109. hr = IASVariantChangeType(
  110. &v,
  111. (LPVARIANT)pvarSrc,
  112. 0,
  113. VT_BSTR
  114. );
  115. if (FAILED(hr)) { return hr; }
  116. // Compute the length of the header and the data.
  117. len = SysStringLen(V_BSTR(&v));
  118. len += swprintf(tag, L"%hu:%lu:", V_VT(pvarSrc), len);
  119. // Allocate the result string.
  120. *pbstrDest = SysAllocStringLen(NULL, len);
  121. if (*pbstrDest != NULL)
  122. {
  123. // Copy in the tag and the data.
  124. wcscat(wcscpy(*pbstrDest, tag), V_BSTR(&v));
  125. }
  126. else
  127. {
  128. hr = E_OUTOFMEMORY;
  129. }
  130. // Clear the intermediate string.
  131. VariantClear(&v);
  132. return hr;
  133. }
  134. //////////
  135. // Loads a single-valued VARIANT (i.e., not a SAFEARRAY) from a string.
  136. // Also returns a pointer to where the scan stopped.
  137. //////////
  138. HRESULT
  139. WINAPI
  140. LoadSingleVariantFromString(
  141. IN PCWSTR pszSrc,
  142. IN UINT cSrcLen,
  143. OUT VARIANT *pvarDest,
  144. OUT PCWSTR *ppszEnd
  145. )
  146. {
  147. PCWSTR nptr;
  148. VARTYPE vt;
  149. PWSTR endptr;
  150. ULONG len;
  151. VARIANT v;
  152. HRESULT hr;
  153. // Initialize the cursor.
  154. nptr = pszSrc;
  155. // Read the VARTYPE token.
  156. vt = (VARTYPE)wcstoul(nptr, &endptr, 10);
  157. if (endptr == nptr || *endptr != L':') { return E_INVALIDARG; }
  158. nptr = endptr + 1;
  159. // Read the length token.
  160. len = wcstoul(nptr, &endptr, 10);
  161. if (endptr == nptr || *endptr != L':') { return E_INVALIDARG; }
  162. nptr = endptr + 1;
  163. // Make sure there's enough characters left for the data.
  164. if (nptr + len > pszSrc + cSrcLen) { return E_INVALIDARG; }
  165. // Read the BSTR data into a VARIANT.
  166. V_VT(&v) = VT_BSTR;
  167. V_BSTR(&v) = SysAllocStringLen(nptr, len);
  168. if (V_BSTR(&v) == NULL) { return E_OUTOFMEMORY; }
  169. // Coerce the VARIANT to the desired type.
  170. hr = IASVariantChangeType(
  171. pvarDest,
  172. &v,
  173. 0,
  174. vt
  175. );
  176. // Clear the intermediate string.
  177. VariantClear(&v);
  178. // Return the position where the scan stopped.
  179. *ppszEnd = nptr + len;
  180. return hr;
  181. }
  182. //////////
  183. // Saves a VARIANT to a string. The caller is responsible for freeing the
  184. // returned string.
  185. //////////
  186. HRESULT
  187. WINAPI
  188. IASSaveVariantToString(
  189. IN CONST VARIANT *pvarSrc,
  190. OUT BSTR *pbstrDest
  191. )
  192. {
  193. HRESULT hr;
  194. SAFEARRAY *psa;
  195. LONG lowerBound, upperBound, idx;
  196. VARIANT *data;
  197. BSTR item, newResult;
  198. // Check the input arguments.
  199. if (pvarSrc == NULL || pbstrDest == NULL) { return E_POINTER; }
  200. // Initialize the return parameter.
  201. *pbstrDest = NULL;
  202. // Is this an array ?
  203. if (V_VT(pvarSrc) != (VT_VARIANT | VT_ARRAY))
  204. {
  205. // No, so we can delegate and bail.
  206. return SaveSingleVariantToString(pvarSrc, pbstrDest);
  207. }
  208. // Yes, so extract the SAFEARRAY.
  209. psa = V_ARRAY(pvarSrc);
  210. // We only handle one-dimensional arrays.
  211. if (SafeArrayGetDim(psa) != 1) { return DISP_E_TYPEMISMATCH; }
  212. // Get the array bounds.
  213. hr = SafeArrayGetLBound(psa, 1, &lowerBound);
  214. if (FAILED(hr)) { return hr; }
  215. hr = SafeArrayGetUBound(psa, 1, &upperBound);
  216. if (FAILED(hr)) { return hr; }
  217. // Get the embedded array of VARIANTs.
  218. hr = SafeArrayAccessData(psa, (PVOID*)&data);
  219. // Loop through each VARIANT in the array.
  220. for (idx = lowerBound; idx <= upperBound; ++idx, ++data)
  221. {
  222. // Save the VARIANT into a BSTR.
  223. hr = SaveSingleVariantToString(data, &item);
  224. if (FAILED(hr)) { break; }
  225. // Merge this into the result ...
  226. newResult = ConcatentateBSTRs(*pbstrDest, item);
  227. // ... and free the old strings.
  228. SysFreeString(*pbstrDest);
  229. SysFreeString(item);
  230. // Store the new result.
  231. *pbstrDest = newResult;
  232. if (!newResult)
  233. {
  234. hr = E_OUTOFMEMORY;
  235. break;
  236. }
  237. }
  238. // If anything went wrong, clean-up the partial result.
  239. if (FAILED(hr))
  240. {
  241. SysFreeString(*pbstrDest);
  242. *pbstrDest = NULL;
  243. }
  244. // Unlock the array.
  245. SafeArrayUnaccessData(psa);
  246. return hr;
  247. }
  248. //////////
  249. // Loads a VARIANT from a string. The caller is responsible for freeing the
  250. // returned VARIANT.
  251. //////////
  252. HRESULT
  253. WINAPI
  254. IASLoadVariantFromString(
  255. IN PCWSTR pszSrc,
  256. IN UINT cSrcLen,
  257. OUT VARIANT *pvarDest
  258. )
  259. {
  260. PCWSTR end;
  261. HRESULT hr;
  262. SAFEARRAYBOUND bound;
  263. SAFEARRAY *psa;
  264. LONG index;
  265. VARIANT* item;
  266. // Check the parameters.
  267. if (pszSrc == NULL || pvarDest == NULL) { return E_POINTER; }
  268. // Initialize the out parameter.
  269. VariantInit(pvarDest);
  270. // Compute the end of the buffer.
  271. end = pszSrc + cSrcLen;
  272. // Go for the quick score on a single-valued property.
  273. hr = LoadSingleVariantFromString(
  274. pszSrc,
  275. cSrcLen,
  276. pvarDest,
  277. &pszSrc
  278. );
  279. if (FAILED(hr) || pszSrc == end) { return hr; }
  280. // Create a SAFEARRAY of VARIANTs to hold the array elements.
  281. // We know we have at least two elements.
  282. bound.cElements = 2;
  283. bound.lLbound = 0;
  284. psa = SafeArrayCreate(VT_VARIANT, 1, &bound);
  285. if (psa == NULL)
  286. {
  287. VariantClear(pvarDest);
  288. return E_OUTOFMEMORY;
  289. }
  290. // Store the VARIANT we already converted.
  291. index = 0;
  292. SafeArrayPtrOfIndex(psa, &index, (PVOID*)&item);
  293. memcpy(item, pvarDest, sizeof(VARIANT));
  294. // Now put the SAFEARRAY into the returned VARIANT.
  295. V_VT(pvarDest) = VT_ARRAY | VT_VARIANT;
  296. V_ARRAY(pvarDest) = psa;
  297. do
  298. {
  299. // Get the next element in the array.
  300. ++index;
  301. hr = SafeArrayPtrOfIndex(psa, &index, (PVOID*)&item);
  302. if (FAILED(hr)) { break; }
  303. // Load the next value.
  304. hr = LoadSingleVariantFromString(
  305. pszSrc,
  306. (UINT)(end - pszSrc),
  307. item,
  308. &pszSrc
  309. );
  310. if (FAILED(hr) || pszSrc == end) { break; }
  311. // We must have at least one more element, so grow the array.
  312. ++bound.cElements;
  313. hr = SafeArrayRedim(psa, &bound);
  314. } while (SUCCEEDED(hr));
  315. // If we failed, clean-up any partial results.
  316. if (FAILED(hr)) { VariantClear(pvarDest); }
  317. return hr;
  318. }
  319. HRESULT
  320. WINAPI
  321. IASParmsSetUserProperty(
  322. IN PCWSTR pszUserParms,
  323. IN PCWSTR pszName,
  324. IN CONST VARIANT *pvarValue,
  325. OUT PWSTR *ppszNewUserParms
  326. )
  327. {
  328. BSTR bstrValue;
  329. UNICODE_STRING uniValue;
  330. NTSTATUS status;
  331. HRESULT hr;
  332. BOOL update;
  333. // Check the parameters.
  334. if (pvarValue == NULL || ppszNewUserParms == NULL) { return E_POINTER; }
  335. // Initialize the out parameter.
  336. *ppszNewUserParms = NULL;
  337. // Is the VARIANT empty ?
  338. if (V_VT(pvarValue) != VT_EMPTY)
  339. {
  340. // No, so save it to a string.
  341. hr = IASSaveVariantToString(
  342. pvarValue,
  343. &bstrValue
  344. );
  345. if (FAILED(hr)) { return hr; }
  346. RtlInitUnicodeString(&uniValue, bstrValue);
  347. }
  348. else
  349. {
  350. // Yes, so we're actually going to erase the property.
  351. bstrValue = NULL;
  352. memset(&uniValue, 0, sizeof(UNICODE_STRING));
  353. }
  354. // Write the property to UserParms.
  355. status = NetpParmsSetUserProperty(
  356. (PWSTR)pszUserParms,
  357. (PWSTR)pszName,
  358. uniValue,
  359. 0,
  360. ppszNewUserParms,
  361. &update
  362. );
  363. if (NT_SUCCESS(status))
  364. {
  365. hr = S_OK;
  366. }
  367. else
  368. {
  369. status = RtlNtStatusToDosError(status);
  370. hr = HRESULT_FROM_WIN32(status);
  371. }
  372. // Free the BSTR value.
  373. SysFreeString(bstrValue);
  374. return hr;
  375. }
  376. HRESULT
  377. WINAPI
  378. IASParmsQueryUserProperty(
  379. IN PCWSTR pszUserParms,
  380. IN PCWSTR pszName,
  381. OUT VARIANT *pvarValue
  382. )
  383. {
  384. NTSTATUS status;
  385. HRESULT hr;
  386. WCHAR flag;
  387. UNICODE_STRING uniValue;
  388. // Check the parameters.
  389. if (pvarValue == NULL) { return E_POINTER; }
  390. // Initialize the out parameter.
  391. VariantInit(pvarValue);
  392. // Get the property from UserParms.
  393. status = NetpParmsQueryUserProperty(
  394. (PWSTR)pszUserParms,
  395. (PWSTR)pszName,
  396. &flag,
  397. &uniValue
  398. );
  399. if (NT_SUCCESS(status))
  400. {
  401. if (uniValue.Buffer != NULL)
  402. {
  403. // We got a string so convert it to a VARIANT ...
  404. hr = IASLoadVariantFromString(
  405. uniValue.Buffer,
  406. uniValue.Length / sizeof (WCHAR),
  407. pvarValue
  408. );
  409. // ... and free the string.
  410. LocalFree(uniValue.Buffer);
  411. }
  412. else
  413. {
  414. // Buffer is zero-length, so we return VT_EMPTY.
  415. hr = S_OK;
  416. }
  417. }
  418. else
  419. {
  420. status = RtlNtStatusToDosError(status);
  421. hr = HRESULT_FROM_WIN32(status);
  422. }
  423. return hr;
  424. }
  425. VOID
  426. WINAPI
  427. IASParmsFreeUserParms(
  428. IN PWSTR pszNewUserParms
  429. )
  430. {
  431. LocalFree(pszNewUserParms);
  432. }
  433. /////////
  434. // Constants used for compressing/decompressing phone numbers.
  435. /////////
  436. CONST WCHAR COMPRESS_MAP[] = L"() tTpPwW,-@*#";
  437. #define UNPACKED_DIGIT (100)
  438. #define COMPRESS_MAP_BEGIN (110)
  439. #define COMPRESS_MAP_END (COMPRESS_MAP_BEGIN + 14)
  440. #define UNPACKED_OTHER (COMPRESS_MAP_END + 1)
  441. ///////////////////////////////////////////////////////////////////////////////
  442. //
  443. // FUNCTION
  444. //
  445. // CompressPhoneNumber
  446. //
  447. // DESCRIPTION
  448. //
  449. // Bizarre algorithm used to compress phone numbers stored in the
  450. // usr_parms field.
  451. //
  452. ///////////////////////////////////////////////////////////////////////////////
  453. VOID
  454. WINAPI
  455. CompressPhoneNumber(
  456. IN PCWSTR uncompressed,
  457. OUT PWSTR compressed
  458. )
  459. {
  460. BOOL packed = FALSE;
  461. for( ; *uncompressed; ++uncompressed)
  462. {
  463. switch (*uncompressed)
  464. {
  465. case L'0':
  466. if (packed)
  467. {
  468. // Put zero as the second paired digit
  469. if (*compressed)
  470. {
  471. *compressed *= 10;
  472. ++compressed;
  473. packed = FALSE;
  474. }
  475. else
  476. {
  477. // We have a zero, we cant put a second zero or that
  478. // will be a null byte. So, we store the value
  479. // UNPACKED_DIGIT to fake this.
  480. *compressed = UNPACKED_DIGIT;
  481. *(++compressed) = 0;
  482. packed = TRUE;
  483. }
  484. }
  485. else
  486. {
  487. *compressed = 0;
  488. packed = TRUE;
  489. }
  490. break;
  491. case L'1':
  492. case L'2':
  493. case L'3':
  494. case L'4':
  495. case L'5':
  496. case L'6':
  497. case L'7':
  498. case L'8':
  499. case L'9':
  500. // If this is the second digit that is going to be
  501. // packed into one byte
  502. if (packed)
  503. {
  504. *compressed *= 10;
  505. *compressed += *uncompressed - L'0';
  506. // we need to special case number 32 which maps to a blank
  507. if (*compressed == L' ')
  508. {
  509. *compressed = COMPRESS_MAP_END;
  510. }
  511. ++compressed;
  512. packed = FALSE;
  513. }
  514. else
  515. {
  516. *compressed = *uncompressed - '0';
  517. packed = TRUE;
  518. }
  519. break;
  520. case L'(':
  521. case L')':
  522. case L' ':
  523. case L't':
  524. case L'T':
  525. case L'p':
  526. case L'P':
  527. case L'w':
  528. case L'W':
  529. case L',':
  530. case L'-':
  531. case L'@':
  532. case L'*':
  533. case L'#':
  534. // if the byte was packed then we unpack it
  535. if (packed)
  536. {
  537. *compressed += UNPACKED_DIGIT;
  538. ++compressed;
  539. packed = FALSE;
  540. }
  541. *compressed = (WCHAR)(COMPRESS_MAP_BEGIN +
  542. (wcschr(COMPRESS_MAP, *uncompressed) -
  543. COMPRESS_MAP));
  544. ++compressed;
  545. break;
  546. default:
  547. // if the chracter is none of the above specially recognized
  548. // characters then copy the value + UNPACKED_OTHER to make it
  549. // possible to decompress at the other end. [ 6/4/96 RamC ]
  550. if (packed)
  551. {
  552. *compressed += UNPACKED_DIGIT;
  553. ++compressed;
  554. packed = FALSE;
  555. }
  556. *compressed = *uncompressed + UNPACKED_OTHER;
  557. ++compressed;
  558. }
  559. }
  560. // If we are in the middle of packing something then we unpack it.
  561. if (packed)
  562. {
  563. *compressed += UNPACKED_DIGIT;
  564. ++compressed;
  565. }
  566. // Add the null terminator.
  567. *compressed = L'\0';
  568. }
  569. ///////////////////////////////////////////////////////////////////////////////
  570. //
  571. // FUNCTION
  572. //
  573. // DecompressPhoneNumber
  574. //
  575. // DESCRIPTION
  576. //
  577. // The inverse of CompressPhoneNumber above.
  578. //
  579. ///////////////////////////////////////////////////////////////////////////////
  580. VOID
  581. WINAPI
  582. DecompressPhoneNumber(
  583. IN PCWSTR compressed,
  584. OUT PWSTR decompressed
  585. )
  586. {
  587. for( ; *compressed; ++compressed, ++decompressed)
  588. {
  589. // If this character is packed, then we unpack it.
  590. if (*compressed < UNPACKED_DIGIT)
  591. {
  592. *decompressed = *compressed / 10 + L'0';
  593. ++decompressed;
  594. *decompressed = *compressed % 10 + L'0';
  595. continue;
  596. }
  597. // We need to special case number 32 which maps to a blank.
  598. if (*compressed == COMPRESS_MAP_END)
  599. {
  600. *decompressed = L'3';
  601. ++decompressed;
  602. *decompressed = L'2';
  603. continue;
  604. }
  605. // The character is an unpacked digit.
  606. if (*compressed < COMPRESS_MAP_BEGIN)
  607. {
  608. *decompressed = *compressed - UNPACKED_DIGIT + L'0';
  609. continue;
  610. }
  611. // The character is from the compression map.
  612. if (*compressed < UNPACKED_OTHER)
  613. {
  614. *decompressed = COMPRESS_MAP[*compressed - COMPRESS_MAP_BEGIN];
  615. continue;
  616. }
  617. // Otherwise the character is unpacked.
  618. *decompressed = *compressed - UNPACKED_OTHER;
  619. }
  620. // Add a null terminator.
  621. *decompressed = L'\0';
  622. }
  623. /////////
  624. // Definition of the downlevel UserParameters.
  625. /////////
  626. #define UP_CLIENT_MAC (L'm')
  627. #define UP_CLIENT_DIAL (L'd')
  628. #define UP_LEN_MAC (LM20_UNLEN)
  629. #define UP_LEN_DIAL (LM20_MAXCOMMENTSZ - 4 - UP_LEN_MAC)
  630. typedef struct {
  631. WCHAR up_MACid;
  632. WCHAR up_PriGrp[UP_LEN_MAC];
  633. WCHAR up_MAC_Terminator;
  634. WCHAR up_DIALid;
  635. WCHAR up_Privilege;
  636. WCHAR up_CBNum[UP_LEN_DIAL];
  637. } USER_PARMS;
  638. #define USER_PARMS_LEN (sizeof(USER_PARMS)/sizeof(WCHAR))
  639. ///////////////////////////////////////////////////////////////////////////////
  640. //
  641. // FUNCTION
  642. //
  643. // InitUserParms
  644. //
  645. // DESCRIPTION
  646. //
  647. // Initializes a USER_PARMS struct to a valid default state.
  648. //
  649. ///////////////////////////////////////////////////////////////////////////////
  650. VOID
  651. WINAPI
  652. InitUserParms(
  653. IN USER_PARMS* userParms
  654. )
  655. {
  656. WCHAR *i, *end;
  657. // Set everything to a space ' '.
  658. i = (PWCHAR)userParms;
  659. end = i + USER_PARMS_LEN;
  660. for ( ; i != end; ++i)
  661. {
  662. *i = L' ';
  663. }
  664. // Initialize the 'special' fields.
  665. userParms->up_MACid = UP_CLIENT_MAC;
  666. userParms->up_PriGrp[0] = L':';
  667. userParms->up_DIALid = UP_CLIENT_DIAL;
  668. userParms->up_Privilege = RASPRIV_NoCallback;
  669. }
  670. ///////////////////////////////////////////////////////////////////////////////
  671. //
  672. // FUNCTION
  673. //
  674. // IASParmsSetRasUser0
  675. //
  676. // DESCRIPTION
  677. //
  678. // Encodes the RAS_USER_0 struct into the downlevel portion of the
  679. // UserParameters string.
  680. //
  681. ///////////////////////////////////////////////////////////////////////////////
  682. DWORD
  683. WINAPI
  684. IASParmsSetRasUser0(
  685. IN OPTIONAL PCWSTR pszOldUserParms,
  686. IN CONST RAS_USER_0* pRasUser0,
  687. OUT PWSTR* ppszNewUserParms
  688. )
  689. {
  690. size_t oldLen, newLen, compressedLen;
  691. USER_PARMS userParms;
  692. WCHAR compressed[MAX_PHONE_NUMBER_LEN + 1];
  693. // Check the pointers.
  694. if (pRasUser0 == NULL || ppszNewUserParms == NULL)
  695. {
  696. return ERROR_INVALID_PARAMETER;
  697. }
  698. // Initialize the out parameters.
  699. *ppszNewUserParms = NULL;
  700. // Determine the length of the old UserParameters.
  701. oldLen = pszOldUserParms ? wcslen(pszOldUserParms) : 0;
  702. // Initialize the USER_PARMS structure.
  703. InitUserParms(&userParms);
  704. // Preserve the MAC Primary Group if present.
  705. if (oldLen > UP_LEN_MAC)
  706. {
  707. memcpy(
  708. userParms.up_PriGrp,
  709. pszOldUserParms + 1,
  710. sizeof(userParms.up_PriGrp)
  711. );
  712. }
  713. // Validate the CallbackType and save the compressed phone number.
  714. switch (pRasUser0->bfPrivilege & RASPRIV_CallbackType)
  715. {
  716. case RASPRIV_NoCallback:
  717. case RASPRIV_AdminSetCallback:
  718. case RASPRIV_CallerSetCallback:
  719. {
  720. // Compress the phone number.
  721. CompressPhoneNumber(pRasUser0->wszPhoneNumber, compressed);
  722. // Make sure it will fit in USER_PARMS.
  723. compressedLen = wcslen(compressed);
  724. if (compressedLen > UP_LEN_DIAL) { compressedLen = UP_LEN_DIAL; }
  725. // Store the compressed phone number.
  726. memcpy(userParms.up_CBNum, compressed, compressedLen * sizeof(WCHAR));
  727. break;
  728. }
  729. default:
  730. return ERROR_BAD_FORMAT;
  731. }
  732. // Store the privilege flags.
  733. userParms.up_Privilege = pRasUser0->bfPrivilege;
  734. // Allocate memory for the new UserParameters.
  735. newLen = max(oldLen, USER_PARMS_LEN);
  736. *ppszNewUserParms = (PWSTR)LocalAlloc(
  737. LMEM_FIXED,
  738. (newLen + 1) * sizeof(WCHAR)
  739. );
  740. if (*ppszNewUserParms == NULL) { return ERROR_NOT_ENOUGH_MEMORY; }
  741. // Copy in the USER_PARMS struct.
  742. memcpy(*ppszNewUserParms, &userParms, sizeof(USER_PARMS));
  743. // Copy in any extra stuff.
  744. if (oldLen > USER_PARMS_LEN)
  745. {
  746. memcpy(
  747. *ppszNewUserParms + USER_PARMS_LEN,
  748. pszOldUserParms + USER_PARMS_LEN,
  749. (oldLen - USER_PARMS_LEN) * sizeof(WCHAR)
  750. );
  751. }
  752. // Add the null terminator.
  753. *(*ppszNewUserParms + newLen) = L'\0';
  754. return NO_ERROR;
  755. }
  756. ///////////////////////////////////////////////////////////////////////////////
  757. //
  758. // FUNCTION
  759. //
  760. // IASParmsQueryRasUser0
  761. //
  762. // DESCRIPTION
  763. //
  764. // Decodes the RAS_USER_0 struct from the UserParameters string.
  765. //
  766. ///////////////////////////////////////////////////////////////////////////////
  767. DWORD
  768. WINAPI
  769. IASParmsQueryRasUser0(
  770. IN OPTIONAL PCWSTR pszUserParms,
  771. OUT PRAS_USER_0 pRasUser0
  772. )
  773. {
  774. USER_PARMS* usrp;
  775. WCHAR callbackNumber[UP_LEN_DIAL + 1], *p;
  776. // Check the pointers.
  777. if (pRasUser0 == NULL)
  778. {
  779. return ERROR_INVALID_PARAMETER;
  780. }
  781. // Cast the string buffer to a USER_PARMS struct.
  782. usrp = (USER_PARMS*)pszUserParms;
  783. // If parms is not properly initialized, default to no RAS privilege.
  784. if (!pszUserParms ||
  785. wcslen(pszUserParms) < USER_PARMS_LEN ||
  786. usrp->up_DIALid != UP_CLIENT_DIAL)
  787. {
  788. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  789. pRasUser0->wszPhoneNumber[0] = L'\0';
  790. return NO_ERROR;
  791. }
  792. // Make a local copy.
  793. memcpy(callbackNumber, usrp->up_CBNum, sizeof(WCHAR) * UP_LEN_DIAL);
  794. // Add a null terminator and null out any trailing blanks.
  795. p = callbackNumber + UP_LEN_DIAL;
  796. *p = L'\0';
  797. while (--p >= callbackNumber && *p == L' ') { *p = L'\0'; }
  798. // Sanity check the bfPrivilege field.
  799. switch(usrp->up_Privilege & RASPRIV_CallbackType)
  800. {
  801. case RASPRIV_NoCallback:
  802. case RASPRIV_AdminSetCallback:
  803. case RASPRIV_CallerSetCallback:
  804. {
  805. pRasUser0->bfPrivilege = (BYTE)usrp->up_Privilege;
  806. DecompressPhoneNumber(callbackNumber, pRasUser0->wszPhoneNumber);
  807. break;
  808. }
  809. default:
  810. {
  811. pRasUser0->bfPrivilege = RASPRIV_NoCallback;
  812. pRasUser0->wszPhoneNumber[0] = L'\0';
  813. }
  814. }
  815. return NO_ERROR;
  816. }