Windows DLL global variables - windows

A DLL loaded into a Windows app is composed of an entry point (DLLMain()) and other functions that can be called from there. Now, how do I make a variable global amongst all those functions for every process and thread that attaches to this DLL?
Currently, I need to open/close a file every time one of the functions is called. Since these functions are called very often it is a real performance problem opening/closing the file each time.
wofstream wofstr;
int WINAPI func(LPCWSTR lpString)
{
...
//wofstr.open(...);
wofstr << lpString << endl; // *** NOT working without opening in this very function
...
//wofstr.close(...);
...
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
...
case DLL_PROCESS_ATTACH:
wofstr.open(...); // *** NOT seen in function above
...
case DLL_THREAD_ATTACH:
...
case DLL_THREAD_DETACH:
...
case DLL_PROCESS_DETACH:
wofstr.close(...)
...
}
What am I missing here? What about threads?

Each global variable in a Windows DLL has a single instance for each process that loads the DLL. There is a one-to-one mapping between processes and global variable instances. Processes are completely isolated from each other and one process cannot directly access memory in a different process.
If you want to share a variable between processes then you will need some form of inter-process communication (IPC). For example you could set up a logging app to which your DLL could send messages.

Related

Is there a race between starting and seeing yourself in WinApi's EnumProcesses()?

I just found this code in the wild:
def _scan_for_self(self):
win32api.Sleep(2000) # sleep to give time for process to be seen in system table.
basename = self.cmdline.split()[0]
pids = win32process.EnumProcesses()
if not pids:
UserLog.warn("WindowsProcess", "no pids", pids)
for pid in pids:
try:
handle = win32api.OpenProcess(
win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ,
pywintypes.FALSE, pid)
except pywintypes.error, err:
UserLog.warn("WindowsProcess", str(err))
continue
try:
modlist = win32process.EnumProcessModules(handle)
except pywintypes.error,err:
UserLog.warn("WindowsProcess",str(err))
continue
This line caught my eye:
win32api.Sleep(2000) # sleep to give time for process to be seen in system table.
It suggests that if you call EnumProcesses() too fast after starting, you won't see yourself. Is there any truth to this?
There is a race, but it's not the race the code tried to protect against.
A successful call to CreateProcess returns only after the kernel object representing the process has been created and enqueued into the kernel's process list. A subsequent call to EnumProcesses accesses the same list, and will immediately observe the newly created process object.
That is, unless the process object has since been destroyed. This isn't entirely unusual since processes in Windows are initialized in-process. The documentation even makes note of that:
Note that the function returns before the process has finished initialization. If a required DLL cannot be located or fails to initialize, the process is terminated.
What this means is that if a call to EnumProcesses immediately following a successful call to CreateProcess doesn't observe the newly created process, it does so because it was late rather than early. If you are late already then adding a delay will only make you more late.
Which swiftly leads to the actual race here: Process IDs uniquely identify processes only for a finite time interval. Once a process object is gone, its ID is up for grabs, and the system will reuse it at some point. The only reliable way to identify a process is by holding a handle to it.
Now it's anyone's guess what the author of _scan_for_self was trying to accomplish. As written, the code takes more time to do something that's probably altogether wrong1 anyway.
1 Turns out my gut feeling was correct. This is just your average POSIX developer, that, in the process of learning that POSIX is insufficient would rather call out Microsoft instead of actually using an all-around superior API.
The documentation for EnumProcesses (WIn32 API - EnumProcesses function), does not mention anything about a delay needed to see the current process in the list it returns.
The example from Microsoft how to use EnumProcess to enumerate all running processes (Enumerating All Processes), also does not contain any delay before calling EnumProcesses.
A small test application I created in C++ (see below) always reports that the current process is in the list (tested on Windows 10):
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
#include <vector>
const DWORD MAX_NUM_PROCESSES = 4096;
DWORD aProcesses[MAX_NUM_PROCESSES];
int main(void)
{
// Get the list of running process Ids:
DWORD cbNeeded;
if (!EnumProcesses(aProcesses, MAX_NUM_PROCESSES * sizeof(DWORD), &cbNeeded))
{
return 1;
}
// Check if current process is in the list:
DWORD curProcId = GetCurrentProcessId();
bool bFoundCurProcId{ false };
DWORD numProcesses = cbNeeded / sizeof(DWORD);
for (DWORD i=0; i<numProcesses; ++i)
{
if (aProcesses[i] == curProcId)
{
bFoundCurProcId = true;
}
}
std::cout << "bFoundCurProcId: " << bFoundCurProcId << std::endl;
return 0;
}
Note: I am aware that the fact that the program reported the expected result does not mean that there is no race. Maybe I just couldn't catch it manifest. But trying to run code like that can give you a hint sometimes (especially if the result would have been that there is a race).
The fact that I never had a problem running this test (did it many times), together with the lack of any mention of the need for a delay in Microsoft's documentation make me believe that it is not required.
My conclusion is that either:
There is a unique issue when using it from python (doubt it).
or:
The code you found is doing something unnecessary.
There is no race.
EnumProcesses calls a NT API function that switches to kernel mode to walk the linked list of processes. Your own process has been added to the list before it starts running.

