CreateToolhelp32Snapshot isn't detecting all the modules for a certain process - c

My code is only outputting a few modules in the process, when there are much more. The procID is correct as i've checked in task manager. I would like it to return every single module in the process.
I'm using a C compiler for this. Is this a problem?
uintptr_t findModuleAddress (char* name, DWORD procID){
MODULEENTRY32 entry;
entry.dwSize = sizeof(MODULEENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, procID);
uintptr_t cModuleAddress = 0;
Module32First(snapshot,&entry);
while (Module32Next(snapshot, &entry)){
printf("%s\n",entry.szModule);
if (!strcmp(name,entry.szModule)){
printf("Found module\n");
cModuleAddress = (uintptr_t)entry.modBaseAddr;
break;
}
}
CloseHandle(snapshot);
return cModuleAddress;
}
The output:

Related

How do I handle errors from cleanup / destroy functions

I am struggeling with cleanup code which returns error codes/objects. Examples on how to cleanup a function usually just call free() at the end or anything not returning an error. But a destroy function of a module could be complex and maybe also return errors. Even close() could return a error although often unchecked.
How do you handle situations like that? Do you just log but ignore the error otherwise, do you return the error code of the *_destroy function at the end? Would you somehow restructure the code? What is the recommended solution here?
Thank you
int moduleA_create(moduleA *handle, int param1, int param2, int param3, int param4);
int moduleA_destroy(moduleA handle);
int moduleB_create(moduleB *handle, const char *param);
int moduleB_destroy(moduleB handle);
int some_function(void) {
int r;
moduleA a;
moduleB b;
r = moduleA_create(&a, 1, 2, 3, 4);
if (r < 0) goto EXIT_A;
r = moduleB_create(&b, "some string");
if (r < 0) goto EXIT_B;
// more code
// this could return error
moduleB_destroy(b);
EXIT_B:
// this could return error
moduleA_destroy(a);
EXIT_A:
return r;
}
Do you just log but ignore the error otherwise, do you return the error code of the *_destroy function at the end? Would you somehow restructure the code? What is the recommended solution here?
It's highly situation-dependent, as, indeed, is error-handling in general. Often, there's not much you can do other than emit messages / different return values, and possibly abort the program.
If the error happens in the context of shutting down the application, as your particular example suggests to me, then I would be inclined to attempt to continue the standard shutdown sequence. A diagnostic message to stderr might be warranted. A non-zero exit status might be warranted. Or not.
For example, I usually just ignore failures to close() / fclose() files that were only read, but I would definitely emit a warning or error message on failing to close a file that the program had created or written to, on account of the possibility that the program's operations on the file might not have actually been carried out as intended.
"Would you somehow restructure the code?"
Rather than using goto with its opportunity for code to be wrong, sequenced progress may require undoing what's been done (as best one can) in exactly the reverse order.
Below is a sketch that demonstrates one "successful" trial run, and one run deliberately coded to fail on the 3rd step. It uses the conditional operator for brevity, and always the return code "-1" from teardown functions. This is just a sketch.
Notice that the progress/teardown function invocations are proximate to one another and that the sequence reverses itself.
This code would, of course, be altered to meet needs. It provides a schema that does not require goto labels to be ordered in code, distant from where they may be "used". This is one alternative to "restructuring the code".
int doPh1R() { puts( "doPh1R" ); return -1; }
int doPh1F() { puts( "doPh1F" ); return 1; }
int doPh2R() { puts( "doPh2R" ); return -1; }
int doPh2F() { puts( "doPh2F" ); return 1; }
int doPh3R() { puts( "doPh3R" ); return -1; }
int doPh3F() {
static bool cond = true;
if( cond ) {
puts( "doPh3F" );
cond = !cond; // boobytrap the next execution
return 1;
}
puts( "doPh3F Error" );
return -1;
}
int doSomething( int trial ) {
enum { done, phase1, phase2, phase3, run };
int dir = 1;
int err = -1; // pessimism
printf( "\tTrial #%d\n", trial );
for( int phase = phase1; phase != done; phase += dir )
switch( phase ) {
case phase1:
dir = dir==1 ? doPh1F() : doPh1R();
break;
case phase2:
dir = dir==1 ? doPh2F() : doPh2R();
break;
case phase3:
dir = dir==1 ? doPh3F() : doPh3R();
break;
case run:
puts( "run" );
dir = -1;
err = 0;
break;
}
return err;
}
int main() {
puts( doSomething(1) ? "\tFail" : "\tSuccess" ); // One good run
puts( doSomething(2) ? "\tFail" : "\tSuccess" ); // One bad run
return 0;
}
Output
Trial #1
doPh1F
doPh2F
doPh3F
run
doPh3R
doPh2R
doPh1R
Success
Trial #2
doPh1F
doPh2F
doPh3F Error
doPh2R
doPh1R
Fail

