RUN FAILED in netbeans ( C++) - c++

On running the following C++ code to extract entire registry sub-keys of HKEY_CURRENT_USER, I am getting RUN FAILED (exit value 1..) error in netbeans. Only one sub-key is being opened i.e the open() function runs once.
Link to RegOpenKeyEx function.
Any help would be highly appreciated.
#include <windows.h>
#include <iostream>
#include <string>
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
#define MAX_SUB_KEYS 10000
using namespace std;
void QueryKey(HKEY);
void open(HKEY,string [],int);
void open(HKEY hkey12,string subkey[],int m)
{
int u=0;
while(u<m)
{
HKEY hkey1;
const char* sub=subkey[u].c_str();
if( RegOpenKeyEx(hkey12,
sub,
0,
KEY_READ,
&hkey1) == ERROR_SUCCESS
)
{
QueryKey(hkey1);
}
else { cout<<"Subkey open failed "<<endl;}
RegCloseKey(hkey1);
u++;
}
}
int main()
{
HKEY hTestKey;
if( RegOpenKeyEx( HKEY_CURRENT_USER,
NULL,
0,
KEY_READ,
&hTestKey) == ERROR_SUCCESS
)
{
QueryKey(hTestKey);
}
RegCloseKey(hTestKey);
return 0;
}
void QueryKey(HKEY hKey) // This function fetches the actual parameters.
{
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
DWORD cbName; // size of name string
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys=0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cValues=0; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time
DWORD i, retCode;
TCHAR achValue[MAX_VALUE_NAME];
DWORD valueData; // BYTE valueData[2048]; // buffer for value data
DWORD cchValue = MAX_VALUE_NAME; //pointer to size of value name
DWORD valueType; // buffer for value type
DWORD size=2049; // pointer to size of value data
// Get the class name and the value count.
retCode = RegQueryInfoKey(
hKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime); // last write time
string subkey[cSubKeys];
string values[cValues];
int typev[cValues];
// Extract the subkeys, until RegEnumKeyEx fails.
if (cSubKeys)
{
for (i=0; i<cSubKeys; i++)
{
cbName = MAX_KEY_LENGTH;
retCode = RegEnumKeyEx(hKey, i,
achKey,
&cbName,
NULL,
NULL,
NULL,
&ftLastWriteTime);
if (retCode == ERROR_SUCCESS)
{
subkey[i]=achKey;
}
}
}
// Enumerate the key values.
if (cValues)
{
for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++)
{
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
retCode = RegEnumValue(hKey, i,
achValue,
&cchValue,
NULL,
&valueType,
(BYTE *)valueData,
&size);
if (retCode == ERROR_SUCCESS )
{
values[i]=achValue;
typev[i]=valueType;
}
else { cout<<"Error"<<endl;
}
}
}
int d=0;
cout<<"------------------------------------------------------------------------"<<endl;
cout<<"Sub Keys of "<<"are displayed below- "<<endl<<endl;
while(d<cSubKeys){
cout<<subkey[d]<<endl;
d++;
}
d=0;
cout<<endl;
if(!values[0].empty()) {
cout<<"Values are displayed below- "<<endl<<endl;
while(d<cValues){
cout<<values[d]<<" "<<typev[d]<<endl;
d++;
}
}
open(hKey,subkey,cSubKeys);
}

Related

Read INT64 from Windows Registry

I'm having an issue reading the InstallTime value from the registry in Windows 11. I used this idea to read the value, but retCode gives me 2 (ERROR_FILE_NOT_FOUND). The value is there, and I guess there's no need for admin rights to read it. I'm using the following code snippet:
UINT64 RegGetQword(HKEY hKey, const std::wstring& subKey, const std::wstring& value)
{
UINT64 data{};
DWORD dataSize = sizeof(data);
LONG retCode = ::RegGetValue(hKey, subKey.c_str(), value.c_str(), RRF_RT_REG_QWORD, nullptr, &data, &dataSize);
if (retCode != ERROR_SUCCESS)
throw RegistryError{ "Cannot read QWORD from registry.", retCode };
return data;
}
int main(void)
{
UINT64 dwInst;
try
{ double nTimeExpr = (double)RegGetQword(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"InstallTime");
dwInst = _getSecondsFromEpoch(nTimeExpr)
}
catch (...)
{
dwInst = 0;
}
//... Do whatever needed with dwInst
return 0;
}