How to identify the window is belong to a specific process?

Win32 programs have an entry parameter HINSTANCE for the Win32 entry function WinMain(). When you create your own window, the CreateWindow() API call needs this parameter.
My first idea in my mind is that this HINSTANCE should be some unique identify to distinguish different windows belong to different processes. Until recently, in some occasions, I use this HINSTANCE. Wow! If you open the same Win32 program (EXE) twice, each process has the same HINSTANCE value.
Later I figured out, it was some resource identifier (memory address) in the process. It's a virtual address for the process which is related to its PE structure in memory.
Now, if I have the two windows' HWND handles, and I want to check whether the two windows are from the same process, what is the best choice?
You can use the GetWindowThreadProcessId function to retrieve the ID of the process that created a window, given that window's HWND.
Below is a brief C code snippet showing how. We check that the return value of each GetWindowThreadProcessId() call is not zero (see this answer or this blog by Raymond Chen), to ensure that we have passed valid HWND handles.
// win1 and win2 are both HWND handles to check...
DWORD proc1, proc2;
if (!GetWindowThreadProcessId(win1, &proc1)) { // Error (invalid HWND?)
//.. error handling
}
if (!GetWindowThreadProcessId(win2, &proc2)) {
//..
}
if (proc1 == proc2) {
// Windows created by same process
}
else {
// Windows created by different processes
}
GetWindowThreadProcessId can do the work. Record here.
An interactive way to do this would be to use Microsoft's Spy++, which lets you find the Process ID, Thread ID, and parents/children of a window by point-and-clicking its GUI.
You can also find window handles (and plenty of other window-specific data) in this way.

How to conditionally execute function if operating system supports it?

I'd like to build an application that invokes CancelIoEx on Windows Vista and newer (where it is supported) and does something else on Windows XP (where it is not).
What happens if I compile the application under Windows 7 but run it under Windows XP? What will happen at runtime? Will I get some sort of load error?
How do I get my application to pick one code path or another (avoiding load errors) depending on what operating system is being used at runtime? Please provide sample code.
UPDATE: Please note that the DLL exists on Windows XP but the function does not.
Yes, an application that references a non-existent DLL export will fail to load.
Adding code to take different paths based on the OS version won't help much, because you'll still have the reference to the non-existent function.
Instead, you need to resolve the reference at run-time.
One option is Delay Load Import (with the /DELAYLOAD linker flag), but I don't think this is supported for the core system DLLs (like kernel32).
The other is to use LoadLibrary and GetProcAddress. The code is something like this, though in reality you'd do the lookup once when your app starts, not each time you call the function.
// Declare type of pointer to CancelIoEx function
typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
// Load module; won't fail because it's already imported
HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
// Look up function address
CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
// Do something with it
if (pCancelIoEx)
{
// Function exists so call it
pCancelIoEx(hMyFile, pMyOverlapped);
}
else
{
// Function doesn't exist
}
In order to resolve a symbol at runtime, you need to use LoadLibrary and GetProcAddress:
HMODULE kernel32 = LoadLibrary("kernel32.dll");
BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED) = GetProcAddress(kernel32, "CancelIoEx");
In the case that CancelIoEx is not available, you will get NULL back from GetProcAddress. Once you have the pointer (you only need to do the above once), you can call it normally with:
pCancelIoEx(h, &lp);

Simple way to hook registry access for specific process

