Search code examples
windowsdelphiwinapiregistry

Some CLSID Registry keys exist but cannot be read


I have following program that reads all CLSID registry keys and displays their name on a listbox; it is written in Delphi, but the question is not specific to Delphi; it is rather a question about the Windows Registry.

procedure TForm2.Button1Click(Sender: TObject);
var
  guid: string;
  reg: TRegistry;
  sl: TStringList;
  i: Integer;
  name: string;
begin
  memo1.Clear;

  reg := TRegistry.Create;
  sl := TStringList.Create;
  memo1.Lines.BeginUpdate;
  try
    reg.RootKey := HKEY_CLASSES_ROOT;
    if reg.OpenKeyReadOnly('\CLSID\') then
    begin
      reg.GetKeyNames(sl);
      reg.CloseKey;

      for i := 1 to sl.Count-1 do
      begin
    guid := sl.Strings[i];

    if reg.OpenKeyReadOnly('\CLSID\'+guid) then
    begin
      try
        name := reg.ReadString('');
      except
        name := '!!! <ERROR1> !!!';
      end;
      reg.CloseKey;
    end;

    memo1.Lines.Add(guid + ' ' + name);
      end;
    end;
  finally
    sl.Free;
    reg.Free;
    memo1.Lines.EndUpdate;
  end;
end;

The problem is that following registry keys do exist (they are listed in GetKeyNames), but they cannot be read (reading the default value). I get the Exception "Invalid data type for ''".

The keys which fail are:

{33297C9D-2A25-1679-1475-A1CE3901C86D} !!! <ERROR1> !!!
{45049248-47E9-7CEE-A822-1E555F74D237} !!! <ERROR1> !!!
{69C5BE90-E717-97A6-CCEF-C44D93111A5A} !!! <ERROR1> !!!
{8663D540-C578-44AE-9D24-4A9D9A4881C3} !!! <ERROR1> !!!
{9A73B3FA-50DF-3410-930D-51C35FC9237E} !!! <ERROR1> !!!
{EACF7497-3D67-8044-DE95-81429597BB8F} !!! <ERROR1> !!!

These keys do not appear in regedit.exe, even if I run RegEdit in the NT-AUTHORITY\SYSTEM context (which shows really everything).

Do you have the same problem, or is my registry somehow damaged?


Solution

  • The obvious explanation is that the keys exist but you look for them in the wrong place. I bet you have a 32 bit process on a 64 bit machine and the keys are redirected by the registry redirector.

    Look for the 32 bit CLSID section in regedit under

    HKCR\Wow6432Node\CLSID
    

    More useful information can be found at Registry Keys Affected by WOW64 on MSDN.

    Then when you've located the key, it would seem that the default value does not have the data type that you expect. You are expecting a string, but some keys clearly have a different type. You'll need to add some resiliency to your program to deal with that.

    Taking your first CLSID, on my machine indeed it is not to be found under HKCR\CLSID, the 64 bit registry. But under HKCR\Wow6432Node\CLSID\{33297C9D-2A25-1679-1475-A1CE3901C86D} is present. And the default value has type REG_BINARY.

    So, to summarise, here are my conclusions:

    • Your registry is fine.
    • Your program reads from the 32 bit view, but you have been looking in the 64 bit view in regedit.
    • Not all CLSID keys use REG_SZ for their default value.

    Should you decide that you want to read from a different registry view than that matched to your program's bitness, use the KEY_WOW64_64KEY or KEY_WOW64_32KEY flags to specify the view. As detailed in Accessing an Alternate Registry View. In your case you might use KEY_WOW64_64KEY to read from the 64 bit view.


    As an aside, your for loop should start from 0 rather than 1.