C++: Access embedded resource from dll - c++

I have a c++ dll project, in which, I have embedded some raw data through "resource.rc" file.
IDR_TEMPLATE1 RCDATA "areaTemplate.bin"
Now I want to access the data of "areaTemplate.bin" file from the dll. How can I read the contents of "areaTemplate.bin" in a byte array?

As Manuell says, you use FindResource(), LoadResource() and probably LockResource() and SizeofResource()
I happen to have some code which does pulls out a resource and writes it to a file, and may help with your understanding of the API in question.
void WriteResourceToFile(
HANDLE hFile,
const _tstring &resourceName,
const _tstring &resourceType,
HMODULE hModule)
{
HRSRC hResource = ::FindResource(
hModule,
resourceName.c_str(),
resourceType.c_str());
if (!hResource)
{
const DWORD lastError = ::GetLastError();
throw CWin32Exception(
_T("WriteResourceToFile() - FindResource"),
lastError);
}
HGLOBAL hGlobal = ::LoadResource(hModule, hResource);
if (!hGlobal)
{
const DWORD lastError = ::GetLastError();
throw CWin32Exception(
_T("WriteResourceToFile() - LoadResource"),
lastError);
}
void *pData = ::LockResource(hGlobal);
if (!pData)
{
const DWORD lastError = ::GetLastError();
throw CWin32Exception(
_T("WriteResourceToFile() - LockResource"),
lastError);
}
const DWORD bytes = ::SizeofResource(hModule, hResource);
DWORD bytesWritten = 0;
if (!::WriteFile(hFile, pData, bytes, &bytesWritten, 0))
{
const DWORD lastError = ::GetLastError();
throw CWin32Exception(
_T("WriteResourceToFile() - WriteFile"),
lastError);
}
if (bytesWritten != bytes)
{
throw CWin32Exception(
_T("WriteResourceToFile() - WriteFile"),
_T("Wrote less bytes (") + ToString(bytesWritten) +
_T("( than expected: ") + ToString(bytes));
}
}

First use FindResource or FindResourceEx, then use LoadResource and LockResource.
Use SizeofResource to get the size of datas.
Code:
HMODULE g_hModDll;
[...]
HRSRC hRscr = FindResource( g_hModDll, MAKEINTRESOURCE( IDR_TEMPLATE1 ),
MAKEINTRESOURCE( RT_RCDATA ) );
if ( hRscr ) {
HGLOBAL hgRscr = LoadResource( g_hModDll, hRscr );
if ( hgRscr ) {
PVOID pRscr = LockResource( hgRscr );
DWORD cbRscr = SizeofResource( g_hModDll, hRscr );
}
}
Be sure to read the following remark about LoadResource:
Remarks The return type of LoadResource is HGLOBAL for backward
compatibility, not because the function returns a handle to a global
memory block. Do not pass this handle to the GlobalLock or GlobalFree
function.
There is no "unlock resource" or "free resource" APIs.
Remarks The pointer returned by LockResource is valid until the module
containing the resource is unloaded. It is not necessary to unlock
resources because the system automatically deletes them when the
process that created them terminates.

// Determine the module handle of your DLL by locating a function
// you know resides in that DLL
HMODULE hModule;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)&myDLLfuncName, &hModule)
HRSRC hRscr = FindResource(hModule, MAKEINTRESOURCE(IDR_TEMPLATE1),
MAKEINTRESOURCE(RT_RCDATA));

Related

Anyone has experience on using GetAppContainerNamedObjectPath?

