RegGetValue vs RegQueryValueEx - windows

I have a program coded by someone else. It has a function RegGetValue used as:
uFuncReturnValue = RegOpenKeyExA( HKEY_LOCAL_MACHINE,
acSubKey,
NULL,
KEY_READ | KEY_WRITE,
&hRegistry
);
//Store signature of the disk in the first 32 bytes of structVal
if( uFuncReturnValue != ERROR_SUCCESS )
{
printf("Unable to open registry with error %u\n", uFuncReturnValue);
exit(EXIT_FAILURE);;
}
uFuncReturnValue = RegGetValueA( hRegistry,
NULL,
"\\DosDevices\\C:",
RRF_RT_REG_BINARY,
NULL,
(LPVOID)&structVal,
&dwSize
);
This block of code works perfectly on Windows 7 but returns error when run on Windows XP (32 bit). As 32-bit xp don't have RegGetValue function so I am trying to make use of RegQueryValueEX but I am having problem in passing arguments to this function. I think it should be used some thing like:
uFuncReturnValue = RegQueryValueExA ( hRegistry,
"\\DosDevices\\J:",
NULL,
NULL,
(LPBYTE) &structVal,
&dwSize
);
But something is wrong here because the code compiles successfully but when I execute it I get a message:
The program '(128) myProgram.exe:
Native' has exited with code 1 (0x1).
Can someone help me here please?

Related

How to avoid memory leaks using ShellExecuteEx?