VirtDisk.h QueryChangesVirtualDisk() function return RangeCount as 0

https://learn.microsoft.com/ko-kr/windows/win32/api/virtdisk/nf-virtdisk-querychangesvirtualdisk?redirectedfrom=MSDN
DWORD QueryChangesVirtualDisk(
HANDLE VirtualDiskHandle,
PCWSTR ChangeTrackingId,
ULONG64 ByteOffset,
ULONG64 ByteLength,
QUERY_CHANGES_VIRTUAL_DISK_FLAG Flags,
PQUERY_CHANGES_VIRTUAL_DISK_RANGE Ranges,
PULONG RangeCount,
PULONG64 ProcessedLength
);
I am trying to get difference between two virtual disk or two Resillent Change Tracking ID (RCT)
but RangeCount always return as 0
I opened virtual disk file (vhdx) with two enum parameter VIRTUAL_DISK_ACCESS_GET_INFO, OPEN_VIRTUAL_DISK_FLAG_NONE
opStatus = OpenVirtualDisk(
&storageType,
VirtualDiskPath,
VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NONE,
NULL,
&vhdHandle ); // output handle
then use QueryChangesVirtualDisk()
opStatus = QueryChangesVirtualDisk(
vhdHandle,
ChangeTrackingId,
0,
32212254720,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
pRctRanges,
&rctRangeCnt,
&processedLength
);
OpenVirtualDisk() QueryChangesVirtualDisk()
Both function did not return error but in every case RangeCount always has a value of 0
There is definitely a difference between virtual disk file and RCT ID
please give me some advice
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <initguid.h>
#include <strsafe.h>
#include <virtdisk.h>
#include "Storage.h"
DWORD QueryChangesVirtualDisk(_In_ LPCWSTR VirtualDiskPath, _In_ LPCWSTR ChangeTrackingId)
{
VIRTUAL_STORAGE_TYPE storageType;
PGET_VIRTUAL_DISK_INFO diskInfo;
ULONG diskInfoSize;
DWORD opStatus;
HANDLE vhdHandle;
QUERY_CHANGES_VIRTUAL_DISK_RANGE *pRctRanges;
ULONG rctRangeCnt;
ULONG64 processedLength;
UINT i;
vhdHandle = INVALID_HANDLE_VALUE;
diskInfo = NULL;
diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);
rctRangeCnt = 0L;
processedLength = 0L;
pRctRanges = NULL;
i = 0;
diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);
if (diskInfo == NULL)
{
opStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;
//////////////////////////////////////////////////////////////////
opStatus = OpenVirtualDisk(
&storageType,
VirtualDiskPath,
VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NONE,
NULL,
&vhdHandle);
if (opStatus != ERROR_SUCCESS)
{
wprintf(L"OpenVirtualDisk fail\n");
goto Cleanup;
}
opStatus = QueryChangesVirtualDisk(
vhdHandle,
ChangeTrackingId,
0,
32212254720,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
pRctRanges,
&rctRangeCnt,
&processedLength
);
wprintf(L"rctRangeCnt : %lu\n", rctRangeCnt);
wprintf(L"processedLength : %llu\n", processedLength);
for (i = 0; i < rctRangeCnt; i++)
{
wprintf(L"ByteOffset : %lld ByteLength : %lld\n", pRctRanges[i].ByteOffset, pRctRanges[i].ByteLength);
}
if (opStatus != ERROR_SUCCESS)
{
wprintf(L"QueryChangesVirtualDisk fail\n");
goto Cleanup;
}
Cleanup:
if (opStatus == ERROR_SUCCESS)
{
wprintf(L"success\n");
}
else
{
wprintf(L"error = %u\n", opStatus);
}
if (vhdHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(vhdHandle);
}
if (diskInfo != NULL)
{
free(diskInfo);
}
if (pRctRanges != NULL)
{
for (i = 0; i < rctRangeCnt; i++)
{
free(&pRctRanges[i]);
}
}
return opStatus;
}
The problem is that you pass a null-pointer for the Ranges argument and zero for RangeCount.
For Ranges you're supposed to pass a pointer to the first element or an array of QUERY_CHANGES_VIRTUAL_DISK_RANGE elements, and the RangeCount should be initialized to the number of elements in that array.
When the QueryChangesVirtualDisk function returns it will have modified RangeCount to be the number of initialized elements in the Ranges array.
From the documentation you linked to, about the RangeCount argument:
On input, the value indicates the number of QUERY_CHANGES_VIRTUAL_DISK_RANGE structures that the array that the Ranges parameter points to can hold. On output, the value contains the number of QUERY_CHANGES_VIRTUAL_DISK_RANGE structures that the method placed in the array.
In short: The function doesn't create this array for you, you must do it before you call the function.