Recently I came across a Windows API called GetAppContainerNamedObjectPath. But I have no idea on how I can use it.
I found a msdn page for this api (https://learn.microsoft.com/en-us/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath). But it does not have a right example and remarks, parameters are written poorly.
I am getting ERROR_INVALID_PARAMETER(87) error at the end, which tells me something's wrong with the parameters that I put. Here's what I've tried.
#define TokenIsAppContainer 29
#define TokenAppContainerSid 31
#define TokenAppContainerNumber 32
typedef struct _TOKEN_APPCONTAINER_INFORMATION {
PSID TokenAppContainer;
} TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION;
void GetAppContainerProcessInfo(CString & procName)
{
DWORD dwSize = 0;
DWORD dwResult;
HANDLE hToken;
PTOKEN_APPCONTAINER_INFORMATION pAppCoInfo;
WCHAR wcsDebug[1024] = {0,};
WCHAR * pwSID = NULL;
typedef BOOL (WINAPI *_LPGETAPPCONTAINERNAMEOBJECTPATH)(HANDLE, PSID, ULONG, LPWSTR, PULONG);
static _LPGETAPPCONTAINERNAMEOBJECTPATH lpGetAppContainerNamedObjectPath = NULL;
if (0 == lpGetAppContainerNamedObjectPath)
{
HMODULE hKernel32 = LoadLibraryExW(L"kernel32.dll", NULL, 0);
if (hKernel32)
{
lpGetAppContainerNamedObjectPath = reinterpret_cast<_LPGETAPPCONTAINERNAMEOBJECTPATH>(GetProcAddress(hKernel32, "GetAppContainerNamedObjectPath"));
}
}
if (lpGetAppContainerNamedObjectPath)
{
DWORD processId = (DWORD)_ttoi((LPCTSTR)procName);
//HANDLE hProcess = GetProcessHandleByProcessName(procName);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if(!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"OpenProcessToken Error(%u) PID(%d)\n", dwResult, processId );
AfxMessageBox(wcsDebug);
return;
}
if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, NULL, dwSize, &dwSize))
{
dwResult = GetLastError();
if( dwResult != ERROR_INSUFFICIENT_BUFFER )
{
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
return;
}
}
pAppCoInfo = (PTOKEN_APPCONTAINER_INFORMATION) GlobalAlloc( GPTR, dwSize );
if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, pAppCoInfo, dwSize, &dwSize))
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
return;
}
WCHAR wcsNamedObjectPath[MAX_PATH];
ULONG ulRetlen = 0;
BOOL bRet = lpGetAppContainerNamedObjectPath(hToken, pAppCoInfo->TokenAppContainer, _countof(wcsNamedObjectPath), wcsNamedObjectPath, &ulRetlen );
if (bRet)
{
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Path(%s)\n", wcsNamedObjectPath );
AfxMessageBox(wcsDebug);
}
else
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
}
if (pwSID)
LocalFree(pwSID);
CloseHandle(hToken)
CloseHandle(hProcess);
}
}
As a side-note, I have tried using wchar_t * and dynamically allocate the memory buffer by calling GetAppContainerNamedObjectPath twice. But still had no chance. Return length does not return a meaningful value.
if you call RtlGetLastNtStatus(); instead GetLastError(); after GetAppContainerNamedObjectPath you will got
STATUS_INVALID_PARAMETER_MIX - An invalid combination of parameters was specified.
this give you more info compare simply invalid parameter.
then look for function signature
BOOL
WINAPI
GetAppContainerNamedObjectPath(
_In_opt_ HANDLE Token,
_In_opt_ PSID AppContainerSid,
_In_ ULONG ObjectPathLength,
_Out_writes_opt_(ObjectPathLength) LPWSTR ObjectPath,
_Out_ PULONG ReturnLength
);
the Token and AppContainerSid declared with In_opt -- this mean that this parameters is optional, and you can pass 0 in place one of it. then ask your self - for what you query token for TokenAppContainerSid ? are system can not do this for you if you pass this token to api ? obvious can. so you not need do this yourself. really you need pass Token to api and in this case AppContainerSid must be 0. or you can pass AppContainerSid to api and in this case Token must be 0. when both AppContainerSid and Token not zero - you and got STATUS_INVALID_PARAMETER_MIX
also as side note - you not need open process with PROCESS_ALL_ACCESS if you need get it token. the PROCESS_QUERY_LIMITED_INFORMATION is enough
really api not do big magic. it return to you
AppContainerNamedObjects\<Sid>
path, where string form of app container sid.(some like S-1-15-2-...)

reasons for STATUS_ACCESS_VIOLATION for a user mode call in ntdll.dll library function

