|
|
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.