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.

1521 lines
49 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. regutil.c
  5. Abstract:
  6. Utility routines for use by REGINI and REGDMP programs.
  7. Author:
  8. Steve Wood (stevewo) 10-Mar-92
  9. Revision History:
  10. --*/
  11. #include "regutil.h"
  12. #define RtlAllocateHeap(x,y,z) malloc(z)
  13. #define RtlFreeHeap(x,y,z) free(z)
  14. UNICODE_STRING RiOnKeyword;
  15. UNICODE_STRING RiYesKeyword;
  16. UNICODE_STRING RiTrueKeyword;
  17. UNICODE_STRING RiOffKeyword;
  18. UNICODE_STRING RiNoKeyword;
  19. UNICODE_STRING RiFalseKeyword;
  20. UNICODE_STRING RiDeleteKeyword;
  21. UNICODE_STRING RiRegKeyword;
  22. UNICODE_STRING RiRegNoneKeyword;
  23. UNICODE_STRING RiRegSzKeyword;
  24. UNICODE_STRING RiRegExpandSzKeyword;
  25. UNICODE_STRING RiRegDwordKeyword;
  26. UNICODE_STRING RiRegBinaryKeyword;
  27. UNICODE_STRING RiRegBinaryFileKeyword;
  28. UNICODE_STRING RiRegLinkKeyword;
  29. UNICODE_STRING RiRegMultiSzKeyword;
  30. UNICODE_STRING RiRegMultiSzFileKeyword;
  31. UNICODE_STRING RiRegDateKeyword;
  32. void
  33. RegInitialize( void )
  34. {
  35. RtlInitUnicodeString( &RiOnKeyword, L"ON" );
  36. RtlInitUnicodeString( &RiYesKeyword, L"YES" );
  37. RtlInitUnicodeString( &RiTrueKeyword, L"TRUE" );
  38. RtlInitUnicodeString( &RiOffKeyword, L"OFF" );
  39. RtlInitUnicodeString( &RiNoKeyword, L"NO" );
  40. RtlInitUnicodeString( &RiFalseKeyword, L"FALSE" );
  41. RtlInitUnicodeString( &RiDeleteKeyword, L"DELETE" );
  42. RtlInitUnicodeString( &RiRegKeyword, L"REG_" );
  43. RtlInitUnicodeString( &RiRegNoneKeyword, L"REG_NONE" );
  44. RtlInitUnicodeString( &RiRegSzKeyword, L"REG_SZ" );
  45. RtlInitUnicodeString( &RiRegExpandSzKeyword, L"REG_EXPAND_SZ" );
  46. RtlInitUnicodeString( &RiRegDwordKeyword, L"REG_DWORD" );
  47. RtlInitUnicodeString( &RiRegBinaryKeyword, L"REG_BINARY" );
  48. RtlInitUnicodeString( &RiRegBinaryFileKeyword, L"REG_BINARYFILE" );
  49. RtlInitUnicodeString( &RiRegLinkKeyword, L"REG_LINK" );
  50. RtlInitUnicodeString( &RiRegMultiSzKeyword, L"REG_MULTI_SZ" );
  51. RtlInitUnicodeString( &RiRegMultiSzFileKeyword, L"REG_MULTISZFILE" );
  52. RtlInitUnicodeString( &RiRegDateKeyword, L"REG_DATE" );
  53. }
  54. NTSTATUS
  55. RegReadMultiSzFile(
  56. IN PUNICODE_STRING FileName,
  57. OUT PVOID *ValueBuffer,
  58. OUT PULONG ValueLength
  59. )
  60. {
  61. NTSTATUS Status;
  62. UNICODE_STRING NtFileName;
  63. PWSTR s;
  64. UNICODE_STRING MultiSource;
  65. UNICODE_STRING MultiValue;
  66. REG_UNICODE_FILE MultiSzFile;
  67. ULONG MultiSzFileSize;
  68. FileName->Buffer[ FileName->Length/sizeof(WCHAR) ] = UNICODE_NULL;
  69. RtlDosPathNameToNtPathName_U( FileName->Buffer,
  70. &NtFileName,
  71. NULL,
  72. NULL );
  73. Status = RegLoadAsciiFileAsUnicode( &NtFileName, &MultiSzFile );
  74. if (!NT_SUCCESS( Status )) {
  75. return( Status );
  76. }
  77. MultiSzFileSize = (MultiSzFile.EndOfFile -
  78. MultiSzFile.NextLine) * sizeof(WCHAR);
  79. *ValueLength = 0;
  80. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0,
  81. MultiSzFileSize);
  82. MultiSource.Buffer = MultiSzFile.NextLine;
  83. if (MultiSzFileSize <= MAXUSHORT) {
  84. MultiSource.Length =
  85. MultiSource.MaximumLength = (USHORT)MultiSzFileSize;
  86. } else {
  87. MultiSource.Length =
  88. MultiSource.MaximumLength = MAXUSHORT;
  89. }
  90. while (RegGetMultiString(&MultiSource, &MultiValue)) {
  91. RtlMoveMemory( (PUCHAR)*ValueBuffer + *ValueLength,
  92. MultiValue.Buffer,
  93. MultiValue.Length );
  94. *ValueLength += MultiValue.Length;
  95. s = MultiSource.Buffer;
  96. while ( *s != L'"' &&
  97. *s != L',' &&
  98. ((s - MultiSource.Buffer) * sizeof(WCHAR)) <
  99. MultiSource.Length ) s++;
  100. if ( ((s - MultiSource.Buffer) * sizeof(WCHAR)) ==
  101. MultiSource.Length ||
  102. *s == L',' ||
  103. *s == L';' ) {
  104. ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] =
  105. UNICODE_NULL;
  106. *ValueLength += sizeof(UNICODE_NULL);
  107. if ( *s == L';' ) {
  108. break;
  109. }
  110. }
  111. if ( (MultiSzFile.EndOfFile - MultiSource.Buffer) * sizeof(WCHAR) >=
  112. MAXUSHORT ) {
  113. MultiSource.Length =
  114. MultiSource.MaximumLength = MAXUSHORT;
  115. } else {
  116. MultiSource.Length =
  117. MultiSource.MaximumLength =
  118. (USHORT)((MultiSzFile.EndOfFile - MultiSource.Buffer) *
  119. sizeof(WCHAR));
  120. }
  121. }
  122. ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL;
  123. *ValueLength += sizeof(UNICODE_NULL);
  124. // Virtual memory for reading of MultiSzFile freed at process
  125. // death?
  126. return( TRUE );
  127. }
  128. NTSTATUS
  129. RegReadBinaryFile(
  130. IN PUNICODE_STRING FileName,
  131. OUT PVOID *ValueBuffer,
  132. OUT PULONG ValueLength
  133. )
  134. {
  135. NTSTATUS Status;
  136. UNICODE_STRING NtFileName;
  137. OBJECT_ATTRIBUTES ObjectAttributes;
  138. IO_STATUS_BLOCK IoStatus;
  139. HANDLE File;
  140. FILE_STANDARD_INFORMATION FileInformation;
  141. WCHAR FileNameBuffer[ 256 ];
  142. PWSTR s;
  143. FileName->Buffer[ FileName->Length/sizeof(WCHAR) ] = UNICODE_NULL;
  144. wcscpy( FileNameBuffer, L"\\DosDevices\\" );
  145. s = wcscat( FileNameBuffer, FileName->Buffer );
  146. while (*s != UNICODE_NULL) {
  147. if (*s == L'/') {
  148. *s = L'\\';
  149. }
  150. s++;
  151. }
  152. RtlInitUnicodeString( &NtFileName, FileNameBuffer );
  153. InitializeObjectAttributes( &ObjectAttributes,
  154. &NtFileName,
  155. OBJ_CASE_INSENSITIVE,
  156. (HANDLE)NULL,
  157. NULL
  158. );
  159. Status = NtOpenFile( &File,
  160. SYNCHRONIZE | GENERIC_READ,
  161. &ObjectAttributes,
  162. &IoStatus,
  163. FILE_SHARE_DELETE |
  164. FILE_SHARE_READ |
  165. FILE_SHARE_WRITE,
  166. FILE_SYNCHRONOUS_IO_NONALERT |
  167. FILE_NON_DIRECTORY_FILE
  168. );
  169. if (!NT_SUCCESS( Status )) {
  170. return( Status );
  171. }
  172. Status = NtQueryInformationFile( File,
  173. &IoStatus,
  174. (PVOID)&FileInformation,
  175. sizeof( FileInformation ),
  176. FileStandardInformation
  177. );
  178. if (NT_SUCCESS( Status )) {
  179. if (FileInformation.EndOfFile.HighPart) {
  180. Status = STATUS_BUFFER_OVERFLOW;
  181. }
  182. }
  183. if (!NT_SUCCESS( Status )) {
  184. NtClose( File );
  185. return( Status );
  186. }
  187. *ValueLength = FileInformation.EndOfFile.LowPart;
  188. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, *ValueLength );
  189. if (*ValueBuffer == NULL) {
  190. Status = STATUS_NO_MEMORY;
  191. }
  192. if (NT_SUCCESS( Status )) {
  193. Status = NtReadFile( File,
  194. NULL,
  195. NULL,
  196. NULL,
  197. &IoStatus,
  198. *ValueBuffer,
  199. *ValueLength,
  200. NULL,
  201. NULL
  202. );
  203. if (NT_SUCCESS( Status )) {
  204. Status = IoStatus.Status;
  205. if (NT_SUCCESS( Status )) {
  206. if (IoStatus.Information != *ValueLength) {
  207. Status = STATUS_END_OF_FILE;
  208. }
  209. }
  210. }
  211. if (!NT_SUCCESS( Status )) {
  212. RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer );
  213. }
  214. }
  215. NtClose( File );
  216. return( Status );
  217. }
  218. NTSTATUS
  219. RegLoadAsciiFileAsUnicode(
  220. IN PUNICODE_STRING FileName,
  221. OUT PREG_UNICODE_FILE UnicodeFile
  222. )
  223. {
  224. NTSTATUS Status;
  225. OBJECT_ATTRIBUTES ObjectAttributes;
  226. IO_STATUS_BLOCK IoStatus;
  227. HANDLE File;
  228. FILE_BASIC_INFORMATION FileDateTimeInfo;
  229. FILE_STANDARD_INFORMATION FileInformation;
  230. ULONG BufferSize, i, i1, LineCount;
  231. PVOID BufferBase;
  232. PCHAR Src, Src1;
  233. PWSTR Dst;
  234. InitializeObjectAttributes( &ObjectAttributes,
  235. FileName,
  236. OBJ_CASE_INSENSITIVE,
  237. (HANDLE)NULL,
  238. NULL
  239. );
  240. Status = NtOpenFile( &File,
  241. SYNCHRONIZE | GENERIC_READ,
  242. &ObjectAttributes,
  243. &IoStatus,
  244. FILE_SHARE_DELETE |
  245. FILE_SHARE_READ |
  246. FILE_SHARE_WRITE,
  247. FILE_SYNCHRONOUS_IO_NONALERT |
  248. FILE_NON_DIRECTORY_FILE
  249. );
  250. if (!NT_SUCCESS( Status )) {
  251. return( Status );
  252. }
  253. Status = NtQueryInformationFile( File,
  254. &IoStatus,
  255. (PVOID)&FileInformation,
  256. sizeof( FileInformation ),
  257. FileStandardInformation
  258. );
  259. if (NT_SUCCESS( Status )) {
  260. if (FileInformation.EndOfFile.HighPart) {
  261. Status = STATUS_BUFFER_OVERFLOW;
  262. }
  263. }
  264. if (!NT_SUCCESS( Status )) {
  265. NtClose( File );
  266. return( Status );
  267. }
  268. BufferSize = FileInformation.EndOfFile.LowPart * sizeof( WCHAR );
  269. BufferSize += sizeof( UNICODE_NULL );
  270. BufferBase = NULL;
  271. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  272. (PVOID *)&BufferBase,
  273. 0,
  274. &BufferSize,
  275. MEM_COMMIT,
  276. PAGE_READWRITE
  277. );
  278. if (NT_SUCCESS( Status )) {
  279. Src = (PCHAR)BufferBase + ((FileInformation.EndOfFile.LowPart+1) & ~1);
  280. Dst = (PWSTR)BufferBase;
  281. Status = NtReadFile( File,
  282. NULL,
  283. NULL,
  284. NULL,
  285. &IoStatus,
  286. Src,
  287. FileInformation.EndOfFile.LowPart,
  288. NULL,
  289. NULL
  290. );
  291. if (NT_SUCCESS( Status )) {
  292. Status = IoStatus.Status;
  293. if (NT_SUCCESS( Status )) {
  294. if (IoStatus.Information != FileInformation.EndOfFile.LowPart) {
  295. Status = STATUS_END_OF_FILE;
  296. }
  297. else {
  298. Status = NtQueryInformationFile( File,
  299. &IoStatus,
  300. (PVOID)&FileDateTimeInfo,
  301. sizeof( FileDateTimeInfo ),
  302. FileBasicInformation
  303. );
  304. }
  305. }
  306. }
  307. if (!NT_SUCCESS( Status )) {
  308. NtFreeVirtualMemory( NtCurrentProcess(),
  309. (PVOID *)&BufferBase,
  310. &BufferSize,
  311. MEM_RELEASE
  312. );
  313. }
  314. }
  315. NtClose( File );
  316. if (!NT_SUCCESS( Status )) {
  317. return( Status );
  318. }
  319. i = 0;
  320. while (i < FileInformation.EndOfFile.LowPart) {
  321. if (i > 1 && (Src[-2] == ' ' || Src[-2] == '\t') &&
  322. Src[-1] == '\\' && (*Src == '\r' || *Src == '\n')
  323. ) {
  324. if (Dst[-1] == L'\\') {
  325. --Dst;
  326. }
  327. while (Dst > (PWSTR)BufferBase) {
  328. if (Dst[-1] > L' ') {
  329. break;
  330. }
  331. Dst--;
  332. }
  333. LineCount = 0;
  334. while (i < FileInformation.EndOfFile.LowPart) {
  335. if (*Src == '\n') {
  336. i++;
  337. Src++;
  338. LineCount++;
  339. }
  340. else
  341. if (*Src == '\r' &&
  342. (i+1) < FileInformation.EndOfFile.LowPart &&
  343. Src[ 1 ] == '\n'
  344. ) {
  345. i += 2;
  346. Src += 2;
  347. LineCount++;
  348. }
  349. else {
  350. break;
  351. }
  352. }
  353. if (LineCount > 1) {
  354. *Dst++ = L'\n';
  355. }
  356. else {
  357. *Dst++ = L' ';
  358. while (i < FileInformation.EndOfFile.LowPart && (*Src == ' ' || *Src == '\t')) {
  359. i++;
  360. Src++;
  361. }
  362. }
  363. if (i >= FileInformation.EndOfFile.LowPart) {
  364. break;
  365. }
  366. }
  367. else
  368. if ((*Src == '\r' && Src[1] == '\n') || *Src == '\n') {
  369. while (TRUE) {
  370. while (i < FileInformation.EndOfFile.LowPart && (*Src == '\r' || *Src == '\n')) {
  371. i++;
  372. Src++;
  373. }
  374. Src1 = Src;
  375. i1 = i;
  376. while (i1 < FileInformation.EndOfFile.LowPart && (*Src1 == ' ' || *Src1 == '\t')) {
  377. i1++;
  378. Src1++;
  379. }
  380. if (i1 < FileInformation.EndOfFile.LowPart &&
  381. (*Src1 == '\r' && Src1[1] == '\n') || *Src1 == '\n'
  382. ) {
  383. Src = Src1;
  384. i = i1;
  385. }
  386. else {
  387. break;
  388. }
  389. }
  390. *Dst++ = L'\n';
  391. }
  392. else {
  393. i++;
  394. *Dst++ = RtlAnsiCharToUnicodeChar( &Src );
  395. }
  396. }
  397. if (NT_SUCCESS( Status )) {
  398. *Dst = UNICODE_NULL;
  399. UnicodeFile->FileContents = BufferBase;
  400. UnicodeFile->EndOfFile = Dst;
  401. UnicodeFile->BeginLine = NULL;
  402. UnicodeFile->EndOfLine = NULL;
  403. UnicodeFile->NextLine = BufferBase;
  404. UnicodeFile->LastWriteTime = FileDateTimeInfo.LastWriteTime;
  405. }
  406. else {
  407. NtFreeVirtualMemory( NtCurrentProcess(),
  408. (PVOID *)&BufferBase,
  409. &BufferSize,
  410. MEM_RELEASE
  411. );
  412. }
  413. return( Status );
  414. }
  415. BOOLEAN
  416. RegGetNextLine(
  417. IN OUT PREG_UNICODE_FILE UnicodeFile,
  418. OUT PULONG IndentAmount,
  419. OUT PWSTR *FirstEqual
  420. )
  421. {
  422. PWSTR s, s1;
  423. while (TRUE) {
  424. if (!(s = UnicodeFile->NextLine)) {
  425. return( FALSE );
  426. }
  427. *IndentAmount = 0;
  428. while (*s <= L' ') {
  429. if (*s == L' ') {
  430. *IndentAmount += 1;
  431. }
  432. else
  433. if (*s == L'\t') {
  434. *IndentAmount = ((*IndentAmount + 8) -
  435. (*IndentAmount % 8)
  436. );
  437. }
  438. if (++s >= UnicodeFile->EndOfFile) {
  439. return( FALSE );
  440. }
  441. }
  442. UnicodeFile->BeginLine = s;
  443. *FirstEqual = NULL;
  444. UnicodeFile->NextLine = NULL;
  445. while (s < UnicodeFile->EndOfFile) {
  446. if (*s == L'=') {
  447. if (*FirstEqual == NULL) {
  448. *FirstEqual = s;
  449. }
  450. }
  451. else
  452. if (*s == L'\n') {
  453. s1 = s;
  454. while (s > UnicodeFile->BeginLine && s[ -1 ] <= L' ') {
  455. s--;
  456. }
  457. UnicodeFile->EndOfLine = s;
  458. do {
  459. if (++s1 >= UnicodeFile->EndOfFile) {
  460. s1 = NULL;
  461. break;
  462. }
  463. }
  464. while (*s1 == L'\r' || *s1 == L'\n');
  465. UnicodeFile->NextLine = s1;
  466. break;
  467. }
  468. if (++s == UnicodeFile->EndOfFile) {
  469. break;
  470. }
  471. }
  472. if (UnicodeFile->EndOfLine > UnicodeFile->BeginLine) {
  473. if (DebugOutput) {
  474. fprintf( stderr, "%02u %.*ws\n",
  475. *IndentAmount,
  476. UnicodeFile->EndOfLine - UnicodeFile->BeginLine,
  477. UnicodeFile->BeginLine
  478. );
  479. }
  480. return( TRUE );
  481. }
  482. }
  483. return( FALSE );
  484. }
  485. void
  486. RegDumpKeyValue(
  487. FILE *fh,
  488. PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
  489. ULONG IndentLevel
  490. )
  491. {
  492. PULONG p;
  493. PWSTR pw, pw1;
  494. ULONG i, j, k, m, cbPrefix;
  495. UNICODE_STRING ValueName;
  496. PUCHAR pbyte;
  497. cbPrefix = fprintf( fh, "%.*s",
  498. IndentLevel,
  499. " "
  500. );
  501. ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]);
  502. ValueName.Length = (USHORT)KeyValueInformation->NameLength;
  503. ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
  504. if (ValueName.Length) {
  505. cbPrefix += fprintf( fh, "%wZ ", &ValueName );
  506. }
  507. cbPrefix += fprintf( fh, "= " );
  508. if (KeyValueInformation->DataLength == 0) {
  509. fprintf( fh, " [no data] \n");
  510. return;
  511. }
  512. switch( KeyValueInformation->Type ) {
  513. case REG_SZ:
  514. case REG_EXPAND_SZ:
  515. if (KeyValueInformation->Type == REG_EXPAND_SZ) {
  516. cbPrefix += fprintf( fh, "REG_EXPAND_SZ " );
  517. }
  518. pw = (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
  519. *(PWSTR)((PCHAR)pw + KeyValueInformation->DataLength) = UNICODE_NULL;
  520. i = 0;
  521. while (*pw) {
  522. if ((cbPrefix + wcslen(pw)) > 80) {
  523. pw1 = pw;
  524. while (*pw1 && *pw1 > L' ') {
  525. pw1++;
  526. }
  527. if (*pw1) {
  528. *pw1++ = UNICODE_NULL;
  529. while (*pw1 && *pw1 <= L' ') {
  530. pw1++;
  531. }
  532. }
  533. } else {
  534. pw1 = NULL;
  535. }
  536. if (i > 0) {
  537. fprintf( fh, " \\\n%.*s",
  538. cbPrefix,
  539. " "
  540. );
  541. }
  542. fprintf( fh, "%ws", pw );
  543. if (!pw1) {
  544. break;
  545. }
  546. i++;
  547. pw = pw1;
  548. }
  549. break;
  550. case REG_BINARY:
  551. fprintf( fh, "REG_BINARY 0x%08lx", KeyValueInformation->DataLength );
  552. p = (PULONG)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
  553. i = (KeyValueInformation->DataLength + 3) / sizeof( ULONG );
  554. if (!SummaryOutput || i <= 8) {
  555. for (j=0; j<i; j++) {
  556. if ((j % 8) == 0) {
  557. fprintf( fh, "\n%.*s",
  558. IndentLevel+4,
  559. " "
  560. );
  561. }
  562. fprintf( fh, "0x%08lx ", *p++ );
  563. }
  564. }
  565. else {
  566. fprintf( fh, " *** value display suppressed ***" );
  567. }
  568. fprintf( fh, "\n" );
  569. break;
  570. // case REG_DWORD_LITTLE_ENDIAN:
  571. case REG_DWORD:
  572. fprintf( fh, "REG_DWORD 0x%08lx",
  573. *((PULONG)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset))
  574. );
  575. break;
  576. case REG_DWORD_BIG_ENDIAN:
  577. fprintf( fh, "REG_DWORD_BIG_ENDIAN 0x%08lx",
  578. *((PULONG)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset))
  579. );
  580. break;
  581. case REG_LINK:
  582. fprintf( fh, "REG_LINK %ws",
  583. ((PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset))
  584. );
  585. break;
  586. case REG_MULTI_SZ:
  587. cbPrefix += fprintf( fh, "REG_MULTI_SZ " );
  588. pw = (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
  589. i = 0;
  590. if (*pw)
  591. while (i < ((KeyValueInformation->DataLength-1) / sizeof(WCHAR))) {
  592. if (i > 0) {
  593. fprintf( fh, " \\\n%.*s",
  594. cbPrefix,
  595. " "
  596. );
  597. }
  598. fprintf(fh, "\"%ws\" ",pw+i);
  599. do {
  600. ++i;
  601. } while ( pw[i] != UNICODE_NULL );
  602. ++i;
  603. }
  604. break;
  605. case REG_RESOURCE_LIST:
  606. case REG_FULL_RESOURCE_DESCRIPTOR:
  607. {
  608. PCM_RESOURCE_LIST ResourceList = ((PCM_RESOURCE_LIST)((PCHAR)KeyValueInformation +
  609. KeyValueInformation->DataOffset));
  610. PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
  611. PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor;
  612. ULONG k, l, count;
  613. PWSTR TypeName;
  614. PWSTR FlagName;
  615. ULONG Size = KeyValueInformation->DataLength;
  616. if (KeyValueInformation->Type == REG_RESOURCE_LIST) {
  617. fprintf( fh, " REG_RESOURCE_LIST\n");
  618. fprintf( fh, "%.*sNumber of Full resource Descriptors = %d",
  619. IndentLevel,
  620. " ",
  621. ResourceList->Count
  622. );
  623. count = ResourceList->Count;
  624. FullDescriptor = &ResourceList->List[0];
  625. } else {
  626. fprintf( fh, " REG_FULL_RESOURCE_DESCRIPTOR\n");
  627. count = 1;
  628. FullDescriptor = ((PCM_FULL_RESOURCE_DESCRIPTOR)
  629. ((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset));
  630. }
  631. for (i=0; i< count; i++) {
  632. fprintf( fh, "\n%.*sPartial List number %d\n",
  633. IndentLevel+4,
  634. " ",
  635. i
  636. );
  637. switch(FullDescriptor->InterfaceType) {
  638. case Internal: TypeName = L"Internal"; break;
  639. case Isa: TypeName = L"Isa"; break;
  640. case Eisa: TypeName = L"Eisa"; break;
  641. case MicroChannel: TypeName = L"MicroChannel"; break;
  642. case TurboChannel: TypeName = L"TurboChannel"; break;
  643. case PCIBus: TypeName = L"PCI"; break;
  644. case VMEBus: TypeName = L"VME"; break;
  645. case NuBus: TypeName = L"NuBus"; break;
  646. case PCMCIABus: TypeName = L"PCMCIA"; break;
  647. case CBus: TypeName = L"CBUS"; break;
  648. case MPIBus: TypeName = L"MPI"; break;
  649. default:
  650. TypeName = L"***invalid bus type***";
  651. break;
  652. }
  653. fprintf( fh, "%.*sINTERFACE_TYPE %ws\n",
  654. IndentLevel+8,
  655. " ",
  656. TypeName
  657. );
  658. fprintf( fh, "%.*sBUS_NUMBER %d\n",
  659. IndentLevel+8,
  660. " ",
  661. FullDescriptor->BusNumber
  662. );
  663. //
  664. // This is a basic test to see if the data format is right.
  665. // We know at least some video resource list are bogus ...
  666. //
  667. if (Size < FullDescriptor->PartialResourceList.Count *
  668. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) ) {
  669. fprintf( fh, "\n%.*s *** !!! Invalid ResourceList !!! *** \n",
  670. IndentLevel+8,
  671. " ",
  672. i
  673. );
  674. break;
  675. }
  676. Size -= FullDescriptor->PartialResourceList.Count *
  677. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  678. for (j=0; j<FullDescriptor->PartialResourceList.Count; j++) {
  679. fprintf( fh, "%.*sDescriptor number %d\n",
  680. IndentLevel+12,
  681. " ",
  682. j
  683. );
  684. PartialResourceDescriptor =
  685. &(FullDescriptor->PartialResourceList.PartialDescriptors[j]);
  686. switch(PartialResourceDescriptor->ShareDisposition) {
  687. case CmResourceShareUndetermined:
  688. TypeName = L"CmResourceShareUndetermined";
  689. break;
  690. case CmResourceShareDeviceExclusive:
  691. TypeName = L"CmResourceDeviceExclusive";
  692. break;
  693. case CmResourceShareDriverExclusive:
  694. TypeName = L"CmResourceDriverExclusive";
  695. break;
  696. case CmResourceShareShared:
  697. TypeName = L"CmResourceShared";
  698. break;
  699. default:
  700. TypeName = L"***invalid share disposition***";
  701. break;
  702. }
  703. fprintf( fh, "%.*sShare Disposition %ws\n",
  704. IndentLevel+12,
  705. " ",
  706. TypeName
  707. );
  708. FlagName = L"***invalid Flags";
  709. switch(PartialResourceDescriptor->Type) {
  710. case CmResourceTypeNull:
  711. TypeName = L"NULL";
  712. FlagName = L"***Unused";
  713. break;
  714. case CmResourceTypePort:
  715. TypeName = L"PORT";
  716. if (PartialResourceDescriptor->Flags == CM_RESOURCE_PORT_MEMORY) {
  717. FlagName = L"CM_RESOURCE_PORT_MEMORY";
  718. }
  719. if (PartialResourceDescriptor->Flags == CM_RESOURCE_PORT_IO) {
  720. FlagName = L"CM_RESOURCE_PORT_IO";
  721. }
  722. break;
  723. case CmResourceTypeInterrupt:
  724. TypeName = L"INTERRUPT";
  725. if (PartialResourceDescriptor->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) {
  726. FlagName = L"CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE";
  727. }
  728. if (PartialResourceDescriptor->Flags == CM_RESOURCE_INTERRUPT_LATCHED) {
  729. FlagName = L"CM_RESOURCE_INTERRUPT_LATCHED";
  730. }
  731. break;
  732. case CmResourceTypeMemory:
  733. TypeName = L"MEMORY";
  734. if (PartialResourceDescriptor->Flags == CM_RESOURCE_MEMORY_READ_WRITE) {
  735. FlagName = L"CM_RESOURCE_MEMORY_READ_WRITE";
  736. }
  737. if (PartialResourceDescriptor->Flags == CM_RESOURCE_MEMORY_READ_ONLY) {
  738. FlagName = L"CM_RESOURCE_MEMORY_READ_ONLY";
  739. }
  740. if (PartialResourceDescriptor->Flags == CM_RESOURCE_MEMORY_WRITE_ONLY) {
  741. FlagName = L"CM_RESOURCE_MEMORY_WRITE_ONLY";
  742. }
  743. break;
  744. case CmResourceTypeDma:
  745. TypeName = L"DMA";
  746. FlagName = L"***Unused";
  747. break;
  748. case CmResourceTypeDeviceSpecific:
  749. TypeName = L"DEVICE SPECIFIC";
  750. FlagName = L"***Unused";
  751. break;
  752. default:
  753. TypeName = L"***invalid type***";
  754. break;
  755. }
  756. fprintf( fh, "%.*sTYPE %ws\n",
  757. IndentLevel+12,
  758. " ",
  759. TypeName
  760. );
  761. fprintf( fh, "%.*sFlags %ws\n",
  762. IndentLevel+12,
  763. " ",
  764. FlagName
  765. );
  766. switch(PartialResourceDescriptor->Type) {
  767. case CmResourceTypePort:
  768. fprintf( fh, "%.*sSTART 0x%08lx LENGTH 0x%08lx\n",
  769. IndentLevel+12,
  770. " ",
  771. PartialResourceDescriptor->u.Port.Start.LowPart,
  772. PartialResourceDescriptor->u.Port.Length
  773. );
  774. break;
  775. case CmResourceTypeInterrupt:
  776. fprintf( fh, "%.*sLEVEL %d VECTOR %d AFFINITY %d\n",
  777. IndentLevel+12,
  778. " ",
  779. PartialResourceDescriptor->u.Interrupt.Level,
  780. PartialResourceDescriptor->u.Interrupt.Vector,
  781. PartialResourceDescriptor->u.Interrupt.Affinity
  782. );
  783. break;
  784. case CmResourceTypeMemory:
  785. fprintf( fh, "%.*sSTART 0x%08lx%08lx LENGTH 0x%08lx\n",
  786. IndentLevel+12,
  787. " ",
  788. PartialResourceDescriptor->u.Memory.Start.HighPart,
  789. PartialResourceDescriptor->u.Memory.Start.LowPart,
  790. PartialResourceDescriptor->u.Memory.Length
  791. );
  792. break;
  793. case CmResourceTypeDma:
  794. fprintf( fh, "%.*sCHANNEL %d PORT %d\n",
  795. IndentLevel+12,
  796. " ",
  797. PartialResourceDescriptor->u.Dma.Channel,
  798. PartialResourceDescriptor->u.Dma.Port
  799. );
  800. break;
  801. case CmResourceTypeDeviceSpecific:
  802. fprintf( fh, "%.*sDataSize 0x%08lx\n",
  803. IndentLevel+12,
  804. " ",
  805. PartialResourceDescriptor->u.DeviceSpecificData.DataSize
  806. );
  807. p = (PULONG)(PartialResourceDescriptor + 1);
  808. k = (PartialResourceDescriptor->u.DeviceSpecificData.DataSize + 3) / sizeof( ULONG );
  809. for (l=0; l<k; l++) {
  810. if ((l % 8) == 0) {
  811. fprintf( fh, "\n%.*s",
  812. IndentLevel+12,
  813. " "
  814. );
  815. }
  816. fprintf( fh, "0x%08lx ", *p++ );
  817. }
  818. fprintf( fh, "\n" );
  819. break;
  820. default:
  821. fprintf( fh, "%.*s*** Unknown resource list type: %c ****\n",
  822. IndentLevel+12,
  823. " ",
  824. PartialResourceDescriptor->Type
  825. );
  826. break;
  827. }
  828. fprintf( fh, "\n" );
  829. }
  830. FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) (PartialResourceDescriptor+1);
  831. }
  832. break;
  833. }
  834. case REG_NONE:
  835. default:
  836. if (KeyValueInformation->Type == REG_NONE) {
  837. fprintf( fh, "REG_NONE\n");
  838. }
  839. else {
  840. fprintf( fh, "*** Unknown registry type (%08lx)",
  841. KeyValueInformation->Type
  842. );
  843. }
  844. fprintf( fh, "%.*s",
  845. IndentLevel,
  846. " "
  847. );
  848. fprintf( fh, " Length: 0x%lx\n", KeyValueInformation->DataLength );
  849. fprintf( fh, "\n%.*s",
  850. IndentLevel,
  851. " "
  852. );
  853. fprintf( fh, " Data: ");
  854. pbyte = ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
  855. for ( k=0, m=1; k<KeyValueInformation->DataLength; k++,m++) {
  856. fprintf( fh, "%02x ", (*pbyte) );
  857. pbyte++;
  858. if (m==8) {
  859. fprintf( fh, "\n%.*s",
  860. IndentLevel+12,
  861. " "
  862. );
  863. m=0;
  864. }
  865. }
  866. break;
  867. }
  868. fprintf( fh, "\n" );
  869. return;
  870. }
  871. //
  872. // Define an upcase macro for temporary use by the upcase routines
  873. //
  874. #define upcase(C) (WCHAR )(((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C)))
  875. BOOLEAN
  876. RegGetMultiString(
  877. IN OUT PUNICODE_STRING ValueString,
  878. OUT PUNICODE_STRING MultiString
  879. )
  880. /*++
  881. Routine Description:
  882. This routine parses multi-strings of the form
  883. "foo" "bar" "bletch"
  884. Each time it is called, it strips the first string in quotes from
  885. the input string, and returns it as the multi-string.
  886. INPUT ValueString: "foo" "bar" "bletch"
  887. OUTPUT ValueString: "bar" "bletch"
  888. MultiString: foo
  889. Arguments:
  890. ValueString - Supplies the string from which the multi-string will be
  891. parsed
  892. - Returns the remaining string after the multi-string is
  893. removed
  894. MultiString - Returns the multi-string removed from ValueString
  895. Return Value:
  896. TRUE - multi-string found and removed.
  897. FALSE - no more multi-strings remaining.
  898. --*/
  899. {
  900. //
  901. // Find the first quote mark.
  902. //
  903. while ((*(ValueString->Buffer) != L'"') &&
  904. (ValueString->Length > 0)) {
  905. ++ValueString->Buffer;
  906. ValueString->Length -= sizeof(WCHAR);
  907. ValueString->MaximumLength -= sizeof(WCHAR);
  908. }
  909. if (ValueString->Length == 0) {
  910. return(FALSE);
  911. }
  912. //
  913. // We have found the start of the multi-string. Now find the end,
  914. // building up our return MultiString as we go.
  915. //
  916. ++ValueString->Buffer;
  917. ValueString->Length -= sizeof(WCHAR);
  918. ValueString->MaximumLength -= sizeof(WCHAR);
  919. MultiString->Buffer = ValueString->Buffer;
  920. MultiString->Length = 0;
  921. MultiString->MaximumLength = 0;
  922. while ((*(ValueString->Buffer) != L'"') &&
  923. (ValueString->Length > 0)) {
  924. ++ValueString->Buffer;
  925. ValueString->Length -= sizeof(WCHAR);
  926. ValueString->MaximumLength -= sizeof(WCHAR);
  927. MultiString->Length += sizeof(WCHAR);
  928. MultiString->MaximumLength += sizeof(WCHAR);
  929. }
  930. if (ValueString->Length == 0) {
  931. return(FALSE);
  932. }
  933. ++ValueString->Buffer;
  934. ValueString->Length -= sizeof(WCHAR);
  935. ValueString->MaximumLength -= sizeof(WCHAR);
  936. return( TRUE );
  937. }
  938. BOOLEAN
  939. RegGetKeyValue(
  940. IN PUNICODE_STRING InitialKeyValue,
  941. IN OUT PREG_UNICODE_FILE UnicodeFile,
  942. OUT PULONG ValueType,
  943. OUT PVOID *ValueBuffer,
  944. OUT PULONG ValueLength
  945. )
  946. {
  947. ULONG PrefixLength;
  948. PWSTR s;
  949. PULONG p;
  950. ULONG n;
  951. NTSTATUS Status;
  952. ULONG IndentAmount;
  953. PWSTR FirstEqual;
  954. UNICODE_STRING KeyValue;
  955. UNICODE_STRING MultiValue;
  956. BOOLEAN GetDataFromBinaryFile = FALSE;
  957. BOOLEAN GetDataFromMultiSzFile = FALSE;
  958. BOOLEAN ParseDateTime = FALSE;
  959. KeyValue = *InitialKeyValue;
  960. if (RtlPrefixUnicodeString( &RiDeleteKeyword, &KeyValue, TRUE )) {
  961. *ValueBuffer = NULL;
  962. return( TRUE );
  963. }
  964. else
  965. if (!RtlPrefixUnicodeString( &RiRegKeyword, &KeyValue, TRUE )) {
  966. *ValueType = REG_SZ;
  967. PrefixLength = 0;
  968. }
  969. else
  970. if (RtlPrefixUnicodeString( &RiRegNoneKeyword, &KeyValue, TRUE )) {
  971. *ValueType = REG_NONE;
  972. PrefixLength = RiRegNoneKeyword.Length;
  973. }
  974. else
  975. if (RtlPrefixUnicodeString( &RiRegSzKeyword, &KeyValue, TRUE )) {
  976. *ValueType = REG_SZ;
  977. PrefixLength = RiRegSzKeyword.Length;
  978. }
  979. else
  980. if (RtlPrefixUnicodeString( &RiRegExpandSzKeyword, &KeyValue, TRUE )) {
  981. *ValueType = REG_EXPAND_SZ;
  982. PrefixLength = RiRegExpandSzKeyword.Length;
  983. }
  984. else
  985. if (RtlPrefixUnicodeString( &RiRegDwordKeyword, &KeyValue, TRUE )) {
  986. *ValueType = REG_DWORD;
  987. PrefixLength = RiRegDwordKeyword.Length;
  988. }
  989. else
  990. if (RtlPrefixUnicodeString( &RiRegBinaryFileKeyword, &KeyValue, TRUE )) {
  991. *ValueType = REG_BINARY;
  992. PrefixLength = RiRegBinaryFileKeyword.Length;
  993. GetDataFromBinaryFile = TRUE;
  994. }
  995. else
  996. if (RtlPrefixUnicodeString( &RiRegBinaryKeyword, &KeyValue, TRUE )) {
  997. *ValueType = REG_BINARY;
  998. PrefixLength = RiRegBinaryKeyword.Length;
  999. }
  1000. else
  1001. if (RtlPrefixUnicodeString( &RiRegLinkKeyword, &KeyValue, TRUE )) {
  1002. *ValueType = REG_LINK;
  1003. PrefixLength = RiRegLinkKeyword.Length;
  1004. }
  1005. else
  1006. if (RtlPrefixUnicodeString( &RiRegMultiSzFileKeyword, &KeyValue, TRUE)) {
  1007. *ValueType = REG_MULTI_SZ;
  1008. PrefixLength = RiRegMultiSzFileKeyword.Length;
  1009. GetDataFromMultiSzFile = TRUE;
  1010. }
  1011. else
  1012. if (RtlPrefixUnicodeString( &RiRegMultiSzKeyword, &KeyValue, TRUE)) {
  1013. *ValueType = REG_MULTI_SZ;
  1014. PrefixLength = RiRegMultiSzKeyword.Length;
  1015. }
  1016. else
  1017. if (RtlPrefixUnicodeString( &RiRegDateKeyword, &KeyValue, TRUE )) {
  1018. *ValueType = REG_BINARY;
  1019. ParseDateTime = TRUE;
  1020. PrefixLength = RiRegDateKeyword.Length;
  1021. }
  1022. else {
  1023. return( FALSE );
  1024. }
  1025. if (*ValueType != REG_NONE) {
  1026. s = (PWSTR)
  1027. ((PCHAR)KeyValue.Buffer + PrefixLength);
  1028. KeyValue.Length -= (USHORT)PrefixLength;
  1029. while (KeyValue.Length != 0 && *s <= L' ') {
  1030. s++;
  1031. KeyValue.Length -= sizeof( WCHAR );
  1032. }
  1033. KeyValue.Buffer = s;
  1034. }
  1035. else {
  1036. *ValueType = REG_SZ;
  1037. }
  1038. if (GetDataFromBinaryFile) {
  1039. Status = RegReadBinaryFile( &KeyValue, ValueBuffer, ValueLength );
  1040. if (NT_SUCCESS( Status )) {
  1041. return( TRUE );
  1042. }
  1043. else {
  1044. fprintf( stderr, "REGINI: Unable to read data from %wZ - Status == %lx\n", &KeyValue, Status );
  1045. return( FALSE );
  1046. }
  1047. }
  1048. if (GetDataFromMultiSzFile) {
  1049. Status = RegReadMultiSzFile( &KeyValue, ValueBuffer, ValueLength );
  1050. if (NT_SUCCESS( Status )) {
  1051. return( TRUE );
  1052. }
  1053. else {
  1054. fprintf( stderr, "REGINI: Unable to read data from %wZ - Status == %lx\n", &KeyValue, Status );
  1055. return( FALSE );
  1056. }
  1057. }
  1058. switch( *ValueType ) {
  1059. case REG_SZ:
  1060. case REG_EXPAND_SZ:
  1061. case REG_LINK:
  1062. *ValueLength = KeyValue.Length + sizeof( UNICODE_NULL );
  1063. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, *ValueLength );
  1064. if (*ValueBuffer == NULL) {
  1065. return( FALSE );
  1066. }
  1067. RtlMoveMemory( *ValueBuffer, KeyValue.Buffer, KeyValue.Length );
  1068. ((PWSTR)*ValueBuffer)[ KeyValue.Length / sizeof( WCHAR ) ] = UNICODE_NULL;
  1069. return( TRUE );
  1070. case REG_DWORD:
  1071. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof( ULONG ) );
  1072. if (*ValueBuffer == NULL) {
  1073. return( FALSE );
  1074. }
  1075. if (RtlPrefixUnicodeString( &RiTrueKeyword, &KeyValue, TRUE ) ||
  1076. RtlPrefixUnicodeString( &RiYesKeyword, &KeyValue, TRUE ) ||
  1077. RtlPrefixUnicodeString( &RiOnKeyword, &KeyValue, TRUE )
  1078. ) {
  1079. *(PULONG)*ValueBuffer = (ULONG)TRUE;
  1080. }
  1081. else
  1082. if (RtlPrefixUnicodeString( &RiFalseKeyword, &KeyValue, TRUE ) ||
  1083. RtlPrefixUnicodeString( &RiNoKeyword, &KeyValue, TRUE ) ||
  1084. RtlPrefixUnicodeString( &RiOffKeyword, &KeyValue, TRUE )
  1085. ) {
  1086. *(PULONG)*ValueBuffer = (ULONG)FALSE;
  1087. }
  1088. else {
  1089. Status = RtlUnicodeStringToInteger( &KeyValue, 0, (PULONG)*ValueBuffer );
  1090. if (!NT_SUCCESS( Status )) {
  1091. fprintf( stderr, "REGINI: CharToInteger( %wZ ) failed - Status == %lx\n", &KeyValue, Status );
  1092. RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer );
  1093. return( FALSE );
  1094. }
  1095. }
  1096. *ValueLength = sizeof( ULONG );
  1097. return( TRUE );
  1098. case REG_BINARY:
  1099. if (ParseDateTime) {
  1100. #define NUMBER_DATE_TIME_FIELDS 6
  1101. ULONG FieldIndexes[ NUMBER_DATE_TIME_FIELDS ] = {1, 2, 0, 3, 4, 7};
  1102. //
  1103. // Month/Day/Year HH:MM DayOfWeek
  1104. //
  1105. ULONG CurrentField = 0;
  1106. PCSHORT Fields;
  1107. TIME_FIELDS DateTimeFields;
  1108. UNICODE_STRING Field;
  1109. ULONG FieldValue;
  1110. RtlZeroMemory( &DateTimeFields, sizeof( DateTimeFields ) );
  1111. Fields = &DateTimeFields.Year;
  1112. while (KeyValue.Length) {
  1113. if (CurrentField >= 7) {
  1114. return( FALSE );
  1115. }
  1116. s = KeyValue.Buffer;
  1117. while (KeyValue.Length && *s == L' ') {
  1118. KeyValue.Length--;
  1119. s++;
  1120. }
  1121. Field.Buffer = s;
  1122. while (KeyValue.Length) {
  1123. if (CurrentField == (NUMBER_DATE_TIME_FIELDS-1)) {
  1124. }
  1125. else
  1126. if (*s < L'0' || *s > L'9') {
  1127. break;
  1128. }
  1129. KeyValue.Length--;
  1130. s++;
  1131. }
  1132. Field.Length = (USHORT)((PCHAR)s - (PCHAR)Field.Buffer);
  1133. Field.MaximumLength = Field.Length;
  1134. if (KeyValue.Length) {
  1135. KeyValue.Length--;
  1136. s++;
  1137. }
  1138. KeyValue.Buffer = s;
  1139. if (CurrentField == (NUMBER_DATE_TIME_FIELDS-1)) {
  1140. if (Field.Length < 3) {
  1141. printf( "REGINI: %wZ invalid day of week length\n", &Field );
  1142. return FALSE;
  1143. }
  1144. if (DateTimeFields.Year != 0) {
  1145. printf( "REGINI: Year must be zero to specify day of week\n" );
  1146. return FALSE;
  1147. }
  1148. if (!_wcsnicmp( Field.Buffer, L"SUN", 3 )) {
  1149. FieldValue = 0;
  1150. }
  1151. else
  1152. if (!_wcsnicmp( Field.Buffer, L"MON", 3 )) {
  1153. FieldValue = 1;
  1154. }
  1155. else
  1156. if (!_wcsnicmp( Field.Buffer, L"TUE", 3 )) {
  1157. FieldValue = 2;
  1158. }
  1159. else
  1160. if (!_wcsnicmp( Field.Buffer, L"WED", 3 )) {
  1161. FieldValue = 3;
  1162. }
  1163. else
  1164. if (!_wcsnicmp( Field.Buffer, L"THU", 3 )) {
  1165. FieldValue = 4;
  1166. }
  1167. else
  1168. if (!_wcsnicmp( Field.Buffer, L"FRI", 3 )) {
  1169. FieldValue = 5;
  1170. }
  1171. else
  1172. if (!_wcsnicmp( Field.Buffer, L"SAT", 3 )) {
  1173. FieldValue = 6;
  1174. }
  1175. else {
  1176. printf( "REGINI: %wZ invalid day of week\n", &Field );
  1177. return FALSE;
  1178. }
  1179. }
  1180. else {
  1181. Status = RtlUnicodeStringToInteger( &Field, 10, &FieldValue );
  1182. if (!NT_SUCCESS( Status )) {
  1183. return( FALSE );
  1184. }
  1185. }
  1186. Fields[ FieldIndexes[ CurrentField++ ] ] = (CSHORT)FieldValue;
  1187. }
  1188. if (DateTimeFields.Year == 0) {
  1189. if (DateTimeFields.Day > 5) {
  1190. printf( "REGINI: Day must be 0 - 5 if year is zero.\n" );
  1191. return FALSE;
  1192. }
  1193. }
  1194. else
  1195. if (DateTimeFields.Year < 100) {
  1196. DateTimeFields.Year += 1900;
  1197. }
  1198. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof( DateTimeFields ) );
  1199. *ValueLength = sizeof( DateTimeFields );
  1200. RtlMoveMemory( *ValueBuffer, &DateTimeFields, sizeof( DateTimeFields ) );
  1201. return TRUE;
  1202. }
  1203. else {
  1204. Status = RtlUnicodeStringToInteger( &KeyValue, 0, ValueLength );
  1205. if (!NT_SUCCESS( Status )) {
  1206. return( FALSE );
  1207. }
  1208. s = KeyValue.Buffer;
  1209. while (KeyValue.Length != 0 && *s > L' ') {
  1210. s++;
  1211. KeyValue.Length -= sizeof( WCHAR );
  1212. }
  1213. KeyValue.Buffer = s;
  1214. }
  1215. break;
  1216. case REG_MULTI_SZ:
  1217. *ValueLength = 0;
  1218. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, KeyValue.Length + sizeof( UNICODE_NULL ) );
  1219. while (RegGetMultiString(&KeyValue, &MultiValue)) {
  1220. RtlMoveMemory( (PUCHAR)*ValueBuffer + *ValueLength,
  1221. MultiValue.Buffer,
  1222. MultiValue.Length );
  1223. *ValueLength += MultiValue.Length;
  1224. ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL;
  1225. *ValueLength += sizeof(UNICODE_NULL);
  1226. }
  1227. ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL;
  1228. *ValueLength += sizeof(UNICODE_NULL);
  1229. return( TRUE );
  1230. default:
  1231. return( FALSE );
  1232. }
  1233. *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, *ValueLength );
  1234. p = *ValueBuffer;
  1235. n = (*ValueLength + sizeof( ULONG ) - 1) / sizeof( ULONG );
  1236. while (n--) {
  1237. if (KeyValue.Length == 0) {
  1238. if (!RegGetNextLine( UnicodeFile, &IndentAmount, &FirstEqual )) {
  1239. RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer );
  1240. return( FALSE );
  1241. }
  1242. KeyValue.Buffer = UnicodeFile->BeginLine;
  1243. KeyValue.Length = (USHORT)
  1244. ((PCHAR)UnicodeFile->EndOfLine - (PCHAR)UnicodeFile->BeginLine);
  1245. KeyValue.MaximumLength = KeyValue.Length;
  1246. }
  1247. s = KeyValue.Buffer;
  1248. while (KeyValue.Length != 0 && *s <= L' ') {
  1249. s++;
  1250. KeyValue.Length -= sizeof( WCHAR );
  1251. }
  1252. KeyValue.Buffer = s;
  1253. if (KeyValue.Length != 0) {
  1254. Status = RtlUnicodeStringToInteger( &KeyValue, 0, p );
  1255. if (!NT_SUCCESS( Status )) {
  1256. RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer );
  1257. return( FALSE );
  1258. }
  1259. p++;
  1260. s = KeyValue.Buffer;
  1261. while (KeyValue.Length != 0 && *s > L' ') {
  1262. s++;
  1263. KeyValue.Length -= sizeof( WCHAR );
  1264. }
  1265. KeyValue.Buffer = s;
  1266. }
  1267. }
  1268. return( TRUE );
  1269. }
  1270. BOOLEAN
  1271. RtlPrefixUnicodeString(
  1272. IN PUNICODE_STRING String1,
  1273. IN PUNICODE_STRING String2,
  1274. IN BOOLEAN CaseInSensitive
  1275. )
  1276. /*++
  1277. Routine Description:
  1278. The RtlPrefixUnicodeString function determines if the String1
  1279. counted string parameter is a prefix of the String2 counted string
  1280. parameter.
  1281. The CaseInSensitive parameter specifies if case is to be ignored when
  1282. doing the comparison.
  1283. Arguments:
  1284. String1 - Pointer to the first unicode string.
  1285. String2 - Pointer to the second unicode string.
  1286. CaseInsensitive - TRUE if case should be ignored when doing the
  1287. comparison.
  1288. Return Value:
  1289. Boolean value that is TRUE if String1 equals a prefix of String2 and
  1290. FALSE otherwise.
  1291. --*/
  1292. {
  1293. PWSTR s1, s2;
  1294. ULONG n;
  1295. WCHAR c1, c2;
  1296. s1 = String1->Buffer;
  1297. s2 = String2->Buffer;
  1298. if (String2->Length < String1->Length) {
  1299. return( FALSE );
  1300. }
  1301. n = String1->Length / sizeof( c1 );
  1302. while (n) {
  1303. c1 = *s1++;
  1304. c2 = *s2++;
  1305. if (CaseInSensitive) {
  1306. c1 = upcase(c1);
  1307. c2 = upcase(c2);
  1308. }
  1309. if (c1 != c2) {
  1310. return( FALSE );
  1311. }
  1312. n--;
  1313. }
  1314. return( TRUE );
  1315. }
  1316.