Minimal, Complete, and Verifiable example:
Visual Studio 2017 Pro 15.9.3
Windows 10 "1803" (17134.441) x64
Environment variable OANOCACHE set to 1.
Data/Screenshots shown for a 32 bits Unicode build.
UPDATE: Exact same behavior on another machine with Windows 10 "1803" (17134.407)
UPDATE: ZERO leaks on an old Laptop with Windows Seven
UPDATE: Exact same behavior (leaks) on another machine with W10 "1803" (17134.335)
#include <windows.h>
#include <cstdio>
int main() {
getchar();
CoInitializeEx( NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
printf( "Launching and terminating processes...\n" );
for ( size_t i = 0; i < 64; ++i ) {
SHELLEXECUTEINFO sei;
memset( &sei, 0, sizeof( sei ) );
sei.cbSize = sizeof( sei );
sei.lpFile = L"iexplore.exe";
sei.lpParameters = L"about:blank";
sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC;
BOOL bSuccess = ShellExecuteEx( &sei );
if ( bSuccess == FALSE ) {
printf( "\nShellExecuteEx failed with Win32 code %d and hInstApp %d. Exiting...\n",
GetLastError(), (int)sei.hInstApp );
CoUninitialize();
return 0;
} // endif
printf( "%d", (int)GetProcessId( sei.hProcess ) );
Sleep( 1000 );
bSuccess = TerminateProcess( sei.hProcess, 0 );
if ( bSuccess == FALSE ) {
printf( "\nTerminateProcess failed with Win32 code %d. Exiting...\n",
GetLastError() );
CloseHandle( sei.hProcess );
CoUninitialize();
return 0;
} // endif
DWORD dwRetCode = WaitForSingleObject( sei.hProcess, 5000 );
if ( dwRetCode != WAIT_OBJECT_0 ) {
printf( "\nWaitForSingleObject failed with code %x. Exiting...\n",
dwRetCode );
CloseHandle( sei.hProcess );
CoUninitialize();
return 0;
} // endif
CloseHandle( sei.hProcess );
printf( "K " );
Sleep( 1000 );
} // end for
printf( "\nDone!" );
CoUninitialize();
getchar();
} // main
The code use ShellExecuteEx to launch, in a loop, 64 instances of Internet Explorer with the about:blank URL. The SEE_MASK_NOCLOSEPROCESS is used to be able to then use the TerminateProcess API.
I notice two kinds of leaks:
Handles leaks: launching Process Explorer when the loop is finished but the program still running, I see several blocks of 64 handles (process handles, and registries handles for various keys)
Memory leaks: attaching the visual C++ 2017 debugger to the program, before the loop, I took a first Heap Snapshot, and a second one after the loop.I see 64 blocs of 8192 bytes, coming from windows.storage.dll!CInvokeCreateProcessVerb::_BuildEnvironmentForNewProcess()
You can read some information about the handles leaks here: ShellExecute leaks handles
Here are some screenshots:
First, the PID launched and terminated:
Second: the same pids, as seen in Process Explorer:
Process Explorer also shows 64*3 open registry handles, for HKCR\.exe, HKCR\exefile and HKCR\exefile\shell\open.
One of the 64 leaked "Environment" (8192 bytes and the callstack):
Last: a screen shot of Process Explorer, showing the "Private Bytes" during the execution of the MCVE modified with a 1024 loop counter. The running time is approximately 36 minutes, the PV start at 1.1 Mo (before CoInitializeEx) and end at 19 Mo (after CoUninitialize). The value then stabilizes at 18.9
What am I doing wrong?
Do I see leaks where there are none?
this is windows bug, in version 1803. minimal code for reproduce:
if (0 <= CoInitialize(0))
{
SHELLEXECUTEINFO sei = {
sizeof(sei), 0, 0, 0, L"notepad.exe", 0, 0, SW_SHOW
};
ShellExecuteEx( &sei );
CoUninitialize();
}
after execute this code, can view handles for notepad.exe process and first thread - this handles of course must not exist (be closed), not closed keys
\REGISTRY\MACHINE\SOFTWARE\Classes\.exe
\REGISTRY\MACHINE\SOFTWARE\Classes\exefile
also private memory leaks exist in process after this call.
of course this bug cause permanent resource leaks in explorer.exe and any process, which use ShellExecute[Ex]
exactly research of this bug - here
The underlying issue here appears to be in windows.storage.dll. In
particular, the CInvokeCreateProcessVerb object is never
destroyed, because the associated reference count never reaches 0.
This leaks all of the objects associated with
CInvokeCreateProcessVerb, including 4 handles and some memory.
The reason the reference count never reaches 0 appears to be related
to the argument change for ShellDDEExec::InitializeByShellInternal
from Windows 10 1709 to 1803, executed by
CInvokeCreateProcessVerb::Launch().
more concrete here we have cyclic reference of an object (CInvokeCreateProcessVerb) to itself.
more concrete error inside method CInvokeCreateProcessVerb::Launch() which call from self
HRESULT ShellDDEExec::InitializeByShellInternal(
IAssociationElement*,
CreateProcessMethod,
PCWSTR,
STARTUPINFOEXW*,
IShellItem2*,
IUnknown*, // !!!
PCWSTR,
PCWSTR,
PCWSTR);
with wrong 6 argument. the CInvokeCreateProcessVerb class containing internal ShellDDEExec sub-object. in windows 1709 CInvokeCreateProcessVerb::Launch() pass pointer to static_cast<IServiceProvider*>(pObj) in place 6 argument to ShellDDEExec::InitializeByShellInternal where pObj is point to instance of CBindAndInvokeStaticVerb class. but in 1803 version here passed pointer to static_cast<IServiceProvider*>(this) - so pointer to self. the InitializeByShellInternal store this pointer inside self and add reference to it. note that ShellDDEExec is sub-object of CInvokeCreateProcessVerb. so destructor of ShellDDEExec will not be called until destructor of CInvokeCreateProcessVerb not be called. but destructor of CInvokeCreateProcessVerb will be not called until it reference count reach 0. but this not happens until ShellDDEExec not release self pointer to CInvokeCreateProcessVerb which will be only inside it destructor ..
may be this more visible in pseudo code
class ShellDDEExec
{
CComPtr<IUnknown*> _pUnk;
HRESULT InitializeByShellInternal(..IUnknown* pUnk..)
{
_pUnk = pUnk;
}
};
class CInvokeCreateProcessVerb : CExecuteCommandBase, IServiceProvider /**/
{
IServiceProvider* _pVerb;//point to static_cast<IServiceProvider*>(CBindAndInvokeStaticVerb*)
ShellDDEExec _exec;
TRYRESULT CInvokeCreateProcessVerb::Launch()
{
// in 1709
// _exec.InitializeByShellInternal(_pVerb);
// in 1803
_exec.InitializeByShellInternal(..static_cast<IServiceProvider*>(this)..); // !! error !!
}
};
ShellDDEExec::_pUnk hold pointer to containing object CInvokeCreateProcessVerb this pointer will be released only inside CComPtr destructor, called from ShellDDEExec destructor. called from CInvokeCreateProcessVerb destructor, called when reference count became 0, but this never happens because extra reference hold ShellDDEExec::_pUnk
so object store referenced pointer to self. after this reference count to CInvokeCreateProcessVerb never reaches 0

Walking the NTFS Change Journal on Windows 10

I'm trying to read the NTFS Change Journal but I've noticed that all the example code I can find fails on Windows 10, even though it works on Windows 7.
For example, Microsofts own example Walking a Buffer of Change Journal Records works on Windows 7 but when I run the same code on Windows 10 I get an error 87 (The parameter is incorrect) when I call DeviceIoControl with FSCTL_READ_USN_JOURNAL (Note that the earlier call to DeviceIoControl with FSCTL_QUERY_USN_JOURNAL completes successfully and return valid data.).
I've even taken the EXE compiled and working on Windows 7 and copied it to the Windows 10 machine and it still fails, so I believe that Windows 10 may be more strict on parameter validation or something like that?
I am running the code as Administrator, so that's not the issue.
I can't find any other references to this problem, but I get the same issue if I take other peoples example code and attempt to run it on Windows 10.
Edit:
The code itself:
#include <Windows.h>
#include <WinIoCtl.h>
#include <stdio.h>
#define BUF_LEN 4096
void main()
{
HANDLE hVol;
CHAR Buffer[BUF_LEN];
USN_JOURNAL_DATA JournalData;
READ_USN_JOURNAL_DATA ReadData = {0, 0xFFFFFFFF, FALSE, 0, 0};
PUSN_RECORD UsnRecord;
DWORD dwBytes;
DWORD dwRetBytes;
int I;
hVol = CreateFile( TEXT("\\\\.\\c:"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if( hVol == INVALID_HANDLE_VALUE )
{
printf("CreateFile failed (%d)\n", GetLastError());
return;
}
if( !DeviceIoControl( hVol,
FSCTL_QUERY_USN_JOURNAL,
NULL,
0,
&JournalData,
sizeof(JournalData),
&dwBytes,
NULL) )
{
printf( "Query journal failed (%d)\n", GetLastError());
return;
}
ReadData.UsnJournalID = JournalData.UsnJournalID;
printf( "Journal ID: %I64x\n", JournalData.UsnJournalID );
printf( "FirstUsn: %I64x\n\n", JournalData.FirstUsn );
for(I=0; I<=10; I++)
{
memset( Buffer, 0, BUF_LEN );
if( !DeviceIoControl( hVol,
FSCTL_READ_USN_JOURNAL,
&ReadData,
sizeof(ReadData),
&Buffer,
BUF_LEN,
&dwBytes,
NULL) )
{
printf( "Read journal failed (%d)\n", GetLastError());
return;
}
dwRetBytes = dwBytes - sizeof(USN);
// Find the first record
UsnRecord = (PUSN_RECORD)(((PUCHAR)Buffer) + sizeof(USN));
printf( "****************************************\n");
// This loop could go on for a long time, given the current buffer size.
while( dwRetBytes > 0 )
{
printf( "USN: %I64x\n", UsnRecord->Usn );
printf("File name: %.*S\n",
UsnRecord->FileNameLength/2,
UsnRecord->FileName );
printf( "Reason: %x\n", UsnRecord->Reason );
printf( "\n" );
dwRetBytes -= UsnRecord->RecordLength;
// Find the next record
UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord) +
UsnRecord->RecordLength);
}
// Update starting USN for next call
ReadData.StartUsn = *(USN *)&Buffer;
}
CloseHandle(hVol);
}
I've managed to work out what the problem is.
The example Microsoft code creates a local variable defined as READ_USN_JOURNAL_DATA, which is defined as:
#if (NTDDI_VERSION >= NTDDI_WIN8)
typedef READ_USN_JOURNAL_DATA_V1 READ_USN_JOURNAL_DATA, *PREAD_USN_JOURNAL_DATA;
#else
typedef READ_USN_JOURNAL_DATA_V0 READ_USN_JOURNAL_DATA, *PREAD_USN_JOURNAL_DATA;
#endif
On my systems (Both the Win10 and Win7 systems) this evaluates to READ_USN_JOURNAL_DATA_V1.
Looking at the difference betweem READ_USN_JOURNAL_DATA_V0 and READ_USN_JOURNAL_DATA_V1 we can see that V0 is defined as:
typedef struct {
USN StartUsn;
DWORD ReasonMask;
DWORD ReturnOnlyOnClose;
DWORDLONG Timeout;
DWORDLONG BytesToWaitFor;
DWORDLONG UsnJournalID;
} READ_USN_JOURNAL_DATA_V0, *PREAD_USN_JOURNAL_DATA_V0;
and the V1 version is defined as:
typedef struct {
USN StartUsn;
DWORD ReasonMask;
DWORD ReturnOnlyOnClose;
DWORDLONG Timeout;
DWORDLONG BytesToWaitFor;
DWORDLONG UsnJournalID;
WORD MinMajorVersion;
WORD MaxMajorVersion;
} READ_USN_JOURNAL_DATA_V1, *PREAD_USN_JOURNAL_DATA_V1;
Note the new Min and Max Major version members.
So, the Microsoft code is defining a local variable called ReadData that is actually a V1 structure, yet it appears to fill in the data assuming it's a V0 structure. i.e. it doesn't set the Min and Max elements.
It appears that Win7 is fine with this but Win10 rejects it and returns error 87 (The parameter is incorrect).
Sure enough if I explicitly define the ReadData variable to be a READ_USN_JOURNAL_DATA_V0 then the code works on Win7 and Win10, whereas if I explicitly define it as a READ_USN_JOURNAL_DATA_V1 then it continues to work on Win7 but not on Win10.
The strange thing is that the API documentation for READ_USN_JOURNAL_DATA_V1 structure states that it's only supported from Windows 8 on, so it's odd that it works on Windows 7 at all. I guess it's just interpreting it as a READ_USN_JOURNAL_DATA_V0 structure given that V1 version is an extension of the V0 structure. If so then it must be ignoring the size parameter that is passed into DeviceIOControl.
Anyway, all working now. I hope someone finds this a useful reference in the future.
I came across this exact same issue with the sample code as the OP. At the start of the sample code, you will see a partial initialization of the structure at the point of declaration. A little later in the code, right before the offending call, there is a line that assigns the UsnJournalID into the read data structure.
For Windows 10, though, the other two members of the V1 structure are not initialized. I initialized them right after the UsnJournalID's initialization with:
#if (NTDDI_VERSION >= NTDDI_WIN8)
ReadData.MinMajorVersion = JournalData.MinSupportedMajorVersion;
ReadData.MaxMajorVersion = JournalData.MaxSupportedMajorVersion;
#endif
When I ran my code after doing this, it worked correctly without the error code. I remember reading in the Volume Management API discussion that the Min and Max versions needed to be set. I forgot exactly where, because I've been reading and testing this stuff for a couple days.
Anyway, I hope that clarifies the issue for anyone coming after me.
Replace the READ_USN_JOURNAL_DATA structure with READ_USN_JOURNAL_DATA_V0 data structure and initialize it.
This worked for me
READ_USN_JOURNAL_DATA_V0 ReadData;
ZeroMemory(&ReadData, sizeof(ReadData));
ReadData.ReasonMask = 0xFFFFFFFF;

WriteProcessMemory in debugged process

I try to write simple debugger. For simplicity, assume the debugger runs under Windows XP.
At first I create new process as follows:
CreateProcess(processName,
NULL,
NULL,
NULL,
false,
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
NULL,
NULL,
&startInfo,
&openedProcessInfo);
And when I try to read or write something in memory of debugging process there are some problems. For example:
DWORD oldProtect;
if(!VirtualProtectEx(hProcess, breakpointAddr, 1, PAGE_EXECUTE_READWRITE, &oldProtect)) {
printf("Error: %d\n", GetLastError());
}
SIZE_T bytesRead = 0;
SIZE_T bytesWritten = 0;
BYTE instruction;
BOOL isOk = ReadProcessMemory(hProcess, breakpointAddr, &instruction, 1, &bytesRead);
BYTE originalByte = instruction;
instruction = 0xCC;
if(isOk && bytesRead == 1) {
isOk = WriteProcessMemory(hProcess, breakpointAddr, &instruction, 1, &bytesWritten);
if(isOk) {
isOk = FlushInstructionCache(hProcess, breakpointAddr, 1);
}
}
if(!isOk) {
printf("Error: %d\n", GetLastError());
}
It works, but not everywhere. It works when the address to which I want to write(read) something, is located within executable module (.exe).
But when I try to write(read) something within DLL library (for example, read at address of function VirtualAlloc) VirtualProtectEx returns false and GetLastError = 487 (Attempt to access invalid address) and ReadProcessMemory also returns false and GetLastError = 299 (Only part of a ReadProcessMemory or WriteProcessMemory request was completed.)
Debug privileges are enabled but it has no effect.
Your code looks fine, if you're running as administrator than the most likely cause of the problem is that breakpointAddr is an invalid address. VirtualProtectEx giving you the "Attempt to access invalid address" error supports this conclusion.

WinRar exit code different behavior in SP2/SP3 and 7

I am new to windows programming and have written a small utility with mingw which will unrar a package. The code is as provided below
Descrition:
When the below program is run, the results are as follows
XPSP2 32 bit and Windows 7
Untar Operation : Success
CreateProcess return code : Non Zero (Success)
exit Code : 0 (Success)
XP2SP3 32 bit
Untar Operation : Success
CreateProcess return code : Non Zero (Success)
exit Code : 3221225477
Problem Statement
I am not sure why in XP2SP3 patch only, the winRar operation provides the exit code as Huge positive value. Do you find any problem in the below code? Please help in this regard.
int main()
{
string ProgramName = "C:\\Program Files\\WinRAR\\WinRAR.exe";
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&StartupInfo, 0, sizeof(STARTUPINFO));
memset(&ProcessInfo, 0, sizeof(PROCESS_INFORMATION)
if (CreateProcess((LPCTSTR)ProgramName.c_str(),(LPCTSTR)"WinRAR.exe x -y -ibck d:\\abc.tar d:\\"),NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&StartupInfo,
&ProcessInfo) == 0)
{
string tmpStr("Error executing");
tmpStr += ProgramName;
cout<<"StmtDesigner"<<tmpStr<<"CreateProcess failed"<<endl;
}
else
{
string tmpStr("Succes executing");
tmpStr += ProgramName;
cout<<"StmtDesigner"<<tmpStr<<"CreateProcess Success"<<endl;
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
DWORD exitCode=0;
if (GetExitCodeProcess(ProcessInfo.hProcess, &exitCode))
{
string tmpStr("GetExitCodeProcess");
tmpStr += ProgramName;
cout<<tmpStr<<"WinRAR.exe x -y -ibc<<endl;
}
}
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
getch();
return 0;
}
PS : WinRar 3.8 version trail Mode is used for above testing.
That huge positive number, in hexadecimal, is 0xC0000005. It's a common Windows error, which means "Access Violation". Why exactly are you getting it really depends on what winrar is trying to do, but the problem might be with access rights to files. I suggest you give it a try with ProcMon watching your program's file activity. If accessing one of the files is denied, you'll see it in the log.

