|
|
1.1 root 1: /*************************************************************************\
2: *
3: * PROGRAM: Monkey: the Registry Monkey Utility.
4: * PURPOSE: To demonstrate Registry API.
5: * COMMENTS:
6: *
7: \*************************************************************************/
8:
9:
10: #include <windows.h>
11: #include <string.h>
12: #include <stdlib.h>
13: #include <stdio.h>
14: #include "monkey.h"
15:
16:
17: HANDLE hInst;
18: HWND hDlg;
19:
20: HANDLE hHeap;
21:
22:
23: /*************************************************************************\
24: *
25: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
26: *
27: * PURPOSE: Creates the dialogbox.
28: *
29: * COMMENTS:
30: *
31: \*************************************************************************/
32:
33: int APIENTRY WinMain (HINSTANCE hInstance,
34: HINSTANCE hPrevInstance,
35: LPSTR lpCmdLine,
36: int nCmdShow)
37:
38:
39: {
40: DWORD retCode;
41:
42: UNREFERENCED_PARAMETER( nCmdShow );
43: UNREFERENCED_PARAMETER( lpCmdLine );
44: UNREFERENCED_PARAMETER( hPrevInstance );
45:
46: hInst = hInstance;
47: hHeap = HeapCreate (HEAP_SERIALIZE, 0, 0);
48:
49: retCode = DialogBox ((HANDLE)hInst, (LPCSTR)"MonkeyDlg",
50: NULL, (DLGPROC)MonkeyDlgProc);
51:
52: HeapDestroy (hHeap);
53: return (retCode);
54:
55: }
56:
57: /************************************************************************\
58: *
59: * FUNCTION: MonkeyDlgProc();
60: *
61: * PURPOSE: Handle the Monkey dialog box messages.
62: *
63: * MESSAGES:
64: *
65: * WM_INITDIALOG - Posts WM_GETFIRSTKEY message.
66: *
67: * WM_GETFIRSTKEY - Puts the first 4 pre-defined keys in the listbox.
68: *
69: * IDL_LISTBOX - Trapped when an item in the left hand listbox
70: * has been double clicked. It posts a IDB_NEXT message.
71: *
72: * IDL_LISTBOX2 - Trapped when an item in the right hand listbox has
73: * been double clicked. It basically calls DisplayKeyData,
74: * which fills the Value edit fields with the data from
75: * the current key's specified value information.
76: *
77: * IDB_PRINT - Basically calls PrintTree() which does a recursive
78: * print of the Registry from the current key to the
79: * end of it's branches.
80: *
81: * IDB_BACK - Sets the dialog box with the information from the
82: * previously selected key (one closer to the root of
83: * the registry, the parent of the current key).
84: *
85: * IDB_NEXT - Sets the dialog box with the information on the
86: * selected key child.
87: *
88: * IDR_FULL - Sets a global variable used to determine if the
89: * user wants to print full Registry information
90: * or only information from keys that have value
91: * associated with it. Variable is set to TRUE.
92: *
93: * IDR_TRIMMED - Same as above, only the variable is set to FALSE.
94: *
95: \************************************************************************/
96:
97: int APIENTRY MonkeyDlgProc (HWND hDlg, WORD wMsg, LONG wParam, LONG lParam)
98: {
99: ULONG KeyClassLength = 256;
100: ULONG KeyNameLength = 256;
101: DWORD indexLB;
102: CHAR *putNullAt;
103:
104: static CHAR RegPath[MAX_PATH] = "";
105: static CHAR NameLBSelect[256] = "";
106: static HKEY hKeyRoot;
107: static DWORD RegLevel;
108: static BOOL FullBranches = TRUE;
109:
110: static HANDLE hFile = INVALID_HANDLE_VALUE;
111: static HANDLE hBootIni;
112:
113: UNREFERENCED_PARAMETER( lParam );
114:
115: switch (wMsg)
116: {
117: case WM_INITDIALOG:
118: // Post a message to get the first 4 pre-defined keys, and set
119: // Full Branches to be the print default.
120: PostMessage (hDlg, WM_GETFIRSTKEY, 0, 0);
121: CheckDlgButton (hDlg, IDR_FULL, TRUE);
122: return (0);
123:
124: case WM_GETFIRSTKEY:
125: // Initialize by putting the first 4 predefined keys of the
126: // registry in the list box.
127:
128: SendMessage (GetDlgItem(hDlg, IDL_LISTBOX),
129: LB_ADDSTRING, 0, (LONG)"HKEY_LOCAL_MACHINE");
130:
131: SendMessage (GetDlgItem(hDlg, IDL_LISTBOX),
132: LB_ADDSTRING, 0, (LONG)"HKEY_CURRENT_USER");
133:
134: SendMessage (GetDlgItem(hDlg, IDL_LISTBOX),
135: LB_ADDSTRING, 0, (LONG)"HKEY_USERS");
136:
137: SendMessage (GetDlgItem(hDlg, IDL_LISTBOX),
138: LB_ADDSTRING, 0, (LONG)"HKEY_CLASSES_ROOT");
139:
140: hKeyRoot = 0; // Initialize hKeyRoot.
141: return (0);
142:
143: case WM_SYSCOMMAND:
144: if (wParam == SC_CLOSE)
145: {
146: EndDialog (hDlg, TRUE);
147: if (hFile != INVALID_HANDLE_VALUE)
148: CloseHandle (hFile);
149: return (TRUE);
150: }
151: break;
152:
153: case WM_COMMAND:
154:
155: switch (LOWORD(wParam))
156: {
157: case IDR_FULL:
158: // If Full Branches pressed, set global var to TRUE.
159: FullBranches = TRUE;
160: return (0);
161:
162: case IDR_TRIMMED:
163: // If Trimmed Branches pressed, set global var to FALSE.
164: FullBranches = FALSE;
165: return (0);
166:
167: case IDL_LISTBOX:
168: // If double click in left hand listbox, clear Value
169: // edit fields, and execute Next functionality.
170: if ( HIWORD (wParam) == LBN_DBLCLK)
171: {
172: SetDlgItemText (hDlg, IDE_VALUE1, "");
173: SetDlgItemText (hDlg, IDE_VALUE2, "");
174: PostMessage (hDlg, WM_COMMAND, IDB_NEXT, 0);
175: }
176: return (0);
177:
178: case IDL_LISTBOX2:
179: // If double click right hand listbox, clear Value edit
180: // fields, then display the key's data.
181: if ( HIWORD (wParam) == LBN_DBLCLK)
182: {
183: SetDlgItemText (hDlg, IDE_VALUE1, "");
184: SetDlgItemText (hDlg, IDE_VALUE2, "");
185: DisplayKeyData (hDlg, RegPath, hKeyRoot);
186: }
187: return (0);
188:
189: case IDB_PRINT:
190:
191: MessageBox (NULL, "Sorry, due to last minute changes in the system, this feature was removed. It may be replaced in a future version.",
192: "Last Minute Note.", MB_OK);
193: return (0);
194:
195: case IDB_NEXT:
196: // Get the index of the cursor selection
197: // in the list box.
198: indexLB = SendMessage (GetDlgItem (hDlg, IDL_LISTBOX),
199: LB_GETCURSEL, 0, 0);
200:
201: // If nothing is selected, flag user and return, otherwise
202: // process the selected key.
203: // LB_ERR indicates nothing selected.
204: if (indexLB == LB_ERR)
205: {
206: MessageBox (hDlg, "Please select an item from the list box",
207: "Registry Monkey Utility", MB_OK);
208: return (0);
209: }
210:
211: // If listbox item 0 is pressed, user wants to move
212: // back up. Execute the Back functionality.
213: if (indexLB == 0 && hKeyRoot)
214: {
215: PostMessage (hDlg, WM_COMMAND, IDB_BACK, 0);
216: return (0);
217: }
218:
219:
220: // Get text from selection in LB.
221: SendMessage (GetDlgItem (hDlg, IDL_LISTBOX),
222: LB_GETTEXT, indexLB, (LPARAM)NameLBSelect);
223:
224: // Put name of chosen item in Name field.
225: SetDlgItemText (hDlg, IDE_NAME, NameLBSelect);
226:
227: // Then clear ListBox entries.
228: SendMessage (GetDlgItem (hDlg, IDL_LISTBOX),
229: LB_RESETCONTENT, 0, 0);
230: SendMessage (GetDlgItem (hDlg, IDL_LISTBOX2),
231: LB_RESETCONTENT, 0, 0);
232:
233: EnumerateLevel (hDlg, NameLBSelect, RegPath, &hKeyRoot);
234:
235: return (0);
236:
237:
238:
239: case IDB_BACK:
240:
241: // For this case (hRootKey = 0)you're at the top level already.
242: // Tell the user, then return
243: if (!hKeyRoot)
244: {
245: MessageBox (hDlg, "Top Level: You can not backup any further.",
246: "Registry Monkey Utility", MB_OK);
247: return (0);
248: }
249:
250: //For all remaining cases, clear the listboxes.
251: SendMessage (GetDlgItem (hDlg, IDL_LISTBOX),
252: LB_RESETCONTENT, 0, 0);
253: SendMessage (GetDlgItem (hDlg, IDL_LISTBOX2),
254: LB_RESETCONTENT, 0, 0);
255:
256:
257:
258: // If hRootKey has a value, but the pathname is blank,
259: // then you must be 1 level deep, reset to level 0 by
260: // posting WM_GETFIRSTKEY.
261: if (strcmp (RegPath, "") == 0)
262: {
263: SetDlgItemText (hDlg, IDE_NAME, "");
264: PostMessage (hDlg, WM_GETFIRSTKEY, 0, 0);
265: return (0);
266: }
267:
268:
269: // Two cases left. One in which the path has only one
270: // key name in it, and no back slash character (meaning
271: // strrchr() will return NULL); and one the other case
272: // where there are more than one key name in the path (
273: // and at least one back slash for strrchr(). If this
274: // is the first case, we want to fakeout EnumerateLevel
275: // into thinking we just picked one of the pre-defined keys,
276: // and then re-enumerate it's child keys.
277: if ((putNullAt = strrchr (RegPath, '\\')) == NULL)
278: {
279: RegPath[0] = '\0';
280:
281: switch ((DWORD)hKeyRoot)
282: {
283: case (DWORD)HKEY_LOCAL_MACHINE:
284: strcpy (NameLBSelect, "HKEY_LOCAL_MACHINE");
285: break;
286:
287: case (DWORD)HKEY_USERS:
288: strcpy (NameLBSelect, "HKEY_USERS");
289: break;
290:
291: case (DWORD)HKEY_CURRENT_USER:
292: strcpy (NameLBSelect, "HKEY_CURRENT_USER");
293: break;
294:
295: case (DWORD)HKEY_CLASSES_ROOT:
296: strcpy (NameLBSelect, "HKEY_CLASSES_ROOT");
297: break;
298: }
299: SetDlgItemText (hDlg, IDE_NAME, NameLBSelect);
300: hKeyRoot = 0;
301: EnumerateLevel (hDlg, NameLBSelect, RegPath, &hKeyRoot);
302: }
303: else
304: {
305: // In the final case, we can just trim the last key
306: // name off the path, and re-enumerate the level.
307: *putNullAt = '\0';
308: putNullAt = strrchr (RegPath, '\\');
309:
310: if (putNullAt)
311: {
312: strcpy (NameLBSelect, putNullAt+1);
313: *putNullAt = '\0';
314: }
315: else
316: {
317: strcpy (NameLBSelect, RegPath);
318: *RegPath = '\0';
319: }
320: SetDlgItemText (hDlg, IDE_NAME, NameLBSelect);
321: EnumerateLevel (hDlg, NameLBSelect, RegPath, &hKeyRoot);
322: }
323: return (0);
324:
325: default:
326: return (0);
327:
328: }
329:
330: }
331: return (FALSE);
332:
333: }
334:
335:
336:
337:
338: /************************************************************************\
339: *
340: * FUNCTION: EnumerateLevel();
341: *
342: * PURPOSE: To get a valid key handle (either to determine if the one sent
343: * to the function was one of the pre-defined, or to open a key
344: * specified by the path), and to pass that key handle along
345: * to QueryKey().
346: *
347: * To enumerate the children of a key, you must have
348: * an open handle to it. The four top keys of the
349: * Registry are predefined and open for use:
350: * HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_USER,
351: * and HKEY_CLASSES_ROOT. These 4 can be used for
352: * RegEnumKey as is; but to RegEnumKey on any of the
353: * children of these you must first have an open key
354: * handle to the child.
355: *
356: * If hKeyRoot != 0, assume you are lower than the
357: * first level of the Registry and the user is trying
358: * to enumerate one of the children. First calculate
359: * the name of the child, and then use RegOpenKey to
360: * get an open handle.
361: *
362: * If hKeyRoot == 0, assume you are at the top level
363: * of the Registry, and set the hKey to be enumerated
364: * to be one of the 4 predefined values, the specific
365: * one indicated by the ListBox selection.
366: *
367: \************************************************************************/
368: VOID EnumerateLevel (HWND hDlg, LPTSTR NameLBSelect,
369: LPTSTR RegPath, HANDLE *hKeyRoot)
370: {
371:
372: HANDLE hKey;
373: HDC hDC;
374: DWORD retCode;
375: CHAR Buf[80];
376: RECT rect;
377:
378:
379: if (*hKeyRoot)
380: {
381: // If RegPath is not NULL, then
382: // you have to add a backslash to the
383: // path name before appending the next
384: // level child name.
385: if (strcmp (RegPath, "") != 0)
386: strcat (RegPath, "\\");
387:
388: // Add the next level child name.
389: strcat (RegPath, NameLBSelect);
390:
391: // Use RegOpenKeyEx() with the new
392: // Registry path to get an open handle
393: // to the child key you want to
394: // enumerate.
395: retCode = RegOpenKeyEx (*hKeyRoot, RegPath,
396: 0,
397: KEY_ENUMERATE_SUB_KEYS |
398: KEY_EXECUTE |
399: KEY_QUERY_VALUE,
400: &hKey);
401:
402: if (retCode != ERROR_SUCCESS)
403: {
404: if (retCode == ERROR_ACCESS_DENIED)
405: wsprintf (Buf, "Error: unable to open key. Probably due to security reasons.");
406: else
407: wsprintf (Buf, "Error: Unable to open key, RegOpenKey = %d, Line = %d",
408: retCode, __LINE__);
409:
410: MessageBox (hDlg, Buf, "", MB_OK);
411: PostMessage (hDlg, WM_COMMAND, IDB_BACK, 0);
412: return;
413: }
414:
415: }
416: else
417: {
418: // Set the *hKeyRoot handle based
419: // on the text taken from the ListBox.
420:
421: if (strcmp (NameLBSelect, "HKEY_CLASSES_ROOT") == 0)
422: *hKeyRoot = HKEY_CLASSES_ROOT;
423:
424: if (strcmp (NameLBSelect, "HKEY_USERS") == 0)
425: *hKeyRoot = HKEY_USERS;
426:
427: if (strcmp (NameLBSelect, "HKEY_LOCAL_MACHINE") == 0)
428: *hKeyRoot = HKEY_LOCAL_MACHINE;
429:
430: if (strcmp (NameLBSelect, "HKEY_CURRENT_USER") == 0)
431: *hKeyRoot = HKEY_CURRENT_USER;
432:
433: hKey = *hKeyRoot; // hKey is used in RegEnumKey().
434:
435: }//end if/else *hKeyRoot
436:
437: QueryKey (hDlg, hKey);
438:
439:
440: RegCloseKey (hKey); // Close the key handle.
441:
442: rect.top = 0; rect.left = 5; rect.right = 1200; rect.bottom = 25;
443: hDC = GetDC (hDlg);
444: FillRect (hDC, &rect, GetStockObject(WHITE_BRUSH));
445: TextOut (hDC, 5, 5, RegPath, strlen(RegPath));
446: ReleaseDC (hDlg, hDC);
447:
448:
449:
450: }
451:
452:
453: /************************************************************************\
454: *
455: * FUNCTION: QueryKey();
456: *
457: * PURPOSE: To display the key's children (subkeys) and the names of
458: * the Values associated with it. This function uses RegEnumKey,
459: * RegEnumValue, and RegQueryInfoKey.
460: *
461: \************************************************************************/
462: VOID QueryKey (HWND hDlg, HANDLE hKey)
463: {
464: CHAR KeyName[MAX_PATH];
465: CHAR ClassName[MAX_PATH] = ""; // Buffer for class name.
466: DWORD dwcClassLen = MAX_PATH; // Length of class string.
467: DWORD dwcSubKeys; // Number of sub keys.
468: DWORD dwcMaxSubKey; // Longest sub key size.
469: DWORD dwcMaxClass; // Longest class string.
470: DWORD dwcValues; // Number of values for this key.
471: DWORD dwcMaxValueName; // Longest Value name.
472: DWORD dwcMaxValueData; // Longest Value data.
473: DWORD dwcSecDesc; // Security descriptor.
474: FILETIME ftLastWriteTime; // Last write time.
475:
476: DWORD i;
477: DWORD retCode;
478:
479: DWORD j;
480: DWORD retValue;
481: CHAR ValueName[MAX_VALUE_NAME];
482: DWORD dwcValueName = MAX_VALUE_NAME;
483: CHAR Buf[80];
484:
485:
486: // Get Class name, Value count.
487:
488: RegQueryInfoKey (hKey, // Key handle.
489: ClassName, // Buffer for class name.
490: &dwcClassLen, // Length of class string.
491: NULL, // Reserved.
492: &dwcSubKeys, // Number of sub keys.
493: &dwcMaxSubKey, // Longest sub key size.
494: &dwcMaxClass, // Longest class string.
495: &dwcValues, // Number of values for this key.
496: &dwcMaxValueName, // Longest Value name.
497: &dwcMaxValueData, // Longest Value data.
498: &dwcSecDesc, // Security descriptor.
499: &ftLastWriteTime); // Last write time.
500:
501: SetDlgItemText (hDlg, IDE_CLASS, ClassName);
502: SetDlgItemInt (hDlg, IDE_CVALUES, dwcValues, FALSE);
503:
504: SendMessage (GetDlgItem (hDlg, IDL_LISTBOX),
505: LB_ADDSTRING, 0, (LONG)"..");
506:
507: // Loop until RegEnumKey fails, get
508: // the name of each child and enter
509: // it into the box.
510:
511: // Enumerate the Child Keys.
512:
513: SetCursor (LoadCursor (NULL, IDC_WAIT));
514: for (i=0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
515: {
516: retCode = RegEnumKey (hKey, i,
517: KeyName, MAX_PATH);
518:
519: if (retCode == (DWORD)ERROR_SUCCESS)
520: SendMessage (GetDlgItem(hDlg, IDL_LISTBOX),
521: LB_ADDSTRING, 0, (LONG)KeyName);
522: }
523: SetCursor (LoadCursor (NULL, IDC_ARROW));
524:
525:
526: // Enumerate the Key Values
527: SetCursor (LoadCursor (NULL, IDC_WAIT));
528:
529: if (dwcValues)
530: for (j = 0, retValue = ERROR_SUCCESS; j < dwcValues; j++)
531: {
532: dwcValueName = MAX_VALUE_NAME;
533: ValueName[0] = '\0';
534: retValue = RegEnumValue (hKey, j, ValueName,
535: &dwcValueName,
536: NULL,
537: NULL, //&dwType,
538: NULL, //&bData,
539: NULL); //&bcData);
540: if (retValue != (DWORD)ERROR_SUCCESS &&
541: retValue != ERROR_INSUFFICIENT_BUFFER)
542: {
543: wsprintf (Buf, "Line:%d 0 based index = %d, retValue = %d, ValueLen = %d",
544: __LINE__, j, retValue, dwcValueName);
545: MessageBox (hDlg, Buf, "Debug", MB_OK);
546: }
547:
548: Buf[0] = '\0';
549: if (!strlen(ValueName))
550: strcpy (ValueName, "<NO NAME>");
551: wsprintf (Buf, "%d) %s ", j, ValueName);
552: SendMessage (GetDlgItem (hDlg, IDL_LISTBOX2),
553: LB_ADDSTRING, 0, (LONG)Buf);
554:
555: }// end for(;;)
556:
557: SetCursor (LoadCursor (NULL, IDC_ARROW));
558:
559: }
560:
561:
562:
563: /************************************************************************\
564: *
565: * FUNCTION: DisplayKeyData();
566: *
567: * PURPOSE: To display the keys values and value types to the Value edit
568: * field. This function is called when the right hand listbox
569: * is double clicked. The functionality is much like that found
570: * in the function PrintTree, please see it for more details.
571: *
572: \************************************************************************/
573:
574:
575: VOID DisplayKeyData (HWND hDlg, CHAR *RegPath, HANDLE hKeyRoot)
576: {
577: HANDLE hKey;
578: DWORD dwLBIndex;
579: CHAR Buf[LINE_LEN];
580: CHAR ValueName[MAX_VALUE_NAME];
581: DWORD cbValueName = MAX_VALUE_NAME;
582: DWORD dwType;
583: DWORD retCode;
584:
585: CHAR ClassName[MAX_PATH];
586: DWORD dwcClassLen = MAX_PATH;
587: DWORD dwcSubKeys;
588: DWORD dwcMaxSubKey;
589: DWORD dwcMaxClass;
590: DWORD dwcValues;
591: DWORD dwcMaxValueName;
592: DWORD dwcMaxValueData;
593: DWORD dwcSecDesc;
594: FILETIME ftLastWriteTime;
595:
596:
597: BYTE *bData;
598: DWORD cbData;
599:
600: CHAR *outBuf;
601: DWORD i;
602: DWORD cStrLen;
603:
604: CHAR *BinaryStrBuf;
605: CHAR ByteBuf[4];
606:
607: CHAR *ptr;
608:
609: // OPEN THE KEY.
610:
611: // LBIndex should == value index.
612: dwLBIndex = SendMessage (GetDlgItem (hDlg, IDL_LISTBOX2),
613: LB_GETCURSEL, 0, 0);
614:
615: retCode = RegOpenKeyEx (hKeyRoot, // Key handle at root level.
616: RegPath, // Path name of child key.
617: 0, // Reserved.
618: KEY_EXECUTE, // Requesting read access.
619: &hKey); // Address of key to be returned.
620:
621: if (retCode)
622: {
623: wsprintf (Buf, "Error: RegOpenKeyEx = %d", retCode);
624: MessageBox (hDlg, Buf, "DisplayKeyData()", MB_OK);
625: return;
626: }
627:
628: // ADD A QUERY AND ALLOCATE A BUFFER FOR BDATA.
629:
630: retCode =
631: RegQueryInfoKey (hKey, // Key handle.
632: ClassName, // Buffer for class name.
633: &dwcClassLen, // Length of class string.
634: NULL, // Reserved.
635: &dwcSubKeys, // Number of sub keys.
636: &dwcMaxSubKey, // Longest sub key size.
637: &dwcMaxClass, // Longest class string.
638: &dwcValues, // Number of values for this key.
639: &dwcMaxValueName, // Longest Value name.
640: &dwcMaxValueData, // Longest Value data.
641: &dwcSecDesc, // Security descriptor.
642: &ftLastWriteTime); // Last write time.
643:
644: if (retCode)
645: {
646: wsprintf (Buf, "Error: RegQIK = %d, %d", retCode, __LINE__);
647: MessageBox (hDlg, Buf, "", MB_OK);
648: }
649:
650: bData = HeapAlloc (hHeap, dwcMaxValueData);
651: cbData = dwcMaxValueData;
652:
653:
654: // ENUMERATE THE KEY.
655:
656: retCode = RegEnumValue (hKey, // Key handle returned from RegOpenKeyEx.
657: dwLBIndex, // Value index, taken from listbox.
658: ValueName, // Name of value.
659: &cbValueName,// Size of value name.
660: NULL, // Reserved, dword = NULL.
661: &dwType, // Type of data.
662: bData, // Data buffer.
663: &cbData); // Size of data buffer.
664:
665: if (retCode)
666: {
667:
668: if (dwType < REG_FULL_RESOURCE_DESCRIPTOR)
669: {
670: wsprintf (Buf, "Error: RegEnumValue = %d, cbData = %d, line %d",
671: retCode, cbData, __LINE__);
672: MessageBox (hDlg, Buf, "", MB_OK);
673: }
674: }
675:
676:
677: switch (dwType)
678: {
679: // REG_NONE ( 0 ) // No value type
680: // REG_SZ ( 1 ) // Unicode nul terminated string
681: // REG_EXPAND_SZ ( 2 ) // Unicode nul terminated string
682: // (with environment variable references)
683: // REG_BINARY ( 3 ) // Free form binary
684: // REG_DWORD ( 4 ) // 32-bit number
685: // REG_DWORD_LITTLE_ENDIAN ( 4 ) // 32-bit number (same as REG_DWORD)
686: // REG_DWORD_BIG_ENDIAN ( 5 ) // 32-bit number
687: // REG_LINK ( 6 ) // Symbolic Link (unicode)
688: // REG_MULTI_SZ ( 7 ) // Multiple Unicode strings
689: // REG_RESOURCE_LIST ( 8 ) // Resource list in the resource map
690: // REG_FULL_RESOURCE_DESCRIPTOR ( 9 ) // Resource list in the hardware description
691:
692: case REG_NONE:
693: SetDlgItemText (hDlg, IDE_VALUE1, "REG_NONE: No defined value type.");
694: break;
695:
696: case REG_SZ:
697: SetDlgItemText (hDlg, IDE_VALUE1, "REG_SZ: A null-terminated Unicode string.");
698:
699: outBuf = HeapAlloc (hHeap, cbData + 2);
700: *outBuf = '\0';
701:
702: strcat (outBuf, "\"");
703: strcat (outBuf, bData);
704: strcat (outBuf, "\"");
705:
706: SetDlgItemText (hDlg, IDE_VALUE2, outBuf);
707: HeapFree (hHeap, outBuf);
708: break;
709:
710: case REG_EXPAND_SZ:
711: SetDlgItemText (hDlg, IDE_VALUE1, "REG_EXPAND_SZ: A String referencing environment variables i.e. PATH.");
712: outBuf = HeapAlloc (hHeap, cbData + 2);
713: *outBuf = '\0';
714:
715: strcat (outBuf, "\"");
716: strcat (outBuf, bData);
717: strcat (outBuf, "\"");
718:
719: SetDlgItemText (hDlg, IDE_VALUE2, outBuf);
720: HeapFree (hHeap, outBuf);
721: break;
722:
723: case REG_BINARY:
724:
725: SetDlgItemText (hDlg, IDE_VALUE1, "REG_BINARY: Freeform binary data.");
726: SetCursor (LoadCursor (NULL, IDC_WAIT));
727:
728: BinaryStrBuf = HeapAlloc (hHeap, (3 * cbData) + 1);
729: if (BinaryStrBuf)
730: {
731: *BinaryStrBuf = '\0';
732: *ByteBuf = '\0';
733: for (i = 0; i < cbData; i++)
734: {
735: sprintf (ByteBuf, "%02x ", (BYTE)bData[i]);
736: strcat (BinaryStrBuf, ByteBuf);
737: }
738: SetDlgItemText (hDlg, IDE_VALUE2, BinaryStrBuf);
739: }
740: else
741: {
742: MessageBox (hDlg, "Error: BinaryStrBuf = malloc failed",
743: "Debug: DisplayKeyData", MB_OK);
744: }
745: SetDlgItemText (hDlg, IDL_LISTBOX2, BinaryStrBuf);
746: HeapFree (hHeap, BinaryStrBuf);
747: SetCursor (LoadCursor (NULL, IDC_ARROW));
748:
749: break;
750:
751: case REG_DWORD:
752: SetDlgItemText (hDlg, IDE_VALUE1, "REG_DWORD: A 32 bit number.");
753: SetDlgItemInt (hDlg, IDE_VALUE2, *bData, TRUE);
754: break;
755:
756: case REG_DWORD_BIG_ENDIAN:
757: SetDlgItemText (hDlg, IDE_VALUE1, "REG_DWORD_BIG_ENDIAN: A 32 bit number in big endian format.");
758: SetDlgItemInt (hDlg, IDE_VALUE2, *bData, TRUE);
759: break;
760:
761: case REG_LINK:
762: SetDlgItemText (hDlg, IDE_VALUE1, "REG_LINK: A Unicode symbolic link.");
763: SetDlgItemText (hDlg, IDE_VALUE2, bData);
764: break;
765:
766: case REG_MULTI_SZ:
767: SetDlgItemText (hDlg, IDE_VALUE1, "REG_MULTI_SZ: An array of null-terminated strings.");
768: SetCursor (LoadCursor (NULL, IDC_WAIT));
769: // Count the NULLs in the buffer to
770: // find out how many strings there are.
771:
772: for (i=0, cStrLen=4; i < cbData; i++)
773: if (!bData[i])
774: cStrLen+=4; // Add room for two quotes and two
775: // spaced per string.
776:
777: outBuf = HeapAlloc (hHeap, cbData + cStrLen);
778:
779: ptr = bData; // Set ptr to beginning of buffer.
780: *outBuf = '\0'; // Initialize output string.
781:
782: strcat (outBuf, "{ "); // Do first bracket.
783: while (*ptr) // Loop til you hit 2 NULLs in a row.
784: {
785: strcat (outBuf, "\""); // Put quotes around each string.
786: strcat (outBuf, ptr);
787: strcat (outBuf, "\" ");
788: ptr += strlen(ptr)+1;
789: }
790: strcat (outBuf, "}"); // Add final bracket.
791: SetDlgItemText (hDlg, IDE_VALUE2, outBuf);
792:
793: SetCursor (LoadCursor (NULL, IDC_ARROW));
794: HeapFree (hHeap, outBuf); // free output string.
795: break;
796:
797:
798: case REG_RESOURCE_LIST: // CM_RESOURCE_LIST is kind of complex,
799: // it's defined in ntconfig.h. Print
800: // it as a free formed binary data now,
801: // and structure it later with a
802: // different release.
803: SetDlgItemText (hDlg, IDE_VALUE1, "REG_RESOURCE_LIST: A device-driver resource list.");
804:
805: BinaryStrBuf = HeapAlloc (hHeap, (3 * cbData) + 1);
806: if (BinaryStrBuf)
807: {
808: *BinaryStrBuf = '\0';
809: *ByteBuf = '\0';
810: for (i = 0; i < cbData; i++)
811: {
812: sprintf (ByteBuf, "%02x ", (BYTE)bData[i]);
813: strcat (BinaryStrBuf, ByteBuf);
814: }
815: SetDlgItemText (hDlg, IDE_VALUE2, BinaryStrBuf);
816: }
817: else
818: {
819: MessageBox (hDlg, "Error: BinaryStrBuf = malloc failed",
820: "Debug: DisplayKeyData", MB_OK);
821: }
822: SetDlgItemText (hDlg, IDL_LISTBOX2, BinaryStrBuf);
823: HeapFree (hHeap, BinaryStrBuf);
824:
825: break;
826:
827: case REG_FULL_RESOURCE_DESCRIPTOR:
828: SetDlgItemText (hDlg, IDE_VALUE1, "REG_FULL_RESOURCE_DESCRIPTOR: A resource list in the hardware description.");
829: break;
830:
831:
832:
833: default:
834: wsprintf (Buf, "Undefine in this verion of the Registry Monkey. %d",
835: dwType);
836: SetDlgItemText (hDlg, IDE_VALUE1, Buf);
837: break;
838:
839: } // end switch
840:
841:
842: HeapFree (hHeap, bData);
843: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.