DirectInput8 Hooking Issue

I'm just beginning with directx/directinput development and I'm running some tests with some code samples I've found online. Anyway, I want to hook an application that uses dinput8 to send my own custom input to the forewindow and I'm working with this base to do it:
// dllmain.cpp : Defines the entry point for the DLL application.
#define _CRT_SECURE_NO_WARNINGS // ignore some warnings...
#define _CRT_NON_CONFORMING_SWPRINTFS // ...
#include "stdio.h"
#include <windows.h>
#include "detours.h"
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <time.h>
#include "dinput.h"
#pragma comment(lib, "detours.lib")
#pragma comment(lib, "user32.lib")
typedef HRESULT(__stdcall* GetDeviceState_t)(LPDIRECTINPUTDEVICE, DWORD, LPVOID *);
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE pDevice, DWORD cbData, LPVOID *lpvData);
DWORD Base = 0;
DWORD GetDeviceStateOffset = 0x7670; // This is the offset of GetDeviceState from DInput8.dll
// Open IDA and Import the DInput8.dll, then look in the Functions Table for DirectInput8Create
// There is an Address (1000XXXX or 0CXXXXX) - copy it and save it for later
// Then take a look for CDIDev_GetDeviceState and copy that address too
// Now substract the Address from CDIDev_GetDeviceState from DIrectInput8Create and u'll get your offset
HANDLE tmpHandle = NULL;
HMODULE hModDInput8 = NULL;
DWORD dwGetDeviceState = NULL;
FARPROC dwDirectInput8Create = NULL;
struct MyKeys
{
BYTE Key;
DWORD StartTime;
DWORD TTL;
BOOLEAN isDown;
};
MyKeys KeyBuffer[256];
DWORD WINAPI HookThread();
void add_log(char* format, ...);
void SendKeyDInput(byte DIK_, DWORD time);
GetDeviceState_t pGetDeviceState;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
add_log("==========LOG START==========");
add_log("DLL Attached");
add_log("Creating Thread...");
tmpHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&HookThread, 0, 0, 0);
if (!tmpHandle)
{
add_log("ThreadCreation Failed!");
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DWORD WINAPI HookThread()
{
Base = (DWORD)GetModuleHandleA("test.exe");
add_log("Thread Created");
add_log("game.exe Base: %x", Base);
while (!hModDInput8)
{
add_log("Searching dinput8.dll...");
hModDInput8 = GetModuleHandle(L"dinput8.dll");
Sleep(100);
}
add_log("Found dinput8.dll: %x !", hModDInput8);
while (!dwDirectInput8Create)
{
add_log("Searching GetDeviceState...");
dwDirectInput8Create = GetProcAddress(hModDInput8, "DirectInput8Create");
Sleep(100);
}
add_log("Found DirectInput8Create: %x !", dwDirectInput8Create);
dwGetDeviceState = (DWORD)((DWORD)dwDirectInput8Create - GetDeviceStateOffset);
add_log("GetDevicestate is here (DirectInput8Create - %x): %x", GetDeviceStateOffset, dwGetDeviceState);
add_log("Hooking GetDeviceState...");
pGetDeviceState = (GetDeviceState_t)DetourAttach(&(PVOID&)dwGetDeviceState, (PBYTE)hkGetDeviceState);
add_log("Initiate Keyboard Buffer...");
//initiate buffer
for (int i = 0; i < 256; i++)
{
KeyBuffer[i].isDown = false;
KeyBuffer[i].Key = 0;
KeyBuffer[i].StartTime = 0;
KeyBuffer[i].TTL = 0;
}
add_log("Going into Main Loop...");
while (true)
{
if (GetAsyncKeyState(VK_F5) & 1 << 15)
{
// We check the Most Sigificant Bit from VK_F5 (F5) whilst we shifted it with 15 bits to left 1
// and then a small delay so we have enaught time to release the key
add_log("F5 pushed attempting to sendkey");
// Sleep a short time so we have time to release the F5 Key
Sleep(500);
// Now we send a A Key with 1 sec time to our Game
SendKeyDInput(DIK_A, 1000);
}
}
return 0;
}
void SendKeyDInput(byte DIK, DWORD time)
{
KeyBuffer[DIK].Key = DIK;
KeyBuffer[DIK].TTL = time;
KeyBuffer[DIK].StartTime = GetTickCount();
}
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE lpDevice, DWORD cbData, LPVOID *lpvData)
{
HRESULT hResult = DI_OK;
static BYTE buffer[256];
int key_count = 0;
for (int i = 0; i<256; i++)
{
if (KeyBuffer[i].Key != 0 && KeyBuffer[i].TTL>0 && KeyBuffer[i].StartTime != 0)
{
if (GetTickCount() > KeyBuffer[i].StartTime + KeyBuffer[i].TTL && KeyBuffer[i].isDown)
{
KeyBuffer[i].Key = 0;
KeyBuffer[i].StartTime = 0;
KeyBuffer[i].TTL = 0;
KeyBuffer[i].isDown = false;
buffer[KeyBuffer[i].Key] = 0;
}
else {
KeyBuffer[i].isDown = true;
buffer[KeyBuffer[i].Key] = 0x80;
key_count += 1;
add_log("Sending Key %x for %i milliseconds count: %i", KeyBuffer[i].Key, KeyBuffer[i].TTL, key_count);
}
}
}
if (key_count != 0)
{
cbData = 256;
memcpy(lpvData, buffer, cbData);
}
else {
hResult = pGetDeviceState(lpDevice, cbData, lpvData);
}
return hResult;
}
//Creates a Logfile in the Game Directory
void add_log(char* format, ...)
{
HANDLE filehandle;
DWORD dwReadBytes;
char buffer[2048];
char writebuffer[2048];
va_list args;
va_start(args, format);
vsprintf_s(buffer, format, args);
filehandle = CreateFile(L"Log.txt", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);
SetFilePointer(filehandle, 0, 0, FILE_END);
sprintf_s(writebuffer, 2048, "Log Added: %s\r\n", buffer);
WriteFile(filehandle, writebuffer, strlen(writebuffer), &dwReadBytes, 0);
CloseHandle(filehandle);
}
The only issue in this code is when I attempt to send input, it doesn't go through. I've gotten some help and narrowed down a solution to this, which was: "Try GetDeviceState hk just memset(buffer, 0, size) or SendDeviceData". I've searched around a bit and I've been unable to find more on how to implement this solution and I'm stumped.
Could one of you kind people show me how I could use this information to fix this base? I'd be extremely grateful, thanks.