Is it possible to access functions on ntdll.dll from user mode? I used LoadLibrary() and GetProcAddress() to obtain function address of NtOpenFile() successfully. But I get STATUS_ACCESS_VIOLATION error during the call to NtOpenFile. I know that this would be because of memory related issues. Should I allocate memory virtually for the UNICODE_STRING structure? I am new to WinApi programming. I am using the example from here
int main() {
typedef NTSTATUS(__stdcall* NT_OPEN_FILE)(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions);
NT_OPEN_FILE NtOpenFileStruct;
/* load the ntdll.dll */
PVOID Info;
HMODULE hModule = LoadLibrary(L"ntdll.dll");
NtOpenFileStruct = (NT_OPEN_FILE)GetProcAddress(hModule, "NtOpenFile");
if (NtOpenFileStruct == NULL) {
printf("Error: could not find the function NtOpenFile in library ntdll.dll.");
exit(-1);
}
printf("NtOpenFile is located at 0x%08x in ntdll.dll.\n", (unsigned int)NtOpenFileStruct);
/* create the string in the right format */
UNICODE_STRING filename;
RtlInitUnicodeString(&filename, L"C:\\temp.txt" );
/* initialize OBJECT_ATTRIBUTES */
OBJECT_ATTRIBUTES obja;
InitializeObjectAttributes(&obja, &filename, OBJ_CASE_INSENSITIVE, NULL, NULL);
/* call NtOpenFile */
IO_STATUS_BLOCK iostatusblock;
HANDLE file = NULL;
NTSTATUS stat = NtOpenFileStruct(&file, FILE_WRITE_DATA, &obja, NULL, NULL, NULL);
if (NT_SUCCESS(stat)) {
printf("File successfully opened.\n");
}
else {
printf("File could not be opened.\n");
}
printf("Error = %x", stat);
return 0;
}
As comment pointed out, you need to pass a pointer of IO_STATUS_BLOCK (&iostatusblock) to the 4rd parameter.
NTSTATUS stat = NtOpenFileStruct(&file, FILE_WRITE_DATA, &obja, &iostatusblock, NULL, NULL);
Then, the sample will still get the error STATUS_OBJECT_PATH_SYNTAX_BAD(0xC000003B): The object path component was not a directory object.
Use Path like L"\\??\\C:\\temp.txt instead.

CreateRemoteThread MessageBoxA causes remote process to crash

