Windows A Regedit bug or what happens if API documentation is fuzzy

Posted on

Registry keys and values have a maximum length, as documented on MSDN. For example, the maximum permitted length of a key is 255 characters – interestingly enough, the question of whether this includes or excludes the NULL terminator is left unanswered. May it be due to this fuzzy documentation or not, Microsoft’s tools and API do not quite seem to agree on a common interpretation of maximum key length, which revealed this little bug in Regedit.

Consider the following code snippet:

    #define SAMPLEKEY  \
      L"12345678901234567890123456789012345678901234567890" \
      L"12345678901234567890123456789012345678901234567890" \
      L"12345678901234567890123456789012345678901234567890" \
      L"12345678901234567890123456789012345678901234567890" \
      L"12345678901234567890123456789012345678901234567890" \
      L"12345"
    
    int wmain(int argc, WCHAR* argv[])
    {
      HKEY hKey;
      if ( NOERROR == RegCreateKeyEx(
        HKEY_CURRENT_USER,
        SAMPLEKEY,
        0,
        NULL,
        0,
        KEY_WRITE,
        NULL,
        &hKey,
        NULL ) )
      {
        RegCloseKey( hKey );
      }
    
      wprintf( L"Now open regedit and try to expand HKEY_CURRENT_USER...\n" );
      _getwch();
    
      RegDeleteKey(
        HKEY_CURRENT_USER,
        SAMPLEKEY );
      return 0;
    }
    

We create key of length 255 (plus the NULL terminator). Before deleting the key again, open regedit and try to open HKEY_CURRENT_USER – nothing happens, the tree does not expand, no error message, nothing. It appears as if all your keys have gone, but fortunately as soon as you delete the key, the key expands normally again.

So what is the problem? RegCreateKeyEx (on Vista x64) happily accepts my 255 character key – it even works with 256 characters (plus NULL terminator) – not before exceeding 257 characters, RegCreateKeyEx fails with ERROR_INVALID_PARAMETER.

On the other hand, Regedit seems to interpret the 255 character limit as including the NULL terminator and passes a buffer length of 0xFF (255) to RegEnumKey when asked to expand HKCU. Unsuprisingly, RegEnumKey fails with ERROR_MORE_DATA. As a result, regedit!KeyTree_ExpandBranch recognizing the error condition bails out and returns – and as no error message is shown, the user is left with the impression of that his keys are gone.

It is unlikely that this bug is ever going to bite you, but unless you know exactly which key is the culprit and can delete it programmatically, this could become quite annoying. Conclusion: It is a good idea to be precise when documenting APIs…

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.
« Back to home