Oddity with Win32API, RegQueryValueEx

Hi all,

Ruby 1.8.4
Windows XP

I noticed something curious when using the RegQueryValueEx() function using straight C versus a Win32API wrapper. Whenever I call it via Win32API, it always returns ERROR_MORE_DATA (i.e. value 234) on the first call, not matter what I set the buffer size to.

Here's a sample C program that works fine:

#include <windows.h>
#include <stdio.h>

int main(){
    char* key = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\SNDSrvc";
    char* val = "EventMessageFile";
    char buf[1024];
    DWORD size;
    int rv;
    HKEY hk;

    rv = RegOpenKeyEx(
       HKEY_LOCAL_MACHINE,
       key,
       0,
       KEY_READ,
       &hk
    );

    if(rv == ERROR_SUCCESS){
       rv = RegQueryValueEx(hk, val, NULL, NULL, buf, &size);
       if(rv == ERROR_SUCCESS){
          printf("Success!\n");
          printf("Size: %i\n", size);
          printf("Buf: %s\n", buf);
          RegCloseKey(hk);
       }
       else{
          printf("Failure: %i\n", GetLastError());
       }
    }

    return 0;
}

However, the equivalent Ruby program always returns ERROR_MORE_DATA:

require 'Win32API'

HKEY_LOCAL_MACHINE = 0x80000002
KEY_READ = 0x20019

RegCloseKey = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
RegOpenKeyEx = Win32API.new('advapi32', 'RegOpenKeyEx', 'LPLLP', 'L')
RegQueryValueEx = Win32API.new('advapi32', 'RegQueryValueEx', 'LPLPPP', 'L')

val = 'EventMessageFile'
key = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\SNDSrvc"
hk = [0].pack('L')

if RegOpenKeyEx.call(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, hk) == 0
    hk = hk.unpack('L').first
    buf = 0.chr * 1024
    size = 0.chr * 4

    p RegQueryValueEx.call(hk, val, 0, 0, buf, size) # 234
end

The size checks out at 58 (as it does in the C program), so I don't understand why I'm getting a 234 back. It's not a huge deal, mind you, since I can just call it again, but I thought it was odd.

Any ideas?

Thanks,

Dan

Hi,

From: Daniel Berger <djberg96@gmail.com>
Reply-To: ruby-talk@ruby-lang.org
To: ruby-talk@ruby-lang.org (ruby-talk ML)
Subject: Oddity with Win32API, RegQueryValueEx
Date: Mon, 15 May 2006 18:45:19 +0900

Hi all,

Ruby 1.8.4
Windows XP

I noticed something curious when using the RegQueryValueEx() function using straight C versus a Win32API wrapper. Whenever I call it via Win32API, it always returns ERROR_MORE_DATA (i.e. value 234) on the first call, not matter what I set the buffer size to.

Here's a sample C program that works fine:

#include <windows.h>
#include <stdio.h>

int main(){
   char* key = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\SNDSrvc";
   char* val = "EventMessageFile";
   char buf[1024];
   DWORD size;
   int rv;
   HKEY hk;

   rv = RegOpenKeyEx(
      HKEY_LOCAL_MACHINE,
      key,
      0,
      KEY_READ,
      &hk
   );

   if(rv == ERROR_SUCCESS){
      rv = RegQueryValueEx(hk, val, NULL, NULL, buf, &size);
      if(rv == ERROR_SUCCESS){
         printf("Success!\n");
         printf("Size: %i\n", size);
         printf("Buf: %s\n", buf);
         RegCloseKey(hk);
      }
      else{
         printf("Failure: %i\n", GetLastError());
      }
   }

   return 0;
}

However, the equivalent Ruby program always returns ERROR_MORE_DATA:

require 'Win32API'

HKEY_LOCAL_MACHINE = 0x80000002
KEY_READ = 0x20019

RegCloseKey = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
RegOpenKeyEx = Win32API.new('advapi32', 'RegOpenKeyEx', 'LPLLP', 'L')
RegQueryValueEx = Win32API.new('advapi32', 'RegQueryValueEx', 'LPLPPP', 'L')

val = 'EventMessageFile'
key = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\SNDSrvc"
hk = [0].pack('L')

if RegOpenKeyEx.call(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, hk) == 0
   hk = hk.unpack('L').first
   buf = 0.chr * 1024
   size = 0.chr * 4

should be
      size = [buf.length].pack('L')

   p RegQueryValueEx.call(hk, val, 0, 0, buf, size) # 234
end

The size checks out at 58 (as it does in the C program), so I don't understand why I'm getting a 234 back. It's not a huge deal, mind you, since I can just call it again, but I thought it was odd.

size is [in, out] pointer to a variable that specifies the size, in bytes, of the buffer pointed to by the buf parameter

Regards,

Park Heesob