I made a simple program that calculates the RVA of the function MessaegBoxA in user32.dll and then adds that offset to the base loading address of the dll in the remote process's memory to get the address of the function MessageBoxA. I made a dummy program that outputs the address of the function in its memory using GetProcAddress and then implement my own function in my program to display the address it calculated for the same function in the remote process. They always match so I'm certain my function for finding the address of MessageBoxA in remote process's is not the problem.
I made a struct that contains all the necessary information and parameters needed for ThreadProc to execute MessageBoxA in the remote process once I load it using WriteProcessMemory.
typedef struct
{
typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
_MessageBoxA MessageBoxA;
//These are the four parameters passed to MessageBoxA
HWND hwnd;
LPCSTR msg;
LPCSTR caption;
UINT mb;
}MB_DATA, *PMB_DATA;
When I try this on my own dummy program, the message box shows up but with weird text contrary to the strings I specified in the msg and caption members of MB_DATA. It says the following for the caption asic_string::erase and for the message it says u). And when I try to do this in any other process than my dummy process it crashes the remote process. I made a function to iterate through the modules that have been loaded in the process with tlhelp32 functions to make sure user32.dll is present and it is and my function for finding the address of the function in the process doesn't return NULL like it would if the dll were not present.
Here all relevant functions and my main function:
dependencies.hpp
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct
{
typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
_MessageBoxA MessageBoxA;
HWND hwnd;
LPCSTR msg;
LPCSTR caption;
UINT mb;
}MB_DATA, *PMB_DATA;
//Map the dll into memory
void* GetFileImage(char path[])
{
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if(hFile == INVALID_HANDLE_VALUE){printf("Error getting file handle: %d", (int)GetLastError());return NULL;}
HANDLE file_map = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap");
if(file_map == INVALID_HANDLE_VALUE){printf("Error mapping file: %d", (int)GetLastError());return NULL;}
LPVOID file_image = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0);
if(file_image == 0){printf("Error getting mapped view: %d", (int)GetLastError());return NULL;}
return file_image;
}
//Get to the function export directory and find the offset for the specified function from the
//address in memory the dll was loaded at
DWORD_PTR RVAddress(char* image, const char* proc_name)
{
PIMAGE_DOS_HEADER pDos_hdr = (PIMAGE_DOS_HEADER)image;
PIMAGE_NT_HEADERS pNt_hdr = (PIMAGE_NT_HEADERS)(image+pDos_hdr->e_lfanew);
IMAGE_OPTIONAL_HEADER opt_hdr = pNt_hdr->OptionalHeader;
IMAGE_DATA_DIRECTORY exp_entry = opt_hdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
PIMAGE_EXPORT_DIRECTORY pExp_dir = (PIMAGE_EXPORT_DIRECTORY)(image+exp_entry.VirtualAddress);
DWORD* func_table = (DWORD*)(image+pExp_dir->AddressOfFunctions);
WORD* ord_table = (WORD*)(image+pExp_dir->AddressOfNameOrdinals);
DWORD* name_table = (DWORD*)(image+pExp_dir->AddressOfNames);
for(u_int i=0;i<pExp_dir->NumberOfNames;i++)
{
char* name = (char*)(image+name_table[i]);
if(strcmp(proc_name, name) == 0)
{
return (DWORD_PTR)func_table[ord_table[i]];
}
}
return (DWORD_PTR)0;
}
//Add the RVA returned from RVAddress to the address of the dll to find the function in the
//process memory
LPVOID GetProcAddressEx(DWORD dwPid, char* mod_path, char* function_name, char* mod_name)
{
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
me32.dwSize = sizeof(MODULEENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, dwPid);
if(hSnapshot == INVALID_HANDLE_VALUE){printf("Snapshot failed");return 0;}
if(!(Module32First(hSnapshot, &me32)))
{
printf("Mod32First failed");
return 0;
}
BOOL found = FALSE;
while(Module32Next(hSnapshot, &me32))
{
if(stricmp(me32.szModule, mod_name) == 0)
{
CloseHandle(hSnapshot);
found = TRUE;
break;
}
}
if(found == FALSE){return 0;}
DWORD_PTR RVA = (DWORD_PTR)RVAddress((char*)GetFileImage(mod_path), function_name);
LPVOID func_addr = me32.modBaseAddr+RVA;
return func_addr;
}
main.cpp
#include "dependencies.hpp"
#define FUNC_SIZE 1024
typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
int main()
{
MB_DATA mb_data;
mb_data.hwnd = NULL;
mb_data.msg = "Hey";
mb_data.caption = "Yo";
mb_data.mb = MB_OK;
SIZE_T nBytes = 0;
char proc_path[MAX_PATH];
char kernel_path[MAX_PATH];
char user32_path[MAX_PATH];
//get full path to the current process and store it in proc_path
GetModuleFileName(GetModuleHandle(NULL), proc_path, MAX_PATH);
//get full path to kernel32.dll and store it in kernel_path
GetModuleFileName(GetModuleHandle("kernel32.dll"), kernel_path, MAX_PATH);
//get full path to user3.dll and store it in user32_path
GetModuleFileName(GetModuleHandle("user32.dll"), user32_path, MAX_PATH);
//show all processes running and their PID's
system("tasklist");
DWORD dwPid = 0;
printf("PID: ");
scanf("%lu", &dwPid);
//if dwPid is 0 assign it the pid of the current process
if(dwPid == 0)
{
dwPid = GetCurrentProcessId();
}
//Get a handle to the process with all access rights
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
//make sure the handle is valid
if(hProc == NULL){printf("Error obtaining handle to process: %lu", GetLastError());return 1;}
//Get the address of the function in the remote process
LPVOID _MessageBoxA1 = GetProcAddressEx(dwPid, user32_path, (char*)"MessageBoxA", (char*)"user32.dll");
//assign the pointer to the address to the member MessageBoxA of the MB_DATA structure
mb_data.MessageBoxA = (_MessageBoxA)_MessageBoxA1;
//allocate 2mb for our the ThreadProc callback function and the MB_DATA structure
LPVOID lpBase = VirtualAllocEx(hProc, NULL, 2048, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//did the allocation work
if(lpBase == NULL){printf("Error allocating space: %lu", GetLastError());return 1;}
//so I can check what was written with CheatEngine
cout << "Base address of memory allocated in remote process: " << lpBase << endl;
//Write the function into memory
if(WriteProcessMemory(hProc, lpBase, (LPVOID)ThreadProc, FUNC_SIZE, &nBytes) == 0)
{
printf("Error writing function to process");
return 1;
}
//the address the space left after having written ThreadProc into memory
LPVOID lpBuffer = lpBase+FUNC_SIZE;
//Write the MB_DATA structure into the memory of the remote process
if(WriteProcessMemory(hProc, lpBuffer, &mb_data, sizeof(MB_DATA), &nBytes) == 0)
{
printf("Error writing buffer to process");
}
//Run the ThreadProc function passing the MB_DATA structure to it as its lpParam parameter
if(CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpBase, lpBuffer, 0, NULL) == NULL)
{
printf("Error creating remote thread: %lu", GetLastError());
return 1;
}
//print a list of all the dll's being used by the process
EnumerateModules(dwPid);
system("pause");
return 0;
}
Any help would be greatly appreciated. Thank you very much! :)
mb_data.msg and mb_data.caption point to what in the another process ?? this is already enough for crash error. what is in ThreadProc not visible, but i not sure that it have no relocs. really ThreadProc must be member function of MB_DATA and access only it members. from you post obviously that you not debug remote process at injection time. also obviously that task is over your current level

