From d6bddeddd45c211d931b49c7efbc219419a4b5b2 Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Wed, 12 Nov 2014 00:36:32 +0000 Subject: [PATCH] msys2-unlocker: Minor reorgs + clang-format (WIP) --- msys2-unlocker/main.c | 589 +++++++++++++++++++++++------------------- 1 file changed, 319 insertions(+), 270 deletions(-) diff --git a/msys2-unlocker/main.c b/msys2-unlocker/main.c index bd7a6dcf..5444ae1a 100644 --- a/msys2-unlocker/main.c +++ b/msys2-unlocker/main.c @@ -9,89 +9,209 @@ .email: . */ -#include -#include -//#define WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN + #include #include + +#include #include + #include "resource.h" +typedef enum { + kUnlockHelpOnly, + kUnlockNone, + kUnlockGUI, + kUnlockForce, +} kUnlockAction; + +typedef enum { + + /* All is good */ + kSuccess = 0, + + /* User errors */ + kUserNoFiles, + kUserTooManyFiles, + kUserExited, + kUserCancelled, + + /* Failures */ + kFailEnumProc, + kFailForce, + +} kExitCode; + +typedef struct { + uint32_t lockedFilesMask; + DWORD processId; +} LockingProcess; + +/* Global variables plus things + that are updated dynamically */ +typedef struct { + HWND appHWnd; + size_t num_processes; + DWORD* p_processes; +} GlobalState; + +/* Values from the commandline */ +typedef struct { + kUnlockAction unlock_action; + size_t num_filenames; + char** p_filenames; +} Arguments; + +HWND FindConsoleHandle(void); + +void PrintHelp() { + printf( + "msys2-unlocker: Informs of and / or terminates\n" + " processes locking modules that\n" + " are passed in from the cmdline\n" + "\n" + "Usage: msys2-unlocker [options] files...\n" + "Options:\n" + " --help Display this message\n" + " --force Force quit locking processes\n" + " --gui Present unlocking GUI\n"); +} + +kExitCode ProcessArguments(int argc, char* argv[], Arguments* args) { + typedef enum { + kArgParseFirst, + kArgParseSwitches = kArgParseFirst, + kArgParseFilenames, + kArgParseCount, + } kArgParsePass; + + args->unlock_action = kUnlockNone; + args->num_filenames = 0; + args->p_filenames = NULL; + int argi; + kArgParsePass pass; + size_t num_filename_char = 0; + char* filename_chars; + + for (pass = kArgParseFirst; pass < kArgParseCount; ++pass) { + if (pass == kArgParseFilenames) { + args->p_filenames = (char**)malloc((sizeof(char*) * args->num_filenames) + + (sizeof(char) * num_filename_char)); + filename_chars = (char*)&args->p_filenames[args->num_filenames]; + args->num_filenames = 0; + } + for (argi = 1; argi < argc; ++argi) { + if (argv[argi] != NULL) { + if (!strcmp("--gui", argv[argi])) { + args->unlock_action = kUnlockGUI; + } else if (!strcmp("--force", argv[argi])) { + args->unlock_action = kUnlockForce; + } else if (!strcmp("--help", argv[argi])) { + PrintHelp(); + args->unlock_action = kUnlockHelpOnly; + return (kSuccess); + } else { + if (pass == kArgParseSwitches) { + ++args->num_filenames; + if (args->num_filenames > 32) { + return (kUserTooManyFiles); + } + num_filename_char += strlen(argv[argi]) + 1; + } else if (pass == kArgParseFilenames) { + args->p_filenames[args->num_filenames++] = filename_chars; + strcpy(filename_chars, argv[argi]); + filename_chars += strlen(argv[argi]) + 1; + } + } + } + } + } + if (args->num_filenames == 0) { + return (kUserNoFiles); + } + return (kSuccess); +} + /* Returns the count, -GetLastError () or -ENOMEM */ ssize_t EnumerateProcessModules(DWORD processId, HMODULE** pp_modules) { - if (pp_modules == NULL) { - return 0; + if (pp_modules == NULL) { + return 0; + } + + HANDLE proc_handle = OpenProcess( + PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, processId); + if (proc_handle == NULL) { + return -(ssize_t)GetLastError(); + } + + ssize_t num_entries = 0; + HMODULE* modules = NULL; + size_t bytes_used = 0; + BOOL result = FALSE; + + do { + DWORD bytes_needed; + num_entries += 1024; + bytes_used = num_entries * sizeof(DWORD); + modules = (HMODULE*)alloca(bytes_used); + if (modules == NULL) { + CloseHandle(proc_handle); + return -ENOMEM; } - HANDLE proc_handle = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, processId); - if (proc_handle == NULL) { - return -(ssize_t)GetLastError (); + result = + EnumProcessModules(proc_handle, modules, bytes_used, &bytes_needed); + if (result != FALSE) { + num_entries = bytes_needed / sizeof(DWORD); + bytes_used = bytes_needed; } + } while (result == FALSE); - ssize_t num_entries = 0; - HMODULE* modules = NULL; - size_t bytes_used = 0; - BOOL result = FALSE; + *pp_modules = malloc(bytes_used); + if (*pp_modules == NULL) { + CloseHandle(proc_handle); + return -ENOMEM; + } + memcpy(*pp_modules, modules, bytes_used); + CloseHandle(proc_handle); - do { - DWORD bytes_needed; - num_entries += 1024; - bytes_used = num_entries * sizeof (DWORD); - modules = (HMODULE*)alloca (bytes_used); - if (modules == NULL) { - CloseHandle (proc_handle); - return -ENOMEM; - } - - result = EnumProcessModules (proc_handle, modules, bytes_used, &bytes_needed); - if (result != FALSE) { - num_entries = bytes_needed / sizeof (DWORD); - bytes_used = bytes_needed; - } - } while (result == FALSE); - - *pp_modules = malloc (bytes_used); - if (*pp_modules == NULL) { - CloseHandle (proc_handle); - return -ENOMEM; - } - memcpy (*pp_modules, modules, bytes_used); - CloseHandle (proc_handle); - - return num_entries; + return num_entries; } -uint32_t CheckForConflictingFiles(DWORD processId, char** filenames, size_t num_files) { - HMODULE* modules; - uint32_t result = 0; - ssize_t num_modules = EnumerateProcessModules (processId, &modules); - if (num_modules <= 0) { - return 0; +uint32_t CheckForConflictingFiles(DWORD processId, char** filenames, + size_t num_files) { + HMODULE* modules; + uint32_t result = 0; + ssize_t num_modules = EnumerateProcessModules(processId, &modules); + if (num_modules <= 0) { + return 0; + } + + HANDLE proc_handle = OpenProcess( + PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, processId); + if (proc_handle == NULL) { + return -(ssize_t)GetLastError(); + } + + size_t fid; + ssize_t mid; + char module_name[1024]; + for (mid = 0; mid < num_modules; ++mid) { + if (GetModuleFileNameExA(proc_handle, modules[mid], module_name, + sizeof(module_name) / sizeof(module_name[0]))) + printf("\t%s\n", module_name); + for (fid = 0; fid < num_files; ++fid) { + if (!strcmp(module_name, filenames[fid])) { + result |= (1 << fid); + } } + } - HANDLE proc_handle = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, processId); - if (proc_handle == NULL) { - return -(ssize_t)GetLastError (); - } + CloseHandle(proc_handle); - size_t fid; - ssize_t mid; - char module_name[1024]; - for (mid = 0; mid < num_modules; ++mid) { - if (GetModuleFileNameExA (proc_handle, modules[mid], module_name, - sizeof(module_name) / sizeof(module_name[0]))) - printf ("\t%s\n", module_name); - for (fid = 0; fid < num_files; ++fid) { - if (!strcmp(module_name, filenames[fid])) { - result |= (1<unlock_action = kUnlockNone; - args->num_filenames = 0; - args->p_filenames = NULL; - args->appHWnd = NULL; - int argi; - kArgParsePass pass; - size_t num_filename_char = 0; - char* filename_chars; - - args->appHWnd = FindConsoleHandle (); - - /* Process arguments */ - for (pass = kArgParseFirst; pass < kArgParseCount; ++pass) { - if (pass == kArgParseFilenames) { - args->p_filenames = (char**)malloc ((sizeof(char*) * args->num_filenames) + - (sizeof(char) * num_filename_char)); - filename_chars = (char*)&args->p_filenames[args->num_filenames]; - args->num_filenames = 0; - } - for (argi = 1; argi < argc; ++argi) { - if (argv[argi] != NULL) { - if (!strcmp ("--gui", argv[argi])) { - args->unlock_action = kUnlockGUI; - } else if (!strcmp ("--force", argv[argi])) { - args->unlock_action = kUnlockForce; - } else { - if (pass == kArgParseSwitches) { - ++args->num_filenames; - if (args->num_filenames > 32) { - return (kUserTooManyFiles); - } - num_filename_char += strlen (argv[argi]) + 1; - } - else if (pass == kArgParseFilenames) { - args->p_filenames[args->num_filenames++] = filename_chars; - strcpy (filename_chars, argv[argi]); - filename_chars += strlen (argv[argi]) + 1; - } - } - } +kExitCode UpdateState(Arguments* args, GlobalState* state) { + ssize_t i, num_processes = EnumerateProcesses(&state->p_processes); + if (num_processes < 0) { + state->num_processes = 0; + return (kFailEnumProc); + } + state->num_processes = (size_t)num_processes; + for (i = 0; i < num_processes; ++i) { + uint32_t conflicts = CheckForConflictingFiles( + state->p_processes[i], args->p_filenames, args->num_filenames); + if (conflicts) { + if (args->unlock_action == kUnlockGUI) { + INT_PTR result = + DialogBoxParamA(NULL, MAKEINTRESOURCEA(IDC_UNLOCKERDIALOG), + state->appHWnd, DialogProc, (LPARAM)state); + if (result == kUserExited) { + return (kUserExited); } + } } - if (args->num_filenames == 0) { - return (kUserNoFiles); - } - return (kSuccess); + } } int main(int argc, char* argv[]) { - Arguments args; - kExitCode args_result = ProcessArguments (argc, argv, &args); - if (args_result == kUserNoFiles) { - fprintf (stderr, "No filenames specified.\n"); - return (kUserNoFiles); - } else if (args_result == kUserTooManyFiles) { - fprintf(stderr, "Too many filenames specified, max is 32.\n"); - return (kUserTooManyFiles); + Arguments args; + GlobalState state; + + state.appHWnd = FindConsoleHandle(); + + kExitCode args_result = ProcessArguments(argc, argv, &args); + if (args_result == kUserNoFiles) { + fprintf(stderr, "No filenames specified.\n"); + return (kUserNoFiles); + } else if (args_result == kUserTooManyFiles) { + fprintf(stderr, "Too many filenames specified, max is 32.\n"); + return (kUserTooManyFiles); + } + + if (args.unlock_action == kUnlockHelpOnly) { + return (kSuccess); + } + + do { + kExitCode update_result = UpdateState(&args, &state); + if (update_result == kFailEnumProc) { + fprintf(stderr, "Failed to enumerate processes.\n"); + return (kFailEnumProc); } - do { - DWORD* p_processes = NULL; - ssize_t i, num_entries = EnumerateProcesses (&p_processes); - if (num_entries < 0) { - fprintf (stderr, "Failed to enumerate processes.\n"); - return (kFailEnumProc); - } - for (i = 0; i < num_entries; ++i) { - uint32_t conflicts = CheckForConflictingFiles (p_processes[i], args.p_filenames, args.num_filenames); - if (conflicts) { - if (args.unlock_action == kUnlockGUI) { - INT_PTR result = DialogBoxA(NULL, MAKEINTRESOURCEA(IDC_UNLOCKERDIALOG), args.appHWnd, DialogProc); - if (result == kUserExited) { - return (kUserExited); - } - } - } - } - } while (0); + } while (0); - return (kSuccess); + return (kSuccess); }