0

Im trying to get all my comports from the registry. Unfortunately i always recieve the ERROR_MORE_DATA error... I already tried to make my buffer bigger, but it wont help at all. Here is my code:

DWORD registry::regGetValue(char *key, int index)
{
HKEY hKey; 
 RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM",0,KEY_ALL_ACCESS,&hKey);
     DWORD chars = sizeof(key);
     LONG result = RegEnumValue(hKey, index, key, &chars, 0,0,0,0 );
 RegCloseKey(hKey);
 return result;
}

Parameters are:

char key[512];
int index = 0;
2
  • 2
    sizeof(key) is 4 because it is a pointer. Pass the actual size of the buffer to your function and use that. Commented Jul 25, 2013 at 12:55
  • thanks a lot man, works perfectly. The problem was that i always tried to get the size with sizeof(), even when i wanted to get the size of a static number. Solution is: DWORD chars = 512; Commented Jul 25, 2013 at 13:47

2 Answers 2

2

The buffer is likely big enough, you're just lying to the function about its actual size.

When you use the sizeof operator on a pointer, it returns the size of the pointer, not the size of the array to which it points. And because key is passed to the function as a char*, it is merely a pointer to the array, not the array itself.

You have to pass the actual size of the buffer to your function as a parameter along with the pointer:

DWORD regGetValue(char *key, size_t length, int index)
{
   HKEY hKey; 
   RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM",0,KEY_ALL_ACCESS,&hKey);
   DWORD chars = length;
   LONG result = RegEnumValue(hKey, index, key, &chars, 0,0,0,0 );
   RegCloseKey(hKey);
   return result;
}
char key[512];
int index = 0;
regGetValue(key, sizeof(key), index);

The sizeof operator works as expected here because it's operating on the array itself, not merely a pointer to it. This approach, however common in C APIs, is cumbersome.

You can simplify things at the call site a bit by using a function template that automatically deduces the size of your buffer and passes it to an internal helper function that actually does the work:

// Helper function, implemented as a private member of your class
DWORD regGetValue(char *key, size_t length int index)
{
   HKEY hKey; 
   RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM",0,KEY_ALL_ACCESS,&hKey);
   DWORD chars = length;
   LONG result = RegEnumValue(hKey, index, key, &chars, 0,0,0,0 );
   RegCloseKey(hKey);
   return result;
}

// The public function that you will actually call
template <size_t N>
DWORD regGetValue(char (&key)[N], int index)
{
   return regGetValue(key, N, index);
}
char key[512];
int index = 0;
regGetValue(key, index);  // length determined and passed automatically

This works because you pass a reference to the array, rather than a pointer.

Aside from all of that, I have to seriously question why you're calling ANSI functions and using char* for your strings. All modern Windows applications should be Unicode. That means calling the W-suffixed versions of the Windows API functions and using wchar_t* as your string type. Make sure that both the UNICODE and _UNICODE symbols are defined for your project, and you'll get a compile-time error if you use the wrong type.

Sign up to request clarification or add additional context in comments.

Comments

0

MSDN says: If the lpName buffer is too small to receive the name of the key, the function returns ERROR_MORE_DATA. Before you call RegEnumKeyEx, you can call function RegQueryInfoKey to determine the size of the largest subkey for the key identified by hKey. The usage of RegQueryInfoKey can find here: "http://msdn.microsoft.com/en-us/library/windows/desktop/ms724902(v=vs.85).aspx"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.