Resource Data Doesnt Write to TextFile

void Extract(WORD wResId , LPSTR lpszOutputPath)
{
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId) , RT_RCDATA);
HGLOBAL hLoaded = LoadResource( NULL,hrsrc);
LPVOID lpLock = LockResource( hLoaded);
DWORD dwSize = SizeofResource(NULL, hrsrc);
HANDLE hFile = CreateFile("C://Windows//Darek//mylo.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD dwByteWritten;
char* cRes = (char*)malloc (dwSize);
memset(cRes,0,dwSize);
memcpy (cRes, cData, dwSize);
cRes[dwSize] = '\0';
FreeResource(hLoaded);
WriteFile(hFile, lpLock , dwSize , &dwByteWritten , NULL);
CloseHandle(hFile);
FreeResource(hLoaded);
}
Ok this creates the file correctly, but the extracted data doesnt seem to extract and write to the textFile,Any problems? i do not seem to understand why it doesnt extract and Write the data to the file.
Please Help.
You are allocating a memory block that is as large as the resource, zeroing it out (which is redundant), and copying something (what is cData pointing at? Maybe you meant lpLock instead?) into that memory, but then you are ignoring the allocated memory and leaking it. You are trying to write the content of lpLock to the file as-is, which is what you should be doing, but you are not doing any error handling at all. Chances are, your resource is missing, or otherwise not available for reading. That would account for your file being empty.
Try this instead:
void Extract(WORD wResId, LPSTR lpszOutputPath)
{
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId), RT_RCDATA);
if (!hrsrc)
{
// GetLastError() tells you why it failed...
return;
}
HGLOBAL hLoaded = LoadResource(NULL, hrsrc);
if (!hLoaded)
{
// GetLastError() tells you why it failed...
return;
}
DWORD dwSize = SizeofResource(NULL, hrsrc);
if ((dwSize == 0) && (GetLastError() != 0))
{
// GetLastError() tells you why it failed...
return;
}
LPVOID lpLock = LockResource(hLoaded);
if (!lpLock)
{
// GetLastError() tells you why it failed...
return;
}
HANDLE hFile = CreateFileA(lpszOutputPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// GetLastError() tells you why it failed...
return;
}
DWORD dwByteWritten;
if (!WriteFile(hFile, lpLock, dwSize, &dwByteWritten, NULL))
{
// GetLastError() tells you why it failed...
CloseHandle(hFile);
DeleteFileA(lpszOutputPath);
return;
}
CloseHandle(hFile);
}
If I had to guess (and please don't make people guess), FindResource() is most likely returning NULL. Make sure the second parameter actually matches the correct resource type for wResId. You cannot load any arbitrary resource using RT_RCDATA, you have to use the correct resource type. Only resources using the RCDATA type can be accessed using the RT_RCDATA parameter value. String resources might be stored using the RT_MESSAGETABLE or RT_STRING type instead, for instance. You can use EnumResourceTypes() and EnumResourceNames(), or an external resource editor/viewer tool, to find out what type the wResId resource is actually using.

C++ read Registry

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:
Anyone can help me? What i'm doing wrong?
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.)
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.