NetApiBufferFree returns ERROR_INVALID_PARAMETER (Error Code 87)

I have been developing an application that uses winapi to get administrator group members. I used NetLocalGroupGetMembers method for that purpose. My problem is when i try to free buffer's heap space i get ERROR_INVALID_PARAMETER (Error Code 87) from NetApiBufferFree method. I have administrator privileges for the application.
Here is the code:
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <lm.h>
#include <time.h>
#include <assert.h>
#define SLEEP_TIME 2000
#define OS_GROUP_NAME L"administrators"
void createServiceThread();
DWORD WINAPI mainServiceThread( LPVOID lpParam );
char** getUsersByLocalGroup();
void freeNetApiBuffer(LPVOID buffer);
int localGroupUserCount;
int WriteToLog(char* str)
{
printf("%s\n", str);
return 0;
}
int main()
{
createServiceThread();
}
void createServiceThread(){
WriteToLog("Application Started...");
while(TRUE){
mainServiceThread(NULL);
Sleep(SLEEP_TIME);
}
WriteToLog("Application Closed...");
}
//-------------------------------------------
// A function that represents Main Service Thread
//-------------------------------------------
DWORD WINAPI mainServiceThread( LPVOID lpParam )
{
time_t startTime;
time (&startTime);
char startTimeText[30];
sprintf(startTimeText, "Service Loop Started %s", ctime(&startTime));
WriteToLog(startTimeText);
localGroupUserCount = 0;
char** localGroupUsers = getUsersByLocalGroup();
WriteToLog("User not found...");
time_t endTime;
time (&endTime);
char endTimeText[30];
sprintf(endTimeText, "Service Loop Ended %s", ctime(&endTime));
WriteToLog(endTimeText);
}
char** getUsersByLocalGroup(){
WriteToLog("getUsersByLocalGroup started");
LOCALGROUP_MEMBERS_INFO_3 *pBuf;
DWORD dwLevel = 3;
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
NET_API_STATUS nStatus;
WriteToLog("Call NetLocalGroupGetMembers");
nStatus = NetLocalGroupGetMembers(
NULL,
OS_GROUP_NAME,
dwLevel,
(LPBYTE *) &pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
NULL
);
// nStatus = ERROR_SUCCESS;
WriteToLog("NetLocalGroupGetMembers called");
//
// If the call succeeds,
//
if (nStatus == ERROR_SUCCESS || nStatus == ERROR_MORE_DATA)
{
DWORD i;
DWORD dwTotalCount = 0;
WriteToLog("Correct Status");
if (pBuf != NULL)
{
//
// Loop through the entries.
//
for (i = 0; (i < dwEntriesRead); i++)
{
assert(pBuf != NULL);
if (pBuf == NULL)
{
char bufError[] = "";
sprintf(bufError, "An access violation has occurred %d", stderr);
WriteToLog(bufError);
break;
}
LPWSTR userNameOnBuffer = pBuf->lgrmi3_domainandname;
pBuf++;
dwTotalCount++;
}
localGroupUserCount = dwTotalCount;
char totalCount[] = "";
sprintf(totalCount, "Entries enumerated: %d", dwTotalCount);
WriteToLog(totalCount);
}
//
// Otherwise, print the system error.
//
else{
char systemError[] = "";
sprintf(systemError, "An system error has occurred %d - %d", stderr, nStatus);
WriteToLog(systemError);
}
}
//
// Free the allocated buffer.
//
if (pBuf != NULL)
{
NET_API_STATUS nBufferFreeStatus = NetApiBufferFree((LPVOID)pBuf);
if(nBufferFreeStatus == NERR_Success){
WriteToLog("Succesfully freed buffer");
}
else{
WriteToLog("Error occured freeing buffer");
}
pBuf = NULL;
}
WriteToLog("getUsersByLocalGroup finished");
return NULL;
}
In your loop you have the line pBuf++;. This modifies pBuf which means that the value you are freeing is not the value that was allocated. Hence the invalid parameter.
Also, these lines
char totalCount[] = "";
sprintf(totalCount, "Entries enumerated: %d", dwTotalCount);
create a stack buffer overflow, which is probably corrupting your pBuf variable. There is another instance of it a few lines later.
In general, here's how you debug it: Set a breakpoint as soon as NetLocalGroupGetMembers returns. Look at the value in pBuf and write it down in a safe place. Set another breakpoint when you are about to call NetApiBufferFree. Look at the value of pBuf you are passing. Is it equal to the value you wrote down earlier? If not, then you have a bug. Use the debugger to find out why you are passing the wrong value.