How can I get the process filename under Vista?

I have an application that aids people with disabilities. In order to work, it tracks the what window is currently in the foreground. Normally, I use this function to get process executable.
bool GetWindowProcessExe2(HWND hwnd, wxString& process_exe)
//LPTSTR buf, DWORD size)
{
DWORD result = 0;
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
if (HANDLE process =
OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
{
char buff[512];
LPTSTR pbuff = buff;
result = GetModuleFileNameEx(process, 0, pbuff, 512);
if(result == 0)
{
//failed.
wxLogError("GetModuleFileNameEx failed with error code %d", GetLastError());
}
CloseHandle(process);
process_exe = fromCString(pbuff);
}
return result > 0 ? true : false;
}
Unfortunately, if the foreground window is the Vista file manager window (the window that opens when you click Start->Computer), GetModuleFileNameEx() fails with error code 299 which says I don't have privileges for this action. My code works for any regular application but not for the windows built in window (the file explorer). I need to know when this window is forefront. Is there another way to do it? I tried reading the window title but that just returns the current directory being shown. Any ideas?
I'm not sure why this isn't working for explorer, but error 299 is ERROR_PARTIAL_COPY, meaning that attempting to read the module name out of explorer is failing.
On Vista, prefer QueryProcessImageFileName and only open the process with PROCESS_QUERY_LIMITED_INFORMATION - your code will work in more cases.
WCHAR exeName[512];
DWORD cchExeName = 512;
HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
QueryFullProcessImageName(process, 0, exeName, &cchExeName);
EDIT: I also got ERROR_PARTIAL_COPY with your code running on 64-bit, but only when the querying process was 32-bit. 64-bit/64-bit worked fine.
Looks like a 32 bit process can call GetModuleFileNameEx only on othere 32 bit processes. If you try to call it on 64 bit processes it fails with ERROR_PARTIAL_COPY.On a 64 bit platform make the calling process 64 bit and you should be able to call GetModuleFileNameEx on both 64 and 32 bit processes.

Resources