1 /* 2 * PROJECT: Global Flags utility 3 * LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0) 4 * PURPOSE: Global Flags utility image file options 5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include "gflags.h" 9 10 static PWSTR ImageFile = NULL; 11 static DWORD OptionsAdd = 0; 12 static DWORD OptionsRemove = 0; 13 static BOOL OptionsSet = FALSE; 14 15 typedef struct FlagInfo 16 { 17 DWORD dwFlag; 18 const wchar_t* szAbbr; 19 WORD wDest; 20 const wchar_t* szDesc; 21 } FlagInfo; 22 23 #define FLG_DISABLE_DBGPRINT 0x8000000 24 #define FLG_CRITSEC_EVENT_CREATION 0x10000000 25 #define FLG_STOP_ON_UNHANDLED_EXCEPTION 0x20000000 26 #define FLG_ENABLE_HANDLE_EXCEPTIONS 0x40000000 27 #define FLG_DISABLE_PROTDLLS 0x80000000 28 29 30 static const FlagInfo g_Flags[] = 31 { 32 {FLG_STOP_ON_EXCEPTION, L"soe", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Stop on exception"}, 33 {FLG_SHOW_LDR_SNAPS, L"sls", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Show loader snaps"}, 34 {FLG_DEBUG_INITIAL_COMMAND, L"dic", (DEST_REGISTRY), L"Debug initial command"}, 35 {FLG_STOP_ON_HUNG_GUI, L"shg", (DEST_KERNEL), L"Stop on hung GUI"}, 36 {FLG_HEAP_ENABLE_TAIL_CHECK, L"htc", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable heap tail checking"}, 37 {FLG_HEAP_ENABLE_FREE_CHECK, L"hfc", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable heap free checking"}, 38 {FLG_HEAP_VALIDATE_PARAMETERS, L"hpc", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable heap parameter checking"}, 39 {FLG_HEAP_VALIDATE_ALL, L"hvc", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable heap validation on call"}, 40 {FLG_APPLICATION_VERIFIER, L"vrf", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable application verifier"}, 41 // FLG_MONITOR_SILENT_PROCESS_EXIT 42 {FLG_POOL_ENABLE_TAGGING, L"ptg", (DEST_REGISTRY), L"Enable pool tagging"}, 43 {FLG_HEAP_ENABLE_TAGGING, L"htg", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable heap tagging"}, 44 {FLG_USER_STACK_TRACE_DB, L"ust", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Create user mode stack trace database"}, 45 {FLG_KERNEL_STACK_TRACE_DB, L"kst", (DEST_REGISTRY), L"Create kernel mode stack trace database"}, 46 {FLG_MAINTAIN_OBJECT_TYPELIST, L"otl", (DEST_REGISTRY), L"Maintain a list of objects for each type"}, 47 {FLG_HEAP_ENABLE_TAG_BY_DLL, L"htd", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable heap tagging by DLL"}, 48 {FLG_DISABLE_STACK_EXTENSION, L"dse", (DEST_IMAGE), L"Disable stack extension"}, 49 50 {FLG_ENABLE_CSRDEBUG, L"d32", (DEST_REGISTRY), L"Enable debugging of Win32 subsystem"}, 51 {FLG_ENABLE_KDEBUG_SYMBOL_LOAD, L"ksl", (DEST_REGISTRY | DEST_KERNEL), L"Enable loading of kernel debugger symbols"}, 52 {FLG_DISABLE_PAGE_KERNEL_STACKS, L"dps", (DEST_REGISTRY), L"Disable paging of kernel stacks"}, 53 {FLG_ENABLE_SYSTEM_CRIT_BREAKS, L"scb", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable system critical breaks"}, 54 {FLG_HEAP_DISABLE_COALESCING, L"dhc", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Disable heap coalesce on free"}, 55 {FLG_ENABLE_CLOSE_EXCEPTIONS, L"ece", (DEST_REGISTRY | DEST_KERNEL), L"Enable close exception"}, 56 {FLG_ENABLE_EXCEPTION_LOGGING, L"eel", (DEST_REGISTRY | DEST_KERNEL), L"Enable exception logging"}, 57 {FLG_ENABLE_HANDLE_TYPE_TAGGING, L"eot", (DEST_REGISTRY | DEST_KERNEL), L"Enable object handle type tagging"}, 58 {FLG_HEAP_PAGE_ALLOCS, L"hpa", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Enable page heap"}, 59 {FLG_DEBUG_INITIAL_COMMAND_EX, L"dwl", (DEST_REGISTRY), L"Debug WinLogon"}, 60 {FLG_DISABLE_DBGPRINT, L"ddp", (DEST_REGISTRY | DEST_KERNEL), L"Buffer DbgPrint Output"}, 61 {FLG_CRITSEC_EVENT_CREATION, L"cse", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Early critical section event creation"}, 62 {FLG_STOP_ON_UNHANDLED_EXCEPTION, L"sue", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Stop on unhandled user-mode exception"}, 63 {FLG_ENABLE_HANDLE_EXCEPTIONS, L"bhd", (DEST_REGISTRY | DEST_KERNEL), L"Enable bad handles detection"}, 64 {FLG_DISABLE_PROTDLLS, L"dpd", (DEST_REGISTRY | DEST_KERNEL | DEST_IMAGE), L"Disable protected DLL verification"}, 65 }; 66 67 void PrintFlags(IN DWORD GlobalFlags, IN OPTIONAL WORD Dest) 68 { 69 DWORD n; 70 71 for (n = 0; n < ARRAYSIZE(g_Flags); ++n) 72 { 73 if (!Dest || (g_Flags[n].wDest & Dest)) 74 { 75 if (g_Flags[n].dwFlag & GlobalFlags) 76 { 77 wprintf(L" %s - %s\n", g_Flags[n].szAbbr, g_Flags[n].szDesc); 78 } 79 } 80 } 81 } 82 83 static void ShowStatus(DWORD GlobalFlags, DWORD Ignored) 84 { 85 if (GlobalFlags) 86 { 87 wprintf(L"Current Registry Settings for %s executable are: %08x\n", ImageFile, GlobalFlags); 88 PrintFlags(GlobalFlags, 0); 89 } 90 else 91 { 92 wprintf(L"No Registry Settings for %s executable\n", ImageFile); 93 } 94 if (Ignored) 95 { 96 wprintf(L"The following settings were ignored: %08x\n", Ignored); 97 PrintFlags(Ignored, 0); 98 } 99 } 100 101 static DWORD ValidateFlags(DWORD GlobalFlags, WORD Dest) 102 { 103 DWORD n; 104 DWORD Valid = 0; 105 106 for (n = 0; n < ARRAYSIZE(g_Flags); ++n) 107 { 108 if (g_Flags[n].wDest & Dest) 109 { 110 Valid |= g_Flags[n].dwFlag; 111 } 112 } 113 114 return GlobalFlags & Valid; 115 } 116 117 static DWORD FindFlag(PCWSTR Name, WORD Dest) 118 { 119 DWORD n; 120 121 for (n = 0; n < ARRAYSIZE(g_Flags); ++n) 122 { 123 if (g_Flags[n].wDest & Dest) 124 { 125 if (!wcsicmp(Name, g_Flags[n].szAbbr)) 126 { 127 return g_Flags[n].dwFlag; 128 } 129 } 130 } 131 132 return 0; 133 } 134 135 static VOID ModifyStatus(VOID) 136 { 137 LONG Ret; 138 DWORD GlobalFlags, Requested, Ignored; 139 HKEY IFEOKey; 140 WCHAR Buffer[11]; 141 142 if (!OpenImageFileExecOptions(KEY_WRITE | KEY_READ, ImageFile, &IFEOKey)) 143 { 144 return; 145 } 146 147 if (OptionsSet) 148 { 149 Requested = OptionsAdd; 150 } 151 else 152 { 153 Requested = ReadSZFlagsFromRegistry(IFEOKey, L"GlobalFlag"); 154 Requested &= ~OptionsRemove; 155 Requested |= OptionsAdd; 156 } 157 158 GlobalFlags = ValidateFlags(Requested, DEST_IMAGE); 159 Ignored = GlobalFlags ^ Requested; 160 161 if (GlobalFlags) 162 { 163 wsprintf(Buffer, L"0x%08x", GlobalFlags); 164 Ret = RegSetValueExW(IFEOKey, L"GlobalFlag", 0, REG_SZ, (BYTE*)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR)); 165 if (Ret != ERROR_SUCCESS) 166 { 167 wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret); 168 } 169 else 170 { 171 ShowStatus(GlobalFlags, Ignored); 172 } 173 } 174 else 175 { 176 Ret = RegDeleteValueW(IFEOKey, L"GlobalFlag"); 177 if (Ret != ERROR_SUCCESS) 178 { 179 wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret); 180 } 181 else 182 { 183 ShowStatus(GlobalFlags, Ignored); 184 } 185 } 186 CloseHandle(IFEOKey); 187 } 188 189 190 static VOID DisplayStatus(VOID) 191 { 192 HKEY IFEOKey; 193 DWORD GlobalFlags; 194 195 if (!OpenImageFileExecOptions(KEY_READ, ImageFile, &IFEOKey)) 196 { 197 return; 198 } 199 200 GlobalFlags = ReadSZFlagsFromRegistry(IFEOKey, L"GlobalFlag"); 201 ShowStatus(GlobalFlags, 0); 202 203 CloseHandle(IFEOKey); 204 } 205 206 207 BOOL ImageFile_ParseCmdline(INT i, int argc, LPWSTR argv[]) 208 { 209 for (; i < argc; i++) 210 { 211 if (ImageFile == NULL) 212 { 213 ImageFile = argv[i]; 214 } 215 else if (argv[i][0] == '+') 216 { 217 if (OptionsSet) 218 { 219 wprintf(L"Unexpected argument - '%s'\n", argv[i]); 220 return FALSE; 221 } 222 OptionsAdd |= FindFlag(argv[i] + 1, DEST_IMAGE); 223 } 224 else if (argv[i][0] == '-') 225 { 226 if (OptionsSet) 227 { 228 wprintf(L"Unexpected argument - '%s'\n", argv[i]); 229 return FALSE; 230 } 231 OptionsRemove |= FindFlag(argv[i] + 1, DEST_IMAGE); 232 } 233 else 234 { 235 OptionsSet = TRUE; 236 OptionsAdd = wcstoul(argv[i], NULL, 16); 237 if (OptionsAdd == ~0) 238 OptionsAdd = 0; 239 } 240 } 241 242 if (ImageFile == NULL) 243 { 244 wprintf(L"No Image specified\n"); 245 return FALSE; 246 } 247 248 return TRUE; 249 } 250 251 INT ImageFile_Execute() 252 { 253 if (!OptionsAdd && !OptionsRemove && !OptionsSet) 254 { 255 DisplayStatus(); 256 } 257 else 258 { 259 ModifyStatus(); 260 } 261 262 return 0; 263 } 264