我尝试在我的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;
}
但每次通话Error2
都会返回。我尝试了很多改变:
\\
)我想获得HKEY_LOCAL_MACHINE\SOFTWARE\World of RPG\Path
的路径:
任何人都可以帮助我吗?我做错了什么?
答案 0 :(得分:2)
在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[]
。
答案 1 :(得分: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 ++,但它仍然适用。)