Is there a simple way to hook registry access of a process that my code executes? I know about SetWindowsHookEx and friends, but its just too complex... I still have hopes that there is a way as simple as LD_PRELOAD on Unix...
Read up on the theory of DLL Injection here: http://en.wikipedia.org/wiki/DLL_injection
However, I will supply you with a DLL Injection snippet here: http://www.dreamincode.net/code/snippet407.htm
It's pretty easy to do these types of things once you're in the memory of an external application, upon injection, you might as well be a part of the process.
There's something called detouring, which I believe is what you're looking for, it simply hooks a function, and when that process calls it, it executes your own function instead. (To ensure that it doesn't crash, call the function at the end of your function)
So if you were wanting to write your own function over CreateRegKeyEx
(http://msdn.microsoft.com/en-us/library/ms724844%28v=vs.85%29.aspx)
It might look something like this:
LONG WINAPI myRegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
{
//check for suspicious keys being made via the parameters
RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
}
You can get a very well written detour library called DetourXS here: http://www.gamedeception.net/threads/10649-DetourXS
Here is his example code of how to establish a detour using it:
#include <detourxs.h>
typedef DWORD (WINAPI* tGetTickCount)(void);
tGetTickCount oGetTickCount;
DWORD WINAPI hGetTickCount(void)
{
printf("GetTickCount hooked!");
return oGetTickCount();
}
// To create the detour
oGetTickCount = (tGetTickCount) DetourCreate("kernel32.dll", "GetTickCount", hGetTickCount, DETOUR_TYPE_JMP);
// ...Or an address
oGetTickCount = (tGetTickCount) DetourCreate(0x00000000, hGetTickCount, DETOUR_TYPE_JMP);
// ...You can also specify the detour len
oGetTickCount = (tGetTickCount) DetourCreate(0x00000000, hGetTickCount, DETOUR_TYPE_JMP, 5);
// To remove the detour
DetourRemove(oGetTickCount);
And if you can't tell, that snippet is hooking GetTickCount() and whenever the function is called, he writes "GetTickCount hooked!" -- then he executes the function GetTickCount is it was intended.
Sorry for being so scattered with info, but I hope this helps. :)
-- I realize this is an old question. --
Most winapi calls generate symbol table entries for inter modular calls, this makes it pretty simple to hook them, all you need to do is overwrite the IAT addresses. Using something such as MSDetours, it can be done safely in a few lines of code. MSDetours also provides the tools to inject a custom dll into the target process so you can do the hooking
SetWindowsHookEx won't help at all - it provides different functionality.
Check if https://web.archive.org/web/20080212040635/http://www.codeproject.com/KB/system/RegMon.aspx helps. SysInternals' RegMon uses a kernel-mode driver which is very complicated way.
Update: Our company offers CallbackRegistry product, that lets you track registry operations without hassle. And BTW we offer free non-commercial licenses upon request (subject to approval on case by case basis).

How can I tell if a Windows module handle is still valid?

A module can be unloaded, so how can I tell for sure if it is still in memory? I have a handle to it, obtained from GetModuleHandle. When I tried calling GetHandleInformation on it I see error 0xc0000008 - "An invalid HANDLE was specified." This happened before it could have been unloaded.
The term "handle" is a bit overloaded here - lots of different classes of objects in the Win32 API are called "Handles".
GetHandleInformation is used for handles to kernel objects - files, registry keys, mutexes, etc.
The HMODULE returned by GetModuleHandle is used by the loader and is not an actual kernel object, hence GetHandleInformation fails. Neither of the flags you get in GetHandleInformation makes sense for HMODULE though.
If you want to check if the HMODULE is still loaded in memory, you can just call GetModuleHandle - this API should be quick enough to call many times. However, the result of GetModuleHandle can be invalid the moment it returns - another thread could have called FreeLibrary. It is better to ensure that the DLL does stay loaded. You can do this by calling LoadLibrary yourself, or by calling GetModuleHandleEx which will increment the reference count of the DLL.
Two solutions:
1
Call GetModuleFileName() on the HMODULE. If the module is loaded you will get a valid filename. If it is not loaded, you won't get a valid filename. Be sure to either set the first byte of the returned filename array to '\0' before you call GetModuleFileName() or to check the return value. If you set the first byte before the call you can effectively ignore the return value and just treat the zero length string as a "not loaded" signal.
TCHAR szModName[MAX_PATH + 1];
szModName[0] = _T('\0');
GetModuleFileName(hMod, szModName, MAX_PATH);
// zero length string if not loaded, valid DLL name if still loaded
2
Call VirtualQuery() passing the HMODULE as the address to query. As an experiment do this on a loaded library and on a library you know to be freed. You will find they have very differentl results for the returned MEMORY_BASIC_INFORMATION. I leave it to you to work out a suitable algorithm to determine the difference between the two.
Caveat
Of course, the caveat that another thread may unload the library while you are running eiher of these tests applies. In my experience, this is highly unlikely to happen, but that depends very much on what you are doing, why you are doing it, and when you are doing it the program's execution path. Use with care.
It's very simple API.
PIMAGE_NT_HEADERS (NTAPI* _RtlImageNtHeader)
Sample program:
(PVOID)typedef PIMAGE_NT_HEADERS (NTAPI *RTLIMAGENTHEADER)(PVOID);
RTLIMAGENTHEADER RtlImageNtHeader;
HMODULE hDll = GetModuleHandle("ntdll.dll");
HMODULE hDllTmp = LoadLibrary("ws2_32.dll");
RtlImageNtHeader = (RTLIMAGENTHEADER)GetProcAddress(hDll,"RtlImageNtHeader");
struct _IMAGE_NT_HEADERS *r,*r2;
r= RtlImageNtHeader(hDllTmp);
FreeLibrary(hDllTmp);
r2= RtlImageNtHeader(hDllTmp);
//r = NULL
//r2 = return ws2_32 PE Header address

Resources