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.

1210 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. spdrutil.c
  5. Abstract:
  6. This module contains general utility and helper functions used by ASR
  7. in textmode Setup.
  8. Authors:
  9. Michael Peterson, Seagate Software (v-michpe) 13-May-1997
  10. Guhan Suriyanarayanan (guhans) 21-Aug-1999
  11. Environment:
  12. Textmode Setup, Kernel-mode.
  13. Revision History:
  14. 21-Aug-1999 guhans
  15. Code clean-up and re-write.
  16. 13-May-1997 v-michpe
  17. Initial implementation.
  18. --*/
  19. #include "spprecmp.h"
  20. #pragma hdrstop
  21. #define THIS_MODULE L"spdrutil.c"
  22. #define THIS_MODULE_CODE L"U"
  23. static const PCWSTR ASR_MOUNTED_DEVICES_KEY = L"\\registry\\machine\\SYSTEM\\MountedDevices";
  24. static const PCWSTR ASR_HKLM_SYSTEM_KEY = L"\\registry\\machine\\SYSTEM";
  25. #ifndef ULONGLONG_MAX
  26. #define ULONGLONG_MAX (0xFFFFFFFFFFFFFFFF)
  27. #endif
  28. //
  29. // Caller must free the string
  30. //
  31. PWSTR
  32. SpAsrGetRegionName(IN PDISK_REGION pRegion)
  33. {
  34. SpNtNameFromRegion(
  35. pRegion,
  36. (PWSTR) TemporaryBuffer,
  37. sizeof(TemporaryBuffer),
  38. PartitionOrdinalCurrent
  39. );
  40. return SpDupStringW((PWSTR)TemporaryBuffer);
  41. }
  42. ULONG
  43. SpAsrGetActualDiskSignature(IN ULONG DiskNumber)
  44. {
  45. PHARD_DISK pDisk = &HardDisks[DiskNumber];
  46. ULONG Signature = 0;
  47. if (PARTITION_STYLE_MBR == (PARTITION_STYLE) pDisk->DriveLayout.PartitionStyle) {
  48. Signature = pDisk->DriveLayout.Mbr.Signature;
  49. }
  50. return Signature;
  51. }
  52. ULONGLONG
  53. SpAsrConvertSectorsToMB(
  54. IN ULONGLONG SectorCount,
  55. IN ULONG BytesPerSector
  56. )
  57. {
  58. ULONGLONG mb = 1024 * 1024;
  59. if ((ULONGLONG) (SectorCount / mb) > (ULONGLONG) (ULONGLONG_MAX / BytesPerSector)) {
  60. //
  61. // This is strange. The sizeMB of the disk is too big to fit in 64-bits,
  62. // yet the SectorCount does. This implies that this disk has more than
  63. // 1 MB Per Sector. Since this is very improbable (disks commonly have 512
  64. // BytesPerSector today), we bail out with an internal error.
  65. //
  66. DbgFatalMesg((_asrerr, "SpAsrConvertSectorsToMB. Disk has too many sectors\n"));
  67. INTERNAL_ERROR((L"Disk has too many sectors\n")); // ok
  68. }
  69. return (ULONGLONG) ((SectorCount * BytesPerSector) / mb);
  70. }
  71. extern
  72. VOID
  73. SpDeleteStorageVolumes (
  74. IN HANDLE SysPrepRegHandle,
  75. IN DWORD ControlSetNumber
  76. );
  77. extern
  78. NTSTATUS
  79. SpGetCurrentControlSetNumber(
  80. IN HANDLE SystemHiveRoot,
  81. OUT PULONG Number
  82. );
  83. VOID
  84. SpAsrDeleteMountedDevicesKey(VOID)
  85. {
  86. NTSTATUS status;
  87. OBJECT_ATTRIBUTES objAttrib;
  88. UNICODE_STRING unicodeString;
  89. HANDLE keyHandle;
  90. //
  91. // Delete HKLM\SYSTEM\MountedDevices.
  92. //
  93. INIT_OBJA(&objAttrib, &unicodeString, ASR_MOUNTED_DEVICES_KEY);
  94. objAttrib.RootDirectory = NULL;
  95. status = ZwOpenKey(&keyHandle, KEY_ALL_ACCESS, &objAttrib);
  96. if(NT_SUCCESS(status)) {
  97. status = ZwDeleteKey(keyHandle);
  98. DbgStatusMesg((_asrinfo,
  99. "SpAsrDeleteMountedDevicesKey. DeleteKey [%ls] on the setup hive returned 0x%lx. \n",
  100. ASR_MOUNTED_DEVICES_KEY,
  101. status
  102. ));
  103. ZwClose(keyHandle);
  104. }
  105. else {
  106. DbgErrorMesg((_asrwarn,
  107. "SpAsrDeleteMountedDevicesKey. No [%ls] on the setup hive.\n",
  108. ASR_MOUNTED_DEVICES_KEY));
  109. }
  110. }
  111. PVOID
  112. SpAsrMemAlloc(
  113. ULONG Size,
  114. BOOLEAN IsErrorFatal
  115. )
  116. {
  117. PVOID ptr = SpMemAlloc(Size);
  118. if (ptr) {
  119. RtlZeroMemory(ptr, Size);
  120. }
  121. else { // allocation failed
  122. if (IsErrorFatal) {
  123. DbgFatalMesg((_asrerr,
  124. "SpAsrMemAlloc. Memory allocation failed, SpMemAlloc(%lu) returned NULL.\n",
  125. Size
  126. ));
  127. SpAsrRaiseFatalError(SP_SCRN_OUT_OF_MEMORY, L"Out of memory.");
  128. }
  129. else {
  130. DbgErrorMesg((_asrerr,
  131. "SpAsrMemAlloc. Memory allocation failed, SpMemAlloc(%lu) returned NULL. Continuing.\n",
  132. Size
  133. ));
  134. }
  135. }
  136. return ptr;
  137. }
  138. BOOLEAN
  139. SpAsrIsValidBootDrive(IN OUT PWSTR NtDir)
  140. /*
  141. Returns TRUE if NtDir starts with ?:\,
  142. where ? is between C and Z or c and z,
  143. and wcslen(NtDir) <= SpGetMaxNtDirLen().
  144. Converts the drive letter to uppercase.
  145. */
  146. {
  147. if (!NtDir ||
  148. wcslen(NtDir) > SpGetMaxNtDirLen()
  149. ) {
  150. return FALSE;
  151. }
  152. // convert drive-letter to upper-case
  153. if (NtDir[0] >= L'c' && NtDir[0] <= L'z') {
  154. NtDir[0] = NtDir[0] - L'a' + L'A';
  155. }
  156. // check drive letter
  157. if (NtDir[0] < L'C' || NtDir[0] > L'Z') {
  158. return FALSE;
  159. }
  160. // check " :\"
  161. if (NtDir[1] == L':' && NtDir[2] == L'\\') {
  162. return TRUE;
  163. }
  164. return FALSE;
  165. }
  166. BOOLEAN
  167. SpAsrIsBootPartitionRecord(IN ULONG CriticalPartitionFlag)
  168. {
  169. return (BOOLEAN) (CriticalPartitionFlag & ASR_PTN_MASK_BOOT);
  170. }
  171. BOOLEAN
  172. SpAsrIsSystemPartitionRecord(IN ULONG CriticalPartitionFlag)
  173. {
  174. return (BOOLEAN) (CriticalPartitionFlag & ASR_PTN_MASK_SYS);
  175. }
  176. // Fatal Error Routines
  177. // -guhans! Lots of code-repitition here, there must be a more efficient way.
  178. VOID
  179. SpAsrRaiseFatalError(
  180. IN ULONG ErrorCode,
  181. IN PWSTR KdPrintStr
  182. )
  183. /*++
  184. Routine:
  185. Terminate setup
  186. Returns:
  187. None.
  188. --*/
  189. {
  190. KdPrintEx((_asrerr, "SETUP: + %ws\n", KdPrintStr));
  191. SpStartScreen(ErrorCode,
  192. 3,
  193. HEADER_HEIGHT+1,
  194. FALSE,
  195. FALSE,
  196. DEFAULT_ATTRIBUTE);
  197. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,
  198. SP_STAT_F3_EQUALS_EXIT,
  199. 0);
  200. SpInputDrain();
  201. while(SpInputGetKeypress() != KEY_F3);
  202. SpDone(0, FALSE, TRUE);
  203. }
  204. VOID
  205. SpAsrRaiseFatalErrorWs(
  206. IN ULONG ErrorCode,
  207. IN PWSTR KdPrintStr,
  208. IN PWSTR MessageStr
  209. )
  210. {
  211. KdPrintEx((_asrerr, "SETUP: + %ws\n", KdPrintStr));
  212. SpStartScreen(ErrorCode,
  213. 3,
  214. HEADER_HEIGHT+1,
  215. FALSE,
  216. FALSE,
  217. DEFAULT_ATTRIBUTE,
  218. MessageStr
  219. );
  220. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE, SP_STAT_F3_EQUALS_EXIT, 0);
  221. SpInputDrain();
  222. while(SpInputGetKeypress() != KEY_F3);
  223. SpDone(0, FALSE, TRUE);
  224. }
  225. VOID
  226. SpAsrRaiseFatalErrorWsWs(
  227. IN ULONG ErrorCode,
  228. IN PWSTR KdPrintStr,
  229. IN PWSTR MessageStr1,
  230. IN PWSTR MessageStr2
  231. )
  232. {
  233. KdPrintEx((_asrerr, "SETUP: + %ws\n", KdPrintStr));
  234. SpStartScreen(ErrorCode,
  235. 3,
  236. HEADER_HEIGHT+1,
  237. FALSE,
  238. FALSE,
  239. DEFAULT_ATTRIBUTE,
  240. MessageStr1,
  241. MessageStr2
  242. );
  243. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE, SP_STAT_F3_EQUALS_EXIT, 0);
  244. SpInputDrain();
  245. while(SpInputGetKeypress() != KEY_F3);
  246. SpDone(0, FALSE, TRUE);
  247. }
  248. VOID
  249. SpAsrRaiseFatalErrorWsLu(
  250. IN ULONG ErrorCode,
  251. IN PWSTR KdPrintStr,
  252. IN PWSTR MessageStr,
  253. IN ULONG MessageVal
  254. )
  255. {
  256. KdPrintEx((_asrerr, "SETUP: + %ws\n", KdPrintStr));
  257. SpStartScreen(ErrorCode,
  258. 3,
  259. HEADER_HEIGHT+1,
  260. FALSE,
  261. FALSE,
  262. DEFAULT_ATTRIBUTE,
  263. MessageStr,
  264. MessageVal
  265. );
  266. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE, SP_STAT_F3_EQUALS_EXIT, 0);
  267. SpInputDrain();
  268. while(SpInputGetKeypress() != KEY_F3);
  269. SpDone(0, FALSE, TRUE);
  270. }
  271. VOID
  272. SpAsrRaiseFatalErrorLu(
  273. IN ULONG ErrorCode,
  274. IN PWSTR KdPrintStr,
  275. IN ULONG MessageVal
  276. )
  277. {
  278. KdPrintEx((_asrerr, "SETUP: + %ws\n", KdPrintStr));
  279. SpStartScreen(ErrorCode,
  280. 3,
  281. HEADER_HEIGHT+1,
  282. FALSE,
  283. FALSE,
  284. DEFAULT_ATTRIBUTE,
  285. MessageVal
  286. );
  287. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE, SP_STAT_F3_EQUALS_EXIT, 0);
  288. SpInputDrain();
  289. while(SpInputGetKeypress() != KEY_F3);
  290. SpDone(0, FALSE, TRUE);
  291. }
  292. VOID
  293. SpAsrRaiseFatalErrorLuLu(
  294. IN ULONG ErrorCode,
  295. IN PWSTR KdPrintStr,
  296. IN ULONG MessageVal1,
  297. IN ULONG MessageVal2
  298. )
  299. {
  300. KdPrintEx((_asrerr, "SETUP: + %ws\n", KdPrintStr));
  301. SpStartScreen(ErrorCode,
  302. 3,
  303. HEADER_HEIGHT+1,
  304. FALSE,
  305. FALSE,
  306. DEFAULT_ATTRIBUTE,
  307. MessageVal1,
  308. MessageVal2
  309. );
  310. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE, SP_STAT_F3_EQUALS_EXIT, 0);
  311. SpInputDrain();
  312. while(SpInputGetKeypress() != KEY_F3);
  313. SpDone(0, FALSE, TRUE);
  314. }
  315. #define ASCI_O 79
  316. #define ASCI_o 111
  317. //
  318. // SpAsrFileErrorRetryIgnoreAbort
  319. // Display an error screen if the file that we are trying to
  320. // copy already exists on target system. Allows user to
  321. // O = Over-write existing file
  322. // ESC = Skip this file (preserve existing file)
  323. // F3 = Exit from Setup
  324. //
  325. // Returns TRUE if the user chose overwrite
  326. // FALSE if the user chose skip
  327. // Does not return if the user hit ESC
  328. //
  329. BOOL
  330. SpAsrFileErrorDeleteSkipAbort(
  331. IN ULONG ErrorCode,
  332. IN PWSTR DestinationFile
  333. )
  334. {
  335. ULONG optionKeys[] = {KEY_F3, ASCI_ESC};
  336. ULONG mnemonicKeys[] = {MnemonicOverwrite, 0};
  337. ULONG *keysPtr;
  338. BOOL done = FALSE,
  339. overwriteFile = FALSE;
  340. while (!done) {
  341. SpStartScreen(
  342. ErrorCode,
  343. 3,
  344. HEADER_HEIGHT+1,
  345. FALSE,
  346. FALSE,
  347. DEFAULT_ATTRIBUTE,
  348. DestinationFile
  349. );
  350. keysPtr = optionKeys;
  351. SpDisplayStatusOptions(
  352. DEFAULT_STATUS_ATTRIBUTE,
  353. SP_STAT_O_EQUALS_OVERWRITE,
  354. SP_STAT_ESC_EQUALS_SKIP_FILE,
  355. SP_STAT_F3_EQUALS_EXIT,
  356. 0
  357. );
  358. SpInputDrain();
  359. switch(SpWaitValidKey(keysPtr,NULL,mnemonicKeys)) {
  360. case (MnemonicOverwrite | KEY_MNEMONIC):
  361. overwriteFile = TRUE;
  362. done = TRUE;
  363. break;
  364. case ASCI_ESC:
  365. overwriteFile = FALSE;
  366. done = TRUE;
  367. break;
  368. case KEY_F3:
  369. SpDone(0, FALSE, TRUE);
  370. break;
  371. }
  372. }
  373. return overwriteFile;
  374. }
  375. //
  376. // SpAsrFileErrorRetryIgnoreAbort
  377. // Display an error screen if the file could not be copied
  378. // over to the target system. Allows user to
  379. // ENTER = Retry
  380. // ESC = Skip this file and continue
  381. // F3 = Exit from Setup
  382. //
  383. // Returns TRUE if the user chose skip
  384. // FALSE if the user chose retry
  385. // Does not return if the user hit ESC
  386. //
  387. BOOL
  388. SpAsrFileErrorRetrySkipAbort(
  389. IN ULONG ErrorCode,
  390. IN PWSTR SourceFile,
  391. IN PWSTR Label,
  392. IN PWSTR Vendor,
  393. IN BOOL AllowSkip
  394. )
  395. {
  396. ULONG optionKeys[] = {KEY_F3, ASCI_CR, ASCI_ESC};
  397. ULONG mnemonicKeys[] = {0};
  398. ULONG *keysPtr;
  399. BOOL done = FALSE,
  400. skipFile = FALSE;
  401. while (!done) {
  402. SpStartScreen(
  403. ErrorCode,
  404. 3,
  405. HEADER_HEIGHT+1,
  406. FALSE,
  407. FALSE,
  408. DEFAULT_ATTRIBUTE,
  409. SourceFile,
  410. Label,
  411. Vendor);
  412. keysPtr = optionKeys;
  413. if (AllowSkip) {
  414. SpDisplayStatusOptions(
  415. DEFAULT_STATUS_ATTRIBUTE,
  416. SP_STAT_ENTER_EQUALS_RETRY,
  417. SP_STAT_ESC_EQUALS_SKIP_FILE,
  418. SP_STAT_F3_EQUALS_EXIT,
  419. 0);
  420. }
  421. else {
  422. SpDisplayStatusOptions(
  423. DEFAULT_STATUS_ATTRIBUTE,
  424. SP_STAT_ENTER_EQUALS_RETRY,
  425. SP_STAT_F3_EQUALS_EXIT,
  426. 0);
  427. }
  428. SpInputDrain();
  429. switch(SpWaitValidKey(keysPtr,NULL,mnemonicKeys)) {
  430. case ASCI_CR:
  431. skipFile = FALSE;
  432. done = TRUE;
  433. break;
  434. case ASCI_ESC:
  435. if (AllowSkip) {
  436. skipFile = TRUE;
  437. done = TRUE;
  438. }
  439. break;
  440. case KEY_F3:
  441. SpDone(0, FALSE, TRUE);
  442. break;
  443. }
  444. }
  445. return skipFile;
  446. }
  447. VOID
  448. SpAsrRaiseInternalError(
  449. IN PWSTR ModuleName,
  450. IN PWSTR ModuleCode,
  451. IN ULONG LineNumber,
  452. IN PWSTR KdPrintStr)
  453. {
  454. PWSTR TmpMsgBuf = SpAsrMemAlloc(4096 * sizeof(WCHAR), TRUE);
  455. swprintf(TmpMsgBuf, L"%ws%lu", ModuleCode, LineNumber);
  456. DbgFatalMesg((_asrerr,
  457. " Internal Error (%ws:%lu %ws) %ws\n",
  458. ModuleName,
  459. LineNumber,
  460. TmpMsgBuf,
  461. KdPrintStr
  462. ));
  463. SpAsrRaiseFatalErrorWs(SP_TEXT_DR_INTERNAL_ERROR,
  464. KdPrintStr,
  465. TmpMsgBuf
  466. );
  467. //
  468. // Never gets here
  469. //
  470. }
  471. ULONGLONG
  472. SpAsrStringToULongLong(
  473. IN PWSTR String,
  474. OUT PWCHAR *EndOfValue,
  475. IN unsigned Radix
  476. )
  477. {
  478. PWSTR p;
  479. BOOLEAN Negative;
  480. ULONGLONG Accum,v;
  481. WCHAR HighestDigitAllowed,HighestLetterAllowed;
  482. WCHAR c;
  483. //
  484. // Validate radix, 0 or 2-36.
  485. //
  486. if((Radix == 1) || (Radix > 36)) {
  487. if(EndOfValue) {
  488. *EndOfValue = String;
  489. }
  490. return(0);
  491. }
  492. p = String;
  493. //
  494. // Skip whitespace.
  495. //
  496. while(SpIsSpace(*p)) {
  497. p++;
  498. }
  499. //
  500. // First char may be a plus or minus.
  501. //
  502. Negative = FALSE;
  503. if(*p == L'-') {
  504. Negative = TRUE;
  505. p++;
  506. } else {
  507. if(*p == L'+') {
  508. p++;
  509. }
  510. }
  511. if(!Radix) {
  512. if(*p == L'0') {
  513. //
  514. // Octal number
  515. //
  516. Radix = 8;
  517. p++;
  518. if((*p == L'x') || (*p == L'X')) {
  519. //
  520. // hex number
  521. //
  522. Radix = 16;
  523. p++;
  524. }
  525. } else {
  526. Radix = 10;
  527. }
  528. }
  529. HighestDigitAllowed = (Radix < 10) ? L'0'+(WCHAR)(Radix-1) : L'9';
  530. HighestLetterAllowed = (Radix > 10) ? L'A'+(WCHAR)(Radix-11) : 0;
  531. Accum = 0;
  532. while(1) {
  533. c = *p;
  534. if((c >= L'0') && (c <= HighestDigitAllowed)) {
  535. v = c - L'0';
  536. } else {
  537. c = SpToUpper(c);
  538. if((c >= L'A') && (c <= HighestLetterAllowed)) {
  539. v = c - L'A' + 10;
  540. } else {
  541. break;
  542. }
  543. }
  544. Accum *= Radix;
  545. Accum += v;
  546. p++;
  547. }
  548. if(EndOfValue) {
  549. *EndOfValue = p;
  550. }
  551. return(Negative ? (0-Accum) : Accum);
  552. }
  553. LONGLONG
  554. SpAsrStringToLongLong(
  555. IN PWSTR String,
  556. OUT PWCHAR *EndOfValue,
  557. IN unsigned Radix
  558. )
  559. {
  560. PWSTR p;
  561. BOOLEAN Negative;
  562. LONGLONG Accum,v;
  563. WCHAR HighestDigitAllowed,HighestLetterAllowed;
  564. WCHAR c;
  565. //
  566. // Validate radix, 0 or 2-36.
  567. //
  568. if((Radix == 1) || (Radix > 36)) {
  569. if(EndOfValue) {
  570. *EndOfValue = String;
  571. }
  572. return(0);
  573. }
  574. p = String;
  575. //
  576. // Skip whitespace.
  577. //
  578. while(SpIsSpace(*p)) {
  579. p++;
  580. }
  581. //
  582. // First char may be a plus or minus.
  583. //
  584. Negative = FALSE;
  585. if(*p == L'-') {
  586. Negative = TRUE;
  587. p++;
  588. } else {
  589. if(*p == L'+') {
  590. p++;
  591. }
  592. }
  593. if(!Radix) {
  594. if(*p == L'0') {
  595. //
  596. // Octal number
  597. //
  598. Radix = 8;
  599. p++;
  600. if((*p == L'x') || (*p == L'X')) {
  601. //
  602. // hex number
  603. //
  604. Radix = 16;
  605. p++;
  606. }
  607. } else {
  608. Radix = 10;
  609. }
  610. }
  611. HighestDigitAllowed = (Radix < 10) ? L'0'+(WCHAR)(Radix-1) : L'9';
  612. HighestLetterAllowed = (Radix > 10) ? L'A'+(WCHAR)(Radix-11) : 0;
  613. Accum = 0;
  614. while(1) {
  615. c = *p;
  616. if((c >= L'0') && (c <= HighestDigitAllowed)) {
  617. v = c - L'0';
  618. } else {
  619. c = SpToUpper(c);
  620. if((c >= L'A') && (c <= HighestLetterAllowed)) {
  621. v = c - L'A' + 10;
  622. } else {
  623. break;
  624. }
  625. }
  626. Accum *= Radix;
  627. Accum += v;
  628. p++;
  629. }
  630. if(EndOfValue) {
  631. *EndOfValue = p;
  632. }
  633. return(Negative ? (0-Accum) : Accum);
  634. }
  635. ULONG
  636. SpAsrStringToULong(
  637. IN PWSTR String,
  638. OUT PWCHAR *EndOfValue,
  639. IN unsigned Radix
  640. )
  641. {
  642. PWSTR p;
  643. BOOLEAN Negative;
  644. ULONG Accum,v;
  645. WCHAR HighestDigitAllowed,HighestLetterAllowed;
  646. WCHAR c;
  647. //
  648. // Validate radix, 0 or 2-36.
  649. //
  650. if((Radix == 1) || (Radix > 36)) {
  651. if(EndOfValue) {
  652. *EndOfValue = String;
  653. }
  654. return(0);
  655. }
  656. p = String;
  657. //
  658. // Skip whitespace.
  659. //
  660. while(SpIsSpace(*p)) {
  661. p++;
  662. }
  663. //
  664. // First char may be a plus or minus.
  665. //
  666. Negative = FALSE;
  667. if(*p == L'-') {
  668. Negative = TRUE;
  669. p++;
  670. } else {
  671. if(*p == L'+') {
  672. p++;
  673. }
  674. }
  675. if(!Radix) {
  676. if(*p == L'0') {
  677. //
  678. // Octal number
  679. //
  680. Radix = 8;
  681. p++;
  682. if((*p == L'x') || (*p == L'X')) {
  683. //
  684. // hex number
  685. //
  686. Radix = 16;
  687. p++;
  688. }
  689. } else {
  690. Radix = 10;
  691. }
  692. }
  693. HighestDigitAllowed = (Radix < 10) ? L'0'+(WCHAR)(Radix-1) : L'9';
  694. HighestLetterAllowed = (Radix > 10) ? L'A'+(WCHAR)(Radix-11) : 0;
  695. Accum = 0;
  696. while(1) {
  697. c = *p;
  698. if((c >= L'0') && (c <= HighestDigitAllowed)) {
  699. v = c - L'0';
  700. } else {
  701. c = SpToUpper(c);
  702. if((c >= L'A') && (c <= HighestLetterAllowed)) {
  703. v = c - L'A' + 10;
  704. } else {
  705. break;
  706. }
  707. }
  708. Accum *= Radix;
  709. Accum += v;
  710. p++;
  711. }
  712. if(EndOfValue) {
  713. *EndOfValue = p;
  714. }
  715. return(Negative ? (0-Accum) : Accum);
  716. }
  717. USHORT
  718. SpAsrStringToUShort(
  719. IN PWSTR String,
  720. OUT PWCHAR *EndOfValue,
  721. IN USHORT Radix
  722. )
  723. {
  724. PWSTR p;
  725. BOOLEAN Negative;
  726. USHORT Accum,v;
  727. WCHAR HighestDigitAllowed,HighestLetterAllowed;
  728. WCHAR c;
  729. //
  730. // Validate radix, 0 or 2-36.
  731. //
  732. if((Radix == 1) || (Radix > 36)) {
  733. if(EndOfValue) {
  734. *EndOfValue = String;
  735. }
  736. return(0);
  737. }
  738. p = String;
  739. //
  740. // Skip whitespace.
  741. //
  742. while(SpIsSpace(*p)) {
  743. p++;
  744. }
  745. //
  746. // First char may be a plus or minus.
  747. //
  748. Negative = FALSE;
  749. if(*p == L'-') {
  750. Negative = TRUE;
  751. p++;
  752. } else {
  753. if(*p == L'+') {
  754. p++;
  755. }
  756. }
  757. if(!Radix) {
  758. if(*p == L'0') {
  759. //
  760. // Octal number
  761. //
  762. Radix = 8;
  763. p++;
  764. if((*p == L'x') || (*p == L'X')) {
  765. //
  766. // hex number
  767. //
  768. Radix = 16;
  769. p++;
  770. }
  771. } else {
  772. Radix = 10;
  773. }
  774. }
  775. HighestDigitAllowed = (Radix < 10) ? L'0'+(WCHAR)(Radix-1) : L'9';
  776. HighestLetterAllowed = (Radix > 10) ? L'A'+(WCHAR)(Radix-11) : 0;
  777. Accum = 0;
  778. while(1) {
  779. c = *p;
  780. if((c >= L'0') && (c <= HighestDigitAllowed)) {
  781. v = c - L'0';
  782. } else {
  783. c = SpToUpper(c);
  784. if((c >= L'A') && (c <= HighestLetterAllowed)) {
  785. v = c - L'A' + 10;
  786. } else {
  787. break;
  788. }
  789. }
  790. Accum *= Radix;
  791. Accum += v;
  792. p++;
  793. }
  794. if(EndOfValue) {
  795. *EndOfValue = p;
  796. }
  797. return(Negative ? (0-Accum) : Accum);
  798. }
  799. int
  800. SpAsrCharToInt(
  801. IN PWSTR String,
  802. OUT PWCHAR *EndOfValue,
  803. IN USHORT Radix
  804. )
  805. {
  806. PWSTR p;
  807. BOOLEAN Negative;
  808. USHORT Accum,v;
  809. WCHAR HighestDigitAllowed,HighestLetterAllowed;
  810. WCHAR c;
  811. //
  812. // Validate radix, 0 or 2-36.
  813. //
  814. if((Radix == 1) || (Radix > 36)) {
  815. if(EndOfValue) {
  816. *EndOfValue = String;
  817. }
  818. return(0);
  819. }
  820. p = String;
  821. //
  822. // Skip whitespace.
  823. //
  824. while(SpIsSpace(*p)) {
  825. p++;
  826. }
  827. //
  828. // First char may be a plus or minus.
  829. //
  830. Negative = FALSE;
  831. if(*p == L'-') {
  832. Negative = TRUE;
  833. p++;
  834. } else {
  835. if(*p == L'+') {
  836. p++;
  837. }
  838. }
  839. if(!Radix) {
  840. if(*p == L'0') {
  841. //
  842. // Octal number
  843. //
  844. Radix = 8;
  845. p++;
  846. if((*p == L'x') || (*p == L'X')) {
  847. //
  848. // hex number
  849. //
  850. Radix = 16;
  851. p++;
  852. }
  853. } else {
  854. Radix = 10;
  855. }
  856. }
  857. HighestDigitAllowed = (Radix < 10) ? L'0'+(WCHAR)(Radix-1) : L'9';
  858. HighestLetterAllowed = (Radix > 10) ? L'A'+(WCHAR)(Radix-11) : 0;
  859. Accum = 0;
  860. while(1) {
  861. c = *p;
  862. if((c >= L'0') && (c <= HighestDigitAllowed)) {
  863. v = c - L'0';
  864. } else {
  865. c = SpToUpper(c);
  866. if((c >= L'A') && (c <= HighestLetterAllowed)) {
  867. v = c - L'A' + 10;
  868. } else {
  869. break;
  870. }
  871. }
  872. Accum *= Radix;
  873. Accum += v;
  874. p++;
  875. }
  876. if(EndOfValue) {
  877. *EndOfValue = p;
  878. }
  879. return(Negative ? (0-Accum) : Accum);
  880. }
  881. PWSTR
  882. SpAsrHexStringToUChar (
  883. IN PWSTR String,
  884. OUT unsigned char * Number
  885. )
  886. /*++
  887. Routine Description:
  888. This routine converts the hex representation of a number into an
  889. unsigned char. The hex representation is assumed to be a full
  890. two characters long.
  891. Arguments:
  892. String - Supplies the hex representation of the number.
  893. Number - Returns the number converted from hex representation.
  894. Return Value:
  895. A pointer to the end of the hex representation is returned if the
  896. hex representation was successfully converted to an unsigned char.
  897. Otherwise, zero is returned, indicating that an error occured.
  898. --*/
  899. {
  900. WCHAR Result;
  901. int Count;
  902. Result = 0;
  903. for (Count = 0; Count < 2; Count++, String++) {
  904. if ((*String >= L'0') && (*String <= L'9')) {
  905. Result = (Result << 4) + *String - L'0';
  906. }
  907. else if ((*String >= L'A') && (*String <= L'F')) {
  908. Result = (Result << 4) + *String - L'A' + 10;
  909. }
  910. else if ((*String >= L'a') && (*String <= L'f')) {
  911. Result = (Result << 4) + *String - L'a' + 10;
  912. }
  913. }
  914. *Number = (unsigned char)Result;
  915. return String;
  916. }
  917. VOID
  918. SpAsrGuidFromString(
  919. IN OUT GUID* Guid,
  920. IN PWSTR GuidString
  921. )
  922. /*++
  923. Routine Description:
  924. Gets a GUID from a string
  925. Arguments:
  926. Guid - The GUID that holds string representation
  927. Buffer - The string version of the guid, in the form
  928. "%x-%x-%x-%x%x%x%x%x%x%x%x"
  929. Return Value:
  930. Returns the converted string version of the given GUID
  931. --*/
  932. {
  933. PWSTR Buffer = GuidString;
  934. int i = 0;
  935. if (Guid) {
  936. ZeroMemory(Guid, sizeof(GUID));
  937. }
  938. if (Guid && Buffer) {
  939. Guid->Data1 = SpAsrStringToULong(Buffer, NULL, 16);
  940. Buffer += 9;
  941. Guid->Data2 = SpAsrStringToUShort(Buffer, NULL, 16);
  942. Buffer += 5;
  943. Guid->Data3 = SpAsrStringToUShort(Buffer, NULL, 16);
  944. Buffer += 5;
  945. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[0]));
  946. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[1]));
  947. ++Buffer;
  948. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[2]));
  949. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[3]));
  950. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[4]));
  951. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[5]));
  952. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[6]));
  953. Buffer = SpAsrHexStringToUChar(Buffer,&(Guid->Data4[7]));
  954. }
  955. }
  956. BOOLEAN
  957. SpAsrIsZeroGuid(
  958. IN GUID * Guid
  959. )
  960. {
  961. GUID ZeroGuid;
  962. ZeroMemory(&ZeroGuid, sizeof(GUID));
  963. if (!memcmp(&ZeroGuid, Guid, sizeof(GUID))) {
  964. return TRUE;
  965. }
  966. return FALSE;
  967. }