UEFI - EDK2 - Hooking SetVariable results in UNEXCEPTED_KERNEL_MODE_TRAP

I'm coding a UEFI Runtime Driver for Windows which hooks gRT->SetVariable(...)
Hooking seems to work fine but whenever I startup a user-mode application and call SetFirmwareEnvironmentVariable(...) it reults in a Bluescreen saying UNEXCEPTED_KERNEL_MODE_TRAP.
I cannot find any solution for this. Here are a few things iam aware of:
I'm raising TPL
I recalculate and set CRC32
On SetVirtualAddressMap(...) i convert all my pointer
Google didn't help at all. So i really wonder what causes this Bluescreen and how i may proceed to resolve this issue.
What am i missing? Am i doing something wrong?
Here is my code:
ExchangePointerInServiceTable((VOID**)&gST->RuntimeServices->SetVariable,
(VOID*)HookedSetVariable,
(VOID**)&gOriginalSetVariable);
static
EFI_STATUS
ExchangePointerInServiceTable(
IN OUT VOID** AddressToUpdate,
IN VOID* NewPointer,
OUT VOID** OriginalPointer OPTIONAL
)
{
EFI_STATUS status;
EFI_TPL tpl;
ASSERT(*AddressToUpdate != NewPointer);
tpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);
if (OriginalPointer != NULL)
{
*OriginalPointer = *AddressToUpdate;
}
*AddressToUpdate = NewPointer;
gST->Hdr.CRC32 = 0;
status = gBS->CalculateCrc32(&gST->Hdr, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
ASSERT_EFI_ERROR(status);
gBS->RestoreTPL(tpl);
return status;
}
EFI_STATUS
EFIAPI
HookedSetVariable(
IN CHAR16* VariableName,
IN EFI_GUID* VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID* Data
) {
if (StrCmp(VariableName, gStrComVarName) == 0) {
COMMUNICATION_PROTOCOL * comVarPtr = (COMMUNICATION_PROTOCOL*)Data;
switch (comVarPtr->i8OperationId) {
case COMMUNICATION_PROTOCOL_OPERATION_PING:
comVarPtr->i8OperationId = COMMUNICATION_PROTOCOL_PONG;
}
CopyMem(Data, comVarPtr, DataSize);
}
return gOriginalSetVariable(VariableName, VendorGuid, Attributes, DataSize, Data);
}
Edit: While in UEFI, other UEFI Applications correctly call the hooked SetVariable(...) without any further problems.
This may bring it down to the problem only existing after VirtualAddressSpace has been created from the OS.

Getting parent for kobject_add