I can't use RegOpenKeyEx

I am having problems with reading the registry.
This function finds the number of entries in a registry path. It works perfectly, I have tested it:
void findNumberEntries(registryTest &INSTALLKEY) {
char buffer[50];
char size = sizeof(buffer);
int index = 0;
if(RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)(INSTALLKEY.regpath.c_str()),0,KEY_ALL_ACCESS,&INSTALLKEY.hKey) == ERROR_SUCCESS) {
DWORD readEntry;
do {
readEntry = RegEnumValue(INSTALLKEY.hKey,index,(LPTSTR)buffer,(LPDWORD)&size,NULL,NULL,NULL,NULL);
index++;
}
while(readEntry != ERROR_NO_MORE_ITEMS);
}
INSTALLKEY.number = index;
RegCloseKey(INSTALLKEY.hKey);
}
now, the main function:
std::string regpath32 = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\";
struct registryTest {
HKEY hKey;
std::string regpath;
int number;
};
registryTest INSTALLKEY = {HKEY_LOCAL_MACHINE, regpath32};
findNumberEntries(INSTALLKEY);
printf("%d\n",INSTALLKEY.number);
system("PAUSE");
//until here everything works as it should
HKEY hKey = INSTALLKEY.hKey;
std::string regpath = INSTALLKEY.regpath;
char buffer[50];
char size = sizeof(buffer);
std::string bufferString;
DWORD regOpen = RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)INSTALLKEY.regpath.c_str(),0,KEY_READ,&INSTALLKEY.hKey);
if(regOpen == ERROR_SUCCESS) //this is the part that fails.
{
printf("Registry Key was successfully opened\n");
}
else
{
printf("Unable to open registry key\n");
LPVOID message;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), NULL,(LPTSTR) &message, 0, NULL );
MessageBox(NULL,(LPCTSTR)message,"ERROR",MB_OK|MB_ICONINFORMATION);
}
...rest of the code
I always get "Unable to open registry" and the error message I get is "There are no more files". What is the problem??
your problem is that when you first open the registry key ,you assign it to hkey-member of your struct. So the second time this hkey doesn't contain the original basekey anymore.
change :
DWORD regOpen =
RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)INSTALLKEY.regpath.c_str(),0,KEY_READ,&INSTALLKEY.hKey);
into
DWORD regOpen = RegOpenKeyEx(
HKEY_LOCAL_MACHINE
,(LPTSTR)INSTALLKEY.regpath.c_str(),0,KEY_READ,&INSTALLKEY.hKey);
or change this:
void findNumberEntries( registryTest &INSTALLKEY)
{
char buffer[50];
char size = sizeof(buffer);
int index = 0;
HKEY hkOpen = 0; // can't use INVALID_HANDLE_VALUE for HKEY's;
if (RegOpenKeyEx( INSTALLKEY.hKey ,(LPTSTR)(INSTALLKEY.regpath.c_str())
,0,&hkOpen ) == ERROR_SUCCESS)
{
// You should use RegQueryInfoKey for below code !
DWORD readEntry;
do {
readEntry = RegEnumValue( hkOpen ,index,(LPTSTR)buffer
,(LPDWORD size,NULL,NULL,NULL,NULL);
index++;
}
while(readEntry != ERROR_NO_MORE_ITEMS); }
INSTALLKEY.number = index;
RegCloseKey( hkOpen );
}
You may need to specify KEY_ALL_ACCESS in the second call as well, rather than just in the first. And on Win7 64-bit you may be running into the registry redirect craziness (http://msdn.microsoft.com/en-us/library/aa384232%28VS.85%29.aspx).
EDIT: ah, you might just be getting an ERROR_CANTWRITE back (error code number 5). You might be able to ignore that and see if it still works.
It's very likely that on Windows 7 64-bit that you are being redirected via Registry Virtualization. You can determine what keys are being redirected by calling RegQueryReflectionKey.
If you modify your code to output the actual integer value that is returned rather than a generic "Unable to open key", then it would be helpful. For example,
long n = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("\\SOFTWARE"),
0,KEY_QUERY_VALUE, &hk );
if ( n == ERROR_SUCCESS ) {
cout << "OK" << endl;
}
else {
cout << "Failed with value " << n << endl;
}