title: Enumerating Registry Subkeys
body: <p>from msdn.microsoft.com - Enumerating Registry Subkeys:</p>
  
  <p><a href="http://msdn.microsoft.com/En-US/library/ms724256.aspx" rel="nofollow">http://msdn.microsoft.com/En-US/library/ms724256.aspx</a></p>
  
  <pre><code>// QueryKey - Enumerates the subkeys of key and its associated values.
  //     hKey - Key whose subkeys and values are to be enumerated.
  
  #include &lt;windows.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;tchar.h&gt;
  
  #define MAX_KEY_LENGTH 255
  #define MAX_VALUE_NAME 16383
  
  void QueryKey(HKEY hKey) 
  { 
      TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
      DWORD    cbName;                   // size of name string 
      TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
      DWORD    cchClassName = MAX_PATH;  // size of class string 
      DWORD    cSubKeys=0;               // number of subkeys 
      DWORD    cbMaxSubKey;              // longest subkey size 
      DWORD    cchMaxClass;              // longest class string 
      DWORD    cValues;              // number of values for key 
      DWORD    cchMaxValue;          // longest value name 
      DWORD    cbMaxValueData;       // longest value data 
      DWORD    cbSecurityDescriptor; // size of security descriptor 
      FILETIME ftLastWriteTime;      // last write time 
  
      DWORD i, retCode; 
  
      TCHAR  achValue[MAX_VALUE_NAME]; 
      DWORD cchValue = MAX_VALUE_NAME; 
  
      // Get the class name and the value count. 
      retCode = RegQueryInfoKey(
          hKey,                    // key handle 
          achClass,                // buffer for class name 
          &amp;cchClassName,           // size of class string 
          NULL,                    // reserved 
          &amp;cSubKeys,               // number of subkeys 
          &amp;cbMaxSubKey,            // longest subkey size 
          &amp;cchMaxClass,            // longest class string 
          &amp;cValues,                // number of values for this key 
          &amp;cchMaxValue,            // longest value name 
          &amp;cbMaxValueData,         // longest value data 
          &amp;cbSecurityDescriptor,   // security descriptor 
          &amp;ftLastWriteTime);       // last write time 
  
      // Enumerate the subkeys, until RegEnumKeyEx fails.
  
      if (cSubKeys)
      {
          printf( "\nNumber of subkeys: %d\n", cSubKeys);
  
          for (i=0; i&lt;cSubKeys; i++) 
          { 
              cbName = MAX_KEY_LENGTH;
              retCode = RegEnumKeyEx(hKey, i,
                       achKey, 
                       &amp;cbName, 
                       NULL, 
                       NULL, 
                       NULL, 
                       &amp;ftLastWriteTime); 
              if (retCode == ERROR_SUCCESS) 
              {
                  _tprintf(TEXT("(%d) %s\n"), i+1, achKey);
              }
          }
      } 
  
      // Enumerate the key values. 
  
      if (cValues) 
      {
          printf( "\nNumber of values: %d\n", cValues);
  
          for (i=0, retCode=ERROR_SUCCESS; i&lt;cValues; i++) 
          { 
              cchValue = MAX_VALUE_NAME; 
              achValue[0] = '\0'; 
              retCode = RegEnumValue(hKey, i, 
                  achValue, 
                  &amp;cchValue, 
                  NULL, 
                  NULL,
                  NULL,
                  NULL);
  
              if (retCode == ERROR_SUCCESS ) 
              { 
                  _tprintf(TEXT("(%d) %s\n"), i+1, achValue); 
              } 
          }
      }
  }
  
  void __cdecl _tmain(void)
  {
     HKEY hTestKey;
  
     if( RegOpenKeyEx( HKEY_CURRENT_USER,
          TEXT("SOFTWARE\\Microsoft"),
          0,
          KEY_READ,
          &amp;hTestKey) == ERROR_SUCCESS
        )
     {
        QueryKey(hTestKey);
     }
  
     RegCloseKey(hTestKey);
  }
  </code></pre>
  
  <p>how can i modify that code at:</p>
  
  <pre><code>cchValue = MAX_VALUE_NAME; 
              achValue[0] = '\0'; 
              retCode = RegEnumValue(hKey, i, 
                  achValue, 
                  &amp;cchValue, 
                  NULL, 
                  NULL,
                  NULL,
                  NULL);
  
              if (retCode == ERROR_SUCCESS ) 
              { 
                  _tprintf(TEXT("(%d) %s\n"), i+1, achValue); 
              } 
  </code></pre>
  
  <p>to output to the console all the values that RegEnumValue function can return,
  function at msdn:
  <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724865%28v=vs.85%29.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/windows/desktop/ms724865%28v=vs.85%29.aspx</a>
  i want to output these vars too:</p>
  
  <pre><code>  __out        LPTSTR lpValueName,
    __inout      LPDWORD lpcchValueName,
    __out_opt    LPDWORD lpType,
    __out_opt    LPBYTE lpData,
    __inout_opt  LPDWORD lpcbData
  </code></pre>
  
  <p>i have tried different things but everytime i change any of NULL var from
  that function:             </p>
  
  <p>retCode = RegEnumValue(hKey, i, 
                      achValue, 
                      &amp;cchValue, 
                      NULL, 
                      NULL,
                      NULL,
                      NULL);</p>
  
  <p>i even don´t get achValue</p>
  
  <p>thanks a lot</p>
  
  <p>PD using windows 7 64 bits visual studio 2010 ultimate</p>