home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / registry / monkey.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  31KB  |  876 lines

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