سؤال

i try to read the Registry in my NPAPI-Plugin:

bool ScriptablePluginObject::Invoke(NPObject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) {
    ScriptablePluginObject *thisObj = (ScriptablePluginObject*) obj;
    char* name                      = npnfuncs->utf8fromidentifier(methodName);
    LPCWSTR game_path               = getRegKey(L"SOFTWARE\\World of RPG", L"Path");

    MessageBox(NULL, game_path, L"Debugging", MB_TOPMOST);

    /* ... */
}

LPCWSTR ScriptablePluginObject::getRegKey(LPCWSTR location, LPCWSTR name) {
    HKEY hKey;
    LPBYTE folder   = new BYTE[MAX_PATH];
    DWORD dwSize    = sizeof(folder);
    long registry   = RegOpenKeyEx(HKEY_LOCAL_MACHINE, location, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
    long entry      = RegQueryValueEx(hKey, name, NULL, REG_NONE, folder, &dwSize);

    if(registry != ERROR_SUCCESS) {
        return L"Error1";
    }

    if(entry != ERROR_SUCCESS) {
        return L"Error2";
    }

    RegCloseKey(hKey);
    folder[dwSize / sizeof(folder[0])] = '\0';
    return (LPCWSTR) folder;
}

But it's returned every call Error2. I've tried a lot of changes:

  • change the Path (with Start and/or Ending \\)
  • change parameters

I Want to get the Path of HKEY_LOCAL_MACHINE\SOFTWARE\World of RPG\Path:

enter image description here

Anyone can help me? What i'm doing wrong?

هل كانت مفيدة؟

المحلول 2

In getRegKey(), your folder variable is a pointer, so sizeof(folder) is 4 (if compiling for 32bit) or 8 (if compiling for 64bit). Thus RegQueryValueEx() fails with an ERROR_MORE_DATA error code.

You are also using the wrong data type for the array. You need to use WCHAR instead of BYTE.

Change this:

LPBYTE folder   = new BYTE[MAX_PATH];
DWORD dwSize    = sizeof(folder);

To this:

LPWSTR folder   = new WCHAR[MAX_PATH];
DWORD dwSize    = sizeof(WCHAR) * MAX_PATH;

With that said, you are leaking the memory pointed to by folder, since you never delete[] it.

نصائح أخرى

Here's the sample I mentioned in the comments above:

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

LSTATUS ReadRegistry ( LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, DWORD *pBufferSize );

int _tmain(int argc, _TCHAR* argv[])
{
    const int BUFFER_SIZE = 1024;

    WCHAR sBuffer[BUFFER_SIZE]; // 2048 bytes
    DWORD nBufferSize = BUFFER_SIZE * sizeof ( WCHAR );

    ZeroMemory ( sBuffer, nBufferSize );
    LSTATUS nResult = ReadRegistry ( L"SOFTWARE\\7-Zip", L"Path64",
        sBuffer, &nBufferSize );

    // check nResult for ERROR_SUCCESS to know if the call succeeded or not

    return 0;
}

LSTATUS ReadRegistry ( LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, LPDWORD pBufferSize )
{
    HKEY hKey;
    LSTATUS nResult = ::RegOpenKeyEx ( HKEY_LOCAL_MACHINE, sPath,
        0, KEY_READ | KEY_WOW64_64KEY, &hKey );

    if ( nResult == ERROR_SUCCESS )
    {
        nResult = ::RegQueryValueEx ( hKey, sKey, NULL, NULL,
            (LPBYTE) pBuffer, pBufferSize );

        RegCloseKey ( hKey );
    }

    return ( nResult );
}

Notice how the ReadRegistry function doesn't allocate memory - it takes a buffer and fills it with data. It's a lot easier to deal with memory if you always have the caller allocate memory. If the callee allocates memory, the caller may not know how memory was allocated and it may not know how to free it. (Of course, you can always assume the use of new and delete but things are simpler if only one side does this consistently. If the caller allocates memory, it'll know how to free it. The callee only needs to put data in the allocated space.

Also, notice how the return value of the API functions is checked before proceeding to the next call - this is important because this tells you if you got a useful registry handle back or not and whether you need to close it or not.

(This sample is really just C, not C++ but it still applies.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top