Search code examples
c++windowswinapiregistrykey

How to recover all the elements of a registry key? (last write time, type, value, name …) Is this the right method?


I would like to recover all the elements of a registry key. the methods of the windows API RegOpenEX and RegEnumKeyEx.But I'm not sure this is the right way to do that. Here is an example of my code, so should these two methods be used to retrieve this information?

HKEY RegHkey;
Long RC=0;
DWORD a=0;
DWORD TMP=255;
FILETIME filetime;
LPWSTR lpName=nullptr;
LPWSTR lpClass=nullptr;
DWORD cchClasss=0;

RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\",0,KEY_READ,&RegHkey);

while(RC != ERROR_NO_MORE_ITEMS)
{
  RC=RegEnumKeyEx(RegHkey, a, lpName, &TMP, nullptr, lpClass, &cchClass, &filetime);
   if(RC==ERROR_SUCCESS)
   {
      std::cout<<"type= "<<cchClass<<std::endl;
     //etc...

   }
   a++;
}

if RC==ERROR_SUCCESS I would like to retrieve the type, value, and last_write_time.... Is this the right method?


Solution

  • Unfortunately, almost everything is wrong in this code.

    LPWSTR lpName=nullptr;
    LPWSTR lpClass=nullptr;
    

    Whenever the documentation for a function parameter says something like "A pointer to a buffer", you are required to provide a buffer, that you have allocated.

    // The {} brackets zero-initialize the buffers.
    wchar_t szName[255]{};
    wchar_t szClass[255]{};
    
    DWORD TMP=255;
    DWORD cchClasss=0;
    

    Setting cchClass to zero is wrong. You have to tell the function, how big your buffers actually are (how many characters including '\0' it can store there). The variable TMP has no meaningful name, cchName will be more consistent:

    // No need to hardcode the array size.
    DWORD cchName  = ARRAYSIZE(szName);
    DWORD cchClass = ARRAYSIZE(szClass);
    
    RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\",0,KEY_READ,&RegHkey);
    

    Missing a check for the success of the function. Opening a registry key can fail for a wide variety of reasons, e. g. not enough permissions:

    DWORD res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\",0,KEY_READ,&RegHkey);
    if(res == ERROR_SUCCESS)
    {
        // do something with the registry key
    } 
    
    while(RC != ERROR_NO_MORE_ITEMS)
    

    You have an endless loop when RegEnumKeyEx fails for other reasons than finishing enumeration. Correct condition would be RC == ERROR_SUCCESS.

      RC=RegEnumKeyEx(RegHkey, a, lpName, &TMP, nullptr, lpClass, &cchClass, &filetime);
    

    The children of the registry key SOFTWARE\Microsoft\Windows\CurrentVersion\Run\ are values, so you have to use RegEnumValueW() instead.

    Make sure you also call RegCloseKey() once you are done with the registry key.