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.

376 lines
11 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. regdat16.c
  5. Abstract:
  6. This module contains code for reading the Windows 3.1 registry
  7. file (REG.DAT)
  8. Author:
  9. Steve Wood (stevewo) 22-Feb-1993
  10. Revision History:
  11. --*/
  12. #include "advapi.h"
  13. #include <stdio.h>
  14. #include <winbasep.h>
  15. #include "win31io.h"
  16. // #define SHOW_TREE_MIGRATION
  17. #define MAX_LEVELS 64
  18. PREG_HEADER16
  19. LoadRegistry16(
  20. PWSTR RegistryFileName
  21. )
  22. {
  23. HANDLE File, Mapping;
  24. LPVOID Base;
  25. File = CreateFileW( RegistryFileName,
  26. GENERIC_READ,
  27. FILE_SHARE_READ,
  28. NULL,
  29. OPEN_EXISTING,
  30. 0,
  31. NULL
  32. );
  33. if (File == INVALID_HANDLE_VALUE) {
  34. return NULL;
  35. }
  36. Mapping = CreateFileMapping( File,
  37. NULL,
  38. PAGE_WRITECOPY,
  39. 0,
  40. 0,
  41. NULL
  42. );
  43. CloseHandle( File );
  44. if (Mapping == NULL) {
  45. return NULL;
  46. }
  47. Base = MapViewOfFile( Mapping,
  48. FILE_MAP_COPY,
  49. 0,
  50. 0,
  51. 0
  52. );
  53. CloseHandle( Mapping );
  54. return (PREG_HEADER16)Base;
  55. }
  56. BOOL
  57. UnloadRegistry16(
  58. PREG_HEADER16 Registry
  59. )
  60. {
  61. return UnmapViewOfFile( (LPVOID)Registry );
  62. }
  63. typedef struct _REG16_PATH_SUBST {
  64. ULONG cbOldValue;
  65. LPSTR OldValue;
  66. LPSTR NewValue;
  67. } REG16_PATH_SUBST, *PREG16_PATH_SUBST;
  68. REG16_PATH_SUBST Reg16PathSubstitutes[] = {
  69. {10, "mciole.dll", "mciole16.dll"},
  70. {11, "mplayer.exe", "mplay32.exe" },
  71. {12, "packager.exe", "packgr32.exe"},
  72. {12, "soundrec.exe", "sndrec32.exe"},
  73. {0, NULL, NULL}
  74. };
  75. typedef struct _REG16_WALK_STATE {
  76. HANDLE KeyHandle;
  77. WORD NodeIndex;
  78. WORD Reserved;
  79. } REG16_WALK_STATE, *PREG16_WALK_STATE;
  80. char *szBlanks = " ";
  81. BOOL
  82. CreateRegistryClassesFromRegistry16(
  83. HANDLE SoftwareRoot,
  84. PREG_HEADER16 Registry
  85. )
  86. {
  87. PREG_KEY16 KeyNode;
  88. PREG_STRING16 KeyNameString, KeyValueString;
  89. PREG_NODE16 NodeTable;
  90. PCH StringTable;
  91. int i;
  92. DWORD Level;
  93. REG16_WALK_STATE State[ MAX_LEVELS ];
  94. ANSI_STRING AnsiString;
  95. UNICODE_STRING KeyName;
  96. UNICODE_STRING KeyValue;
  97. UNICODE_STRING ValueName;
  98. NTSTATUS Status;
  99. OBJECT_ATTRIBUTES ObjectAttributes;
  100. ULONG CreateDisposition;
  101. PREG16_PATH_SUBST PathSubst;
  102. RtlInitUnicodeString( &ValueName, NULL );
  103. NodeTable = (PREG_NODE16)((PBYTE)Registry + Registry->dwNodeTable);
  104. StringTable = (PCH)Registry + Registry->dwStringValue;
  105. i = NodeTable[ 0 ].key.iChild;
  106. Level = 0;
  107. while (i != 0) {
  108. KeyNode = &NodeTable[ i ].key;
  109. KeyNameString = &NodeTable[ KeyNode->iKey ].str;
  110. AnsiString.Length = KeyNameString->cb;
  111. AnsiString.MaximumLength = AnsiString.Length;
  112. AnsiString.Buffer = StringTable + KeyNameString->irgb;
  113. if (Level == 0 && *AnsiString.Buffer == '.') {
  114. AnsiString.Buffer += 1;
  115. AnsiString.Length -= 1;
  116. }
  117. RtlAnsiStringToUnicodeString( &KeyName, &AnsiString, TRUE );
  118. #ifdef SHOW_TREE_MIGRATION
  119. DbgPrint( "%.*s%wZ", Level * 4, szBlanks, &KeyName );
  120. #endif
  121. InitializeObjectAttributes( &ObjectAttributes,
  122. &KeyName,
  123. OBJ_CASE_INSENSITIVE,
  124. Level == 0 ? SoftwareRoot : State[ Level-1 ].KeyHandle,
  125. NULL
  126. );
  127. Status = NtCreateKey( &State[ Level ].KeyHandle,
  128. STANDARD_RIGHTS_WRITE |
  129. KEY_QUERY_VALUE |
  130. KEY_ENUMERATE_SUB_KEYS |
  131. KEY_SET_VALUE |
  132. KEY_CREATE_SUB_KEY,
  133. &ObjectAttributes,
  134. 0,
  135. NULL,
  136. 0,
  137. &CreateDisposition
  138. );
  139. RtlFreeUnicodeString( &KeyName );
  140. if (!NT_SUCCESS( Status )) {
  141. #ifdef SHOW_TREE_MIGRATION
  142. DbgPrint( " *** CreateKey failed with Status == %x\n", Status );
  143. #endif
  144. BaseSetLastNTError( Status );
  145. break;
  146. }
  147. #ifdef SHOW_TREE_MIGRATION
  148. DbgPrint( "%s\n", CreateDisposition == REG_CREATED_NEW_KEY ? " *** NEW ***" : "" );
  149. #endif
  150. if (KeyNode->iValue != 0) {
  151. ULONG cb;
  152. LPSTR s, Src, Dst;
  153. KeyValueString = &NodeTable[ KeyNode->iValue ].str;
  154. cb = KeyValueString->cb;
  155. Src = StringTable + KeyValueString->irgb;
  156. Dst = RtlAllocateHeap( RtlProcessHeap(), 0, 2*(cb+1) );
  157. if (Dst != NULL) {
  158. AnsiString.Length = 0;
  159. AnsiString.Buffer = Dst;
  160. while (cb) {
  161. PathSubst = &Reg16PathSubstitutes[ 0 ];
  162. while (PathSubst->OldValue) {
  163. if (cb >= PathSubst->cbOldValue &&
  164. !_strnicmp( Src, PathSubst->OldValue, PathSubst->cbOldValue )
  165. ) {
  166. *Dst = '\0';
  167. while (Dst > AnsiString.Buffer) {
  168. if (Dst[ -1 ] <= ' ') {
  169. break;
  170. }
  171. else {
  172. Dst -= 1;
  173. }
  174. }
  175. s = PathSubst->NewValue;
  176. #ifdef SHOW_TREE_MIGRATION
  177. DbgPrint( " Found '%s%s' changed to '%s' ", Dst, PathSubst->OldValue, PathSubst->NewValue );
  178. #else
  179. KdPrint(( "ADVAPI: Found '%s%s' changed to '%s'\n", Dst, PathSubst->OldValue, PathSubst->NewValue ));
  180. #endif
  181. Src += PathSubst->cbOldValue;
  182. cb -= PathSubst->cbOldValue;
  183. while (*Dst = *s++) {
  184. Dst += 1;
  185. }
  186. break;
  187. }
  188. else {
  189. PathSubst += 1;
  190. }
  191. }
  192. if (PathSubst->OldValue == NULL) {
  193. *Dst++ = *Src++;
  194. cb -= 1;
  195. }
  196. }
  197. *Dst = '\0';
  198. AnsiString.Length = (USHORT)(Dst - AnsiString.Buffer);
  199. AnsiString.MaximumLength = (USHORT)(AnsiString.Length + 1);
  200. RtlAnsiStringToUnicodeString( &KeyValue, &AnsiString, TRUE );
  201. RtlFreeHeap( RtlProcessHeap(), 0, AnsiString.Buffer );
  202. #ifdef SHOW_TREE_MIGRATION
  203. DbgPrint( "%.*s= (%u, %u) %wZ", (Level+1) * 4, szBlanks, KeyValueString->cb, cb, &KeyValue );
  204. #endif
  205. Status = NtSetValueKey( State[ Level ].KeyHandle,
  206. &ValueName,
  207. 0,
  208. REG_SZ,
  209. KeyValue.Buffer,
  210. KeyValue.Length + sizeof( UNICODE_NULL )
  211. );
  212. RtlFreeUnicodeString( &KeyValue );
  213. if (!NT_SUCCESS( Status )) {
  214. #ifdef SHOW_TREE_MIGRATION
  215. DbgPrint( " *** SetValueKey failed with Status == %x\n", Status );
  216. #endif
  217. BaseSetLastNTError( Status );
  218. break;
  219. }
  220. #ifdef SHOW_TREE_MIGRATION
  221. DbgPrint( "\n" );
  222. #endif
  223. }
  224. }
  225. if (KeyNode->iChild != 0) {
  226. State[ Level++ ].NodeIndex = KeyNode->iNext;
  227. State[ Level ].KeyHandle = NULL;
  228. i = KeyNode->iChild;
  229. }
  230. else {
  231. NtClose( State[ Level ].KeyHandle );
  232. if (KeyNode->iNext != 0) {
  233. i = KeyNode->iNext;
  234. }
  235. else {
  236. while (Level != 0) {
  237. Level -= 1;
  238. NtClose( State[ Level ].KeyHandle );
  239. if (i = State[ Level ].NodeIndex) {
  240. break;
  241. }
  242. }
  243. }
  244. }
  245. }
  246. if (Level == 0) {
  247. return TRUE;
  248. }
  249. while (Level != 0 && (i = State[ --Level ].NodeIndex) == 0) {
  250. NtClose( State[ Level ].KeyHandle );
  251. }
  252. return FALSE;
  253. }
  254. #if DBG
  255. char *Blanks = " ";
  256. BOOL
  257. DumpRegistry16(
  258. PREG_HEADER16 Registry
  259. )
  260. {
  261. PREG_KEY16 KeyNode;
  262. PREG_STRING16 StringNode, KeyNameString, KeyValueString;
  263. PREG_NODE16 NodeTable;
  264. PCH StringTable, String, KeyName, KeyValue;
  265. int i, j;
  266. DWORD Level;
  267. WORD LevelNode[ MAX_LEVELS ];
  268. NodeTable = (PREG_NODE16)((PBYTE)Registry + Registry->dwNodeTable);
  269. StringTable = (PCH)Registry + Registry->dwStringValue;
  270. DbgPrint( "Windows 3.1 Registry data at %08x\n", Registry );
  271. DbgPrint( " dwMagic: %08x\n", Registry->dwMagic );
  272. DbgPrint( " dwVersion: %08x\n", Registry->dwVersion );
  273. DbgPrint( " dwHdrSize: %08x\n", Registry->dwHdrSize );
  274. DbgPrint( " dwNodeTable: %08x\n", Registry->dwNodeTable );
  275. DbgPrint( " dwNTSize: %08x\n", Registry->dwNTSize );
  276. DbgPrint( " dwStringValue: %08x\n", Registry->dwStringValue );
  277. DbgPrint( " dwSVSize: %08x\n", Registry->dwSVSize );
  278. DbgPrint( " nHash: %04x\n", Registry->nHash );
  279. DbgPrint( " iFirstFree: %04x\n", Registry->iFirstFree );
  280. i = NodeTable[ 0 ].key.iChild;
  281. Level = 0;
  282. while (i != 0) {
  283. KeyNode = &NodeTable[ i ].key;
  284. KeyNameString = &NodeTable[ KeyNode->iKey ].str;
  285. KeyName = StringTable + KeyNameString->irgb;
  286. DbgPrint( "%.*s%.*s\n",
  287. Level * 4,
  288. Blanks,
  289. KeyNameString->cb,
  290. KeyName
  291. );
  292. if (KeyNode->iValue != 0) {
  293. KeyValueString = &NodeTable[ KeyNode->iValue ].str;
  294. KeyValue = StringTable + KeyValueString->irgb;
  295. DbgPrint( "%.*s= %.*s\n",
  296. (Level+1) * 4,
  297. Blanks,
  298. KeyValueString->cb,
  299. KeyValue
  300. );
  301. }
  302. if (KeyNode->iChild != 0) {
  303. LevelNode[ Level++ ] = KeyNode->iNext;
  304. i = KeyNode->iChild;
  305. }
  306. else
  307. if (KeyNode->iNext != 0) {
  308. i = KeyNode->iNext;
  309. }
  310. else {
  311. while (Level != 0 && (i = LevelNode[ --Level ]) == 0) {
  312. ;
  313. }
  314. }
  315. }
  316. return TRUE;
  317. }
  318. #endif // DBG