Windows — C ++ читать реестр

я пытаюсь прочитать реестр в моем NPAPI-плагине:

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;
}

Но он возвращается каждый звонок Error2, Я перепробовал много изменений:

  • изменить путь (с помощью Start и / или Ending \\)
  • изменить параметры

Я хочу получить Путь HKEY_LOCAL_MACHINE\SOFTWARE\World of RPG\Path:

введите описание изображения здесь

Кто-нибудь может мне помочь? Что я делаю не так?

0

Решение

В getRegKey(), ваш folder переменная является указателем, так sizeof(folder) равно 4 (если компилируется для 32-битного) или 8 (если компилируется для 64-битного). таким образом RegQueryValueEx() терпит неудачу с ERROR_MORE_DATA код ошибки.

Вы также используете неправильный тип данных для массива. Вам нужно использовать WCHAR вместо BYTE,

Изменить это:

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

К этому:

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

С учетом сказанного вы теряете память, на которую указывает folder, так как ты никогда delete[] Это.

2

Другие решения

Вот пример, который я упомянул в комментариях выше:

#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 );
}

Обратите внимание, как ReadRegistry функция не выделяет память — она ​​берет буфер и заполняет его данными. Намного легче иметь дело с памятью, если у вас всегда есть память, выделяемая вызывающим абонентом. Если вызываемый объект выделяет память, вызывающий может не знать, как была выделена память, и может не знать, как ее освободить. (Конечно, вы всегда можете взять на себя использование new а также delete но все проще, если только одна сторона делает это последовательно. Если вызывающая сторона выделяет память, она знает, как ее освободить. Вызываемый должен только поместить данные в выделенное пространство.

Кроме того, обратите внимание, как проверяется возвращаемое значение функций API, прежде чем переходить к следующему вызову — это важно, потому что это говорит вам, получили ли вы полезный дескриптор реестра или нет, и нужно ли вам его закрывать или нет.

(Этот пример на самом деле просто C, а не C ++, но он все еще применяется.)

2

По вопросам рекламы [email protected]