Is there any simple method for getting parent to use in kobject_add function? I want to put the file in /sys/module/mymodule/parameters. I've got already working parameter, but I create it in wrong directory. I've found that there is module_subsys in module.h, but I have no idea how to use it.
It's my code for init function:
static int __init init_hello(void)
{
subsystem_register(&module_subsys);
struct my_attr *a;
Major = misc_register(&mydevice);
mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL);
if (mykobj) {
kobject_init(mykobj, &mytype);
kobj_set_kset_s(mykobj, module_subsys);
if (kobject_add(mykobj, NULL, "%s", "sysfs_example")) {
printk("Sysfs creation failed\n");
kobject_put(mykobj);
mykobj = NULL;
return -1;
}
}
a = container_of(&(my_first.attr), struct my_attr, attr);
msg_Ptr = kzalloc(a->value, GFP_KERNEL);
bytesindev=0;
if(Major) {
printk(KERN_ALERT "Rejestrowanie urządzenia nie powiodło się\n");
return Major;
}
return SUCCESS;
}
Never tried it myself, but &THIS_MODULE->mkobj.kobj looks appropriate.
I didn't see any kernel code that uses kobject_add directly with this, so perhaps it isn't the right way.
If you've registered a device driver, then &dev->kobj looks like a good way.

Suspend/Resume all user processes - Is that possible?

I have PC's with a lot of applications running at once, i was thinking is it possible to SUSPEND all applications, i want to do that to run periodically one other application that is using a lot the CPU so want it to have all the processor time.
The thing is i want to suspend all applications run my thing that uses the CPU a lot, then when my thingy exit, to resume all applications and all work to be resumed fine....
Any comments are welcome.
It's possible but not recommended at all.
Set the process and thread priority so your application will be given a larger slice of the CPU.
This also means it won't kill the desktop, any network connections, antivirus, start menu, the window manager, etc as your method will.
You could possibly keep a list that you yourself manually generate of programs that are too demanding (say, for (bad) example, Steam.exe, chrome.exe, 90GB-video-game.exe, etc). Basically, you get the entire list of all running processes, search that list for all of the blacklisted names, and NtSuspendProcess/NtResumeProcess (should you need to allow it to run again in the future).
I don't believe suspending all user processes is a good idea. Much of those are weirdly protected and probably should remain running, anyway, and it's an uphill battle with very little to gain.
As mentioned in another answer, you can of course just adjust your processes priority up if you have permission to do so. This sorts the OS-wide process list in favor of your process, so you get CPU time first.
Here's an example of something similar to your original request. I'm writing a program in C++ that needed this exact feature, so I figured I'd help out. This will find Steam.exe or chrome.exe, and suspend the first one it finds for 10 seconds.. then will resume it. This will show as "not responding" on Windows if you try to interact with the window whilst it's suspended. Some applications may not like being suspended, YMMV.
/*Find, suspend, resume Win32 C++
*Written by jimmio92. No rights reserved. Public domain.
*NO WARRANTY! NO LIABILITY! (obviously)
*/
#include <windows.h>
#include <psapi.h>
typedef LONG (NTAPI *NtSuspendProcess)(IN HANDLE ProcessHandle);
typedef LONG (NTAPI *NtResumeProcess)(IN HANDLE ProcessHandle);
NtSuspendProcess dSuspendProcess = nullptr;
NtResumeProcess dResumeProcess = nullptr;
int get_the_pid() {
DWORD procs[4096], bytes;
int out = -1;
if(!EnumProcesses(procs, sizeof(procs), &bytes)) {
return -1;
}
for(size_t i = 0; i < bytes/sizeof(DWORD); ++i) {
TCHAR name[MAX_PATH] = "";
HMODULE mod;
HANDLE p = nullptr;
bool found = false;
p = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, procs[i]);
if(p == nullptr)
continue;
DWORD unused_bytes_for_all_modules = 0;
if(EnumProcessModules(p, &mod, sizeof(mod), &unused_bytes_for_all_modules)) {
GetModuleBaseName(p, mod, name, sizeof(name));
//change this to use an array of names or whatever fits your need better
if(strcmp(name, "Steam.exe") == 0 || strcmp(name, "chrome.exe") == 0) {
out = procs[i];
found = true;
}
}
CloseHandle(p);
if(found) break;
}
return out;
}
void suspend_process_by_id(int pid) {
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(h == nullptr)
return;
dSuspendProcess(h);
CloseHandle(h);
}
void resume_process_by_id(int pid) {
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(h == nullptr)
return;
dResumeProcess(h);
CloseHandle(h);
}
void init() {
//load NtSuspendProcess from ntdll.dll
HMODULE ntmod = GetModuleHandle("ntdll");
dSuspendProcess = (NtSuspendProcess)GetProcAddress(ntmod, "NtSuspendProcess");
dResumeProcess = (NtResumeProcess)GetProcAddress(ntmod, "NtResumeProcess");
}
int main() {
init();
int pid = get_the_pid();
if(pid < 0) {
printf("Steam.exe and chrome.exe not found");
}
suspend_process_by_id(pid);
//wait ten seconds for demonstration purposes
Sleep(10000);
resume_process_by_id(pid);
return 0;
}

tmpfile() on windows 7 x64

Running the following code on Windows 7 x64
#include <stdio.h>
#include <errno.h>
int main() {
int i;
FILE *tmp;
for (i = 0; i < 10000; i++) {
errno = 0;
if(!(tmp = tmpfile())) printf("Fail %d, err %d\n", i, errno);
fclose(tmp);
}
return 0;
}
Gives errno 13 (Permission denied), on the 637th and 1004th call, it works fine on XP (haven't tried 7 x86). Am I missing something or is this a bug?
I've got similar problem on Windows 8 - tmpfile() was causing win32 ERROR_ACCESS_DENIED error code - and yes, if you run application with administrator privileges - then it works fine.
I guess problem is mentioned over here:
https://lists.gnu.org/archive/html/bug-gnulib/2007-02/msg00162.html
Under Windows, the tmpfile function is defined to always create
its temporary file in the root directory. Most users don't have
permission to do that, so it will often fail.
I would suspect that this is kinda incomplete windows port issue - so this should be an error reported to Microsoft. (Why to code tmpfile function if it's useless ?)
But who have time to fight with Microsoft wind mills ?! :-)
I've coded similar implementation using GetTempPathW / GetModuleFileNameW / _wfopen. Code where I've encountered this problem came from libjpeg - I'm attaching whole source code here, but you can pick up code from jpeg_open_backing_store.
jmemwin.cpp:
//
// Windows port for jpeg lib functions.
//
#define JPEG_INTERNALS
#include <Windows.h> // GetTempFileName
#undef FAR // Will be redefined - disable warning
#include "jinclude.h"
#include "jpeglib.h"
extern "C" {
#include "jmemsys.h" // jpeg_ api interface.
//
// Memory allocation and freeing are controlled by the regular library routines malloc() and free().
//
GLOBAL(void *) jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
{
return (void *) malloc(sizeofobject);
}
GLOBAL(void) jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
{
free(object);
}
/*
* "Large" objects are treated the same as "small" ones.
* NB: although we include FAR keywords in the routine declarations,
* this file won't actually work in 80x86 small/medium model; at least,
* you probably won't be able to process useful-size images in only 64KB.
*/
GLOBAL(void FAR *) jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
{
return (void FAR *) malloc(sizeofobject);
}
GLOBAL(void) jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
{
free(object);
}
//
// Used only by command line applications, not by static library compilation
//
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
#endif
GLOBAL(long) jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated)
{
// jmemansi.c's jpeg_mem_available implementation was insufficient for some of .jpg loads.
MEMORYSTATUSEX status = { 0 };
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
if( status.ullAvailPhys > LONG_MAX )
// Normally goes here since new PC's have more than 4 Gb of ram.
return LONG_MAX;
return (long) status.ullAvailPhys;
}
/*
Backing store (temporary file) management.
Backing store objects are only used when the value returned by
jpeg_mem_available is less than the total space needed. You can dispense
with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
METHODDEF(void) read_backing_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(cinfo, JERR_TFILE_SEEK);
size_t readed = fread( buffer_address, 1, byte_count, info->temp_file);
if (readed != (size_t) byte_count)
ERREXIT(cinfo, JERR_TFILE_READ);
}
METHODDEF(void)
write_backing_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(cinfo, JERR_TFILE_SEEK);
if (JFWRITE(info->temp_file, buffer_address, byte_count) != (size_t) byte_count)
ERREXIT(cinfo, JERR_TFILE_WRITE);
// E.g. if you need to debug writes.
//if( fflush(info->temp_file) != 0 )
// ERREXIT(cinfo, JERR_TFILE_WRITE);
}
METHODDEF(void)
close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
{
fclose(info->temp_file);
// File is deleted using 'D' flag on open.
}
static HMODULE DllHandle()
{
MEMORY_BASIC_INFORMATION info;
VirtualQuery(DllHandle, &info, sizeof(MEMORY_BASIC_INFORMATION));
return (HMODULE)info.AllocationBase;
}
GLOBAL(void) jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed)
{
// Generate unique filename.
wchar_t path[ MAX_PATH ] = { 0 };
wchar_t dllPath[ MAX_PATH ] = { 0 };
GetTempPathW( MAX_PATH, path );
// Based on .exe or .dll filename
GetModuleFileNameW( DllHandle(), dllPath, MAX_PATH );
wchar_t* p = wcsrchr( dllPath, L'\\');
wchar_t* ext = wcsrchr( p + 1, L'.');
if( ext ) *ext = 0;
wchar_t* outFile = path + wcslen(path);
static int iTempFileId = 1;
// Based on process id (so processes would not fight with each other)
// Based on some process global id.
wsprintfW(outFile, L"%s_%d_%d.tmp",p + 1, GetCurrentProcessId(), iTempFileId++ );
// 'D' - temporary file.
if ((info->temp_file = _wfopen(path, L"w+bD") ) == NULL)
ERREXITS(cinfo, JERR_TFILE_CREATE, "");
info->read_backing_store = read_backing_store;
info->write_backing_store = write_backing_store;
info->close_backing_store = close_backing_store;
} //jpeg_open_backing_store
/*
* These routines take care of any system-dependent initialization and
* cleanup required.
*/
GLOBAL(long)
jpeg_mem_init (j_common_ptr cinfo)
{
return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
}
GLOBAL(void)
jpeg_mem_term (j_common_ptr cinfo)
{
/* no work */
}
}
I'm intentionally ignoring errors from some of functions - have you ever seen GetTempPathW or GetModuleFileNameW failing ?
A bit of a refresher from the manpage of on tmpfile(), which returns a FILE*:
The file will be automatically deleted when it is closed or the program terminates.
My verdict for this issue: Deleting a file on Windows is weird.
When you delete a file on Windows, for as long as something holds a handle, you can't call CreateFile on something with the same absolute path, otherwise it will fail with the NT error code STATUS_DELETE_PENDING, which gets mapped to the Win32 code ERROR_ACCESS_DENIED. This is probably where EPERM in errno is coming from. You can confirm this with a tool like Sysinternals Process Monitor.
My guess is that CRT somehow wound up creating a file that has the same name as something it's used before. I've sometimes witnessed that deleting files on Windows can appear asynchronous because some other process (sometimes even an antivirus product, in reaction to the fact that you've just closed a delete-on-close handle...) will leave a handle open to the file, so for some timing window you will see a visible file that you can't get a handle to without hitting delete pending/access denied. Or, it could be that tmpfile has simply chosen a filename that some other process is working on.
To avoid this sort of thing you might want to consider another mechanism for temp files... For example a function like Win32 GetTempFileName allows you to create your own prefix which might make a collision less likely. That function appears to resolve race conditions by retrying if a create fails with "already exists", so be careful about deleting the temp filenames that thing generates - deleting the file cancels your rights to use it concurrently with other processes/threads.

Resources