Code Example for People: Reading 32 or 64-bit Registry from a 32-bit Application lazarus / 34-Windows ---------------------------------------------------------------------- seier · 2012-08-30 02:22 Hi Gang, I had so much trouble reading the 64-bit registry from a 32-bit application that I thought I'd post the working result so others might have less trouble in the future.  For starters, I didn't realize that 32-bit applications are segmented to a different chunk of the registry than native 64-bit applications.  Cheers, Christian Blackburn Code: [Select]uses   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, LCLType, StdCtrls, Windows; const     KEY_WOW64_64KEY = $000000100; function IsWin64: boolean; { Detect if we are running on 64 bit Windows or 32 bit Windows, independently of bitness of this program. Original source: http://www.delphipraxis.net/118485-ermitteln-ob-32-bit-oder-64-bit- betriebssystem.html modified for FreePascal in German Lazarus forum: http://www.lazarusforum.de/viewtopic.php?f=55&t=5287 } {$ifdef WIN32} //Modified KpjComp for 64bit compile mode type   TIsWow64Process = function( // Type of IsWow64Process API fn       Handle: Windows.THandle; var Res: Windows.BOOL): Windows.BOOL; stdcall; var   IsWow64Result: Windows.BOOL; // Result from IsWow64Process   IsWow64Process: TIsWow64Process; // IsWow64Process fn reference begin   // Try to load required function from kernel32   IsWow64Process := TIsWow64Process(Windows.GetProcAddress(     Windows.GetModuleHandle('kernel32'), 'IsWow64Process'));   if Assigned(IsWow64Process) then   begin     // Function is implemented: call it     if not IsWow64Process(Windows.GetCurrentProcess, IsWow64Result{%H-}) then       raise SysUtils.Exception.Create('IsWindows64: bad process handle');     // Return result of function     Result := IsWow64Result;   end   else     // Function not implemented: can't be running on Wow64     Result := False; {$else} //if were running 64bit code, OS must be 64bit :) begin  Result := True; {$endif} end; function RegReadString(pcKey_Path:pchar; pcValue_Name:Pchar; hkRoot:hkey=HKEY_LOCAL_MACHINE):String; var   hkCurrent: HKEY;   chrValue: array[0..512] of Char;   dwLength: DWORD;   intCode: integer;   dwType:DWORD;   strError: String; begin     //Tells RegQueryValueEx that we want a string value     dwType := reg_SZ;    // if the (32-bit) program is running on 64-bit Windows    if isWin64 then    begin         try             //opens the appropriate key             //ask for the 64-bit registry path: KEY_WOW64_64KEY             if RegOpenKeyEx( hkRoot ,pcKey_Path,0, KEY_QUERY_VALUE + KEY_WOW64_64KEY, hkCurrent {%H-})=ERROR_SUCCESS then              begin                 intCode:=RegQueryValueEx(hkCurrent, pcValue_Name, nil, @dwType, @chrValue, @dwLength);                 if (intCode=ERROR_SUCCESS) then                 begin                     result:=chrValue;                 end                 else                 begin                     strError := 'There was an error detecting your current registration information in the registry. The Error Code was: '+IntToStr(intCode)+'.';                     MessageDlg('Registry Error A', strError, mtWarning, [mbOK], 0);                 end;             end             else                 begin                     strError := 'There was an error loading your current registration information from the registry. The Key Path:' + strPas(pcKey_Path) + ' could not be opened.';                     MessageDlg('Registry Error B', strError, mtWarning, [mbOK], 0);                 end;         except             strError := 'There was an unknown error accessing the registry. The Key Path:' + strPas(pcKey_Path) + ' or value ' + strPas(pcValue_Name) + ' could not be opened.';             MessageDlg('Registry Error C', strError, mtERROR,  [mbOK], 0);        end;    end    // is 32-bit Windows    else    begin         try             //opens the appropriate key             //ask for the 64-bit registry path: KEY_WOW64_64KEY             if RegOpenKeyEx( hkRoot ,pcKey_Path,0, KEY_QUERY_VALUE, hkCurrent )=ERROR_SUCCESS then             begin                 intCode:=RegQueryValueEx(hkCurrent, pcValue_Name, nil, @dwType, @chrValue, @dwLength);                 if (intCode=ERROR_SUCCESS) then                 begin                     result:=chrValue;                 end                 else                 begin                     strError := 'There was an error detecting your current registration information in the registry. The Error Code was: '+IntToStr(intCode)+'.';                     MessageDlg('Registry Error A', strError, mtWarning, [mbOK], 0);                 end;             end             else                 begin                     strError := 'There was an error loading your current registration information from the registry. The Key Path:' + strPas(pcKey_Path) + ' could not be opened.';                     MessageDlg('Registry Error B', strError, mtWarning, [mbOK], 0);                 end;         except             strError := 'There was an unknown error accessing the registry. The Key Path:' + strPas(pcKey_Path) + ' or value ' + strPas(pcValue_Name) + ' could not be opened.';             MessageDlg('Registry Error C', strError, mtERROR,  [mbOK], 0);        end;    end;    //Closes the otherwise open access to the current registry key    RegCloseKey(hkCurrent); end;  procedure RegWriteString(intParent_Key: integer; strPath: string; strValue_Name: string; strValue: string); var   hkCurrent: HKEY; begin   // is 64-bit Windows   if isWin64 then   begin      if RegOpenKeyEx(intParent_key, Pchar(strPath), 0, KEY_WRITE + KEY_WOW64_64KEY, hkCurrent {%H-})  = ERROR_SUCCESS then      begin          RegSetValueEx(hkCurrent, pchar(strValue_Name), 0, REG_SZ, PChar(strValue), Length(strValue) + 1); // The 1 is for the terminating 0 (PChar)     end;   end   // is 32-bit Windows   else   begin     if RegOpenKeyEx( intParent_key,pchar(strPath),0, KEY_WRITE, hkCurrent )  = ERROR_SUCCESS then     begin       RegSetValueEx(hkCurrent, pchar(strValue_Name), 0, REG_SZ, PChar(strValue), Length(strValue) + 1); // The 1 is for the terminating 0 (PChar)     end;   end;   RegCloseKey(hkCurrent); // Close the open registry key end; ---------------------------------------------------------------------- exdatis · 2012-08-30 05:21 Thanks! Regards! ---------------------------------------------------------------------- u2o · 2014-12-17 05:02 @Christian: I used your code for some time, it really helped me in my projects. However I would like to make a correction to solve a random error. Quote from: seier on August 30, 2012, 04:22:05 amCode: [Select]intCode:=RegQueryValueEx(hkCurrent, pcValue_Name, nil, @dwType, @chrValue, @dwLength); Some times RegQueryValueEx return the error 234 (ERROR_MORE_DATA), Although this does not always happen, it is very usual. To prevent this from happening, you need to set a value to dwLength before making the call. For example: Code: [Select]dwLength := SizeOf(dwLength); intCode := RegQueryValueEx(hkCurrent, pcValue_Name, nil, @dwType, @chrValue, @dwLength); I hope to help as well. And although late thank you very much!