/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS ping utility * FILE: applications/cmdutils/gflags/gflags.c * PURPOSE: Global Flags utility * PROGRAMMERS: Pierre Schweitzer */ #define WIN32_NO_STATUS #include #include #include #include #include #include #include static BOOL Set = FALSE; static BOOL Unset = FALSE; static BOOL Full = FALSE; static PWSTR Image = NULL; static WCHAR ImageExecOptionsString[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"; static DWORD ReagFlagsFromRegistry(HKEY SubKey, PVOID Buffer, PWSTR Value, DWORD MaxLen) { DWORD Len, Flags, Type; Len = MaxLen; Flags = 0; if (RegQueryValueEx(SubKey, Value, NULL, &Type, Buffer, &Len) == ERROR_SUCCESS && Type == REG_SZ) { Flags = wcstoul(Buffer, NULL, 16); } return Flags; } static VOID ModifyStatus(VOID) { LONG Ret; DWORD MaxLen, GlobalFlags; PVOID Buffer; HKEY HandleKey, HandleSubKey; Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_WRITE | KEY_READ, &HandleKey); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegOpenKeyEx failed (%d)\n", Ret); return; } Ret = RegCreateKeyEx(HandleKey, Image, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &HandleSubKey, NULL); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegCreateKeyEx failed (%d)\n", Ret); return; } Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegQueryInfoKey failed (%d)\n", Ret); RegCloseKey(HandleSubKey); RegCloseKey(HandleKey); return; } MaxLen = max(MaxLen, 11 * sizeof(WCHAR)); Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen); if (Buffer == NULL) { wprintf(L"MS: HeapAlloc failed\n"); RegCloseKey(HandleSubKey); RegCloseKey(HandleKey); return; } GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen); if (Set) { GlobalFlags |= 0x02000000; } else { GlobalFlags &= ~0x02000000; } if (GlobalFlags != 0) { wsprintf(Buffer, L"0x%08x", GlobalFlags); Ret = RegSetValueEx(HandleSubKey, L"GlobalFlag", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR)); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret); } } else { Ret = RegDeleteValue(HandleSubKey, L"GlobalFlag"); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret); } } if (Unset) { Ret = RegDeleteValue(HandleSubKey, L"PageHeapFlags"); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegDeleteValue failed (%d)\n", Ret); } } else { DWORD PageHeapFlags; PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen); PageHeapFlags &= ~3; if (Full) { PageHeapFlags |= 1; } PageHeapFlags |= 2; wsprintf(Buffer, L"0x%x", PageHeapFlags); Ret = RegSetValueEx(HandleSubKey, L"PageHeapFlags", 0, REG_SZ, Buffer, 11 * sizeof(WCHAR)); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret); } } if (Set) { DWORD Type, VerifierFlags, Len; VerifierFlags = 0; Len = MaxLen; if (RegQueryValueEx(HandleSubKey, L"VerifierFlags", NULL, &Type, Buffer, &Len) == ERROR_SUCCESS && Type == REG_DWORD && Len == sizeof(DWORD)) { VerifierFlags = ((DWORD *)Buffer)[0]; VerifierFlags &= ~0x8001; } if (Full) { VerifierFlags |= 1; } else { VerifierFlags |= 0x8000; } Ret = RegSetValueEx(HandleSubKey, L"VerifierFlags", 0, REG_DWORD, (const BYTE *)&VerifierFlags, sizeof(DWORD)); if (Ret != ERROR_SUCCESS) { wprintf(L"MS: RegSetValueEx failed (%d)\n", Ret); } } wprintf(L"path: %s\n", ImageExecOptionsString); wprintf(L"\t%s: page heap %s\n", Image, (Set ? L"enabled" : L"disabled")); HeapFree(GetProcessHeap(), 0, Buffer); RegCloseKey(HandleSubKey); RegCloseKey(HandleKey); } static BOOL DisplayImageInfo(HKEY HandleKey, PWSTR SubKey, PBOOL Header) { LONG Ret; BOOL Handled; DWORD MaxLen, GlobalFlags; HKEY HandleSubKey; PVOID Buffer; Ret = RegOpenKeyEx(HandleKey, SubKey, 0, KEY_READ, &HandleSubKey); if (Ret != ERROR_SUCCESS) { wprintf(L"DII: RegOpenKeyEx failed (%d)\n", Ret); return FALSE; } Ret = RegQueryInfoKey(HandleSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL); if (Ret != ERROR_SUCCESS) { wprintf(L"DII: RegQueryInfoKey failed (%d)\n", Ret); RegCloseKey(HandleSubKey); return FALSE; } Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen); if (Buffer == NULL) { wprintf(L"DII: HeapAlloc failed\n"); RegCloseKey(HandleSubKey); return FALSE; } Handled = FALSE; GlobalFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"GlobalFlag", MaxLen); if (GlobalFlags & 0x02000000) { DWORD PageHeapFlags; if (Image == NULL) { if (!*Header) { wprintf(L"path: %s\n", ImageExecOptionsString); *Header = TRUE; } wprintf(L"\t%s: page heap enabled with flags (", SubKey); } else { wprintf(L"Page heap is enabled for %s with flags (", SubKey); } PageHeapFlags = ReagFlagsFromRegistry(HandleSubKey, Buffer, L"PageHeapFlags", MaxLen); if (PageHeapFlags & 0x1) { wprintf(L"full "); } if (PageHeapFlags & 0x2) { wprintf(L"traces"); } wprintf(L")\n"); Handled = TRUE; } HeapFree(GetProcessHeap(), 0, Buffer); RegCloseKey(HandleSubKey); return Handled; } static VOID DisplayStatus(VOID) { LONG Ret; HKEY HandleKey; DWORD Index, MaxLen, Handled; TCHAR * SubKey; BOOL Header; Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, KEY_READ, &HandleKey); if (Ret != ERROR_SUCCESS) { wprintf(L"DS: RegOpenKeyEx failed (%d)\n", Ret); return; } Ret = RegQueryInfoKey(HandleKey, NULL, NULL, NULL, NULL, &MaxLen, NULL, NULL, NULL, NULL, NULL, NULL); if (Ret != ERROR_SUCCESS) { wprintf(L"DS: RegQueryInfoKey failed (%d)\n", Ret); RegCloseKey(HandleKey); return; } ++MaxLen; // NULL-char SubKey = HeapAlloc(GetProcessHeap(), 0, MaxLen * sizeof(TCHAR)); if (SubKey == NULL) { wprintf(L"DS: HeapAlloc failed\n"); RegCloseKey(HandleKey); return; } Index = 0; Handled = 0; Header = FALSE; do { Ret = RegEnumKey(HandleKey, Index, SubKey, MaxLen); if (Ret != ERROR_NO_MORE_ITEMS) { if (Image == NULL || wcscmp(SubKey, Image) == 0) { if (DisplayImageInfo(HandleKey, SubKey, &Header)) { ++Handled; } } ++Index; } } while (Ret != ERROR_NO_MORE_ITEMS); if (Handled == 0) { if (Image == NULL) { wprintf(L"No application has page heap enabled.\n"); } else { wprintf(L"Page heap is not enabled for %s\n", Image); } } HeapFree(GetProcessHeap(), 0, SubKey); RegCloseKey(HandleKey); } static VOID Usage(VOID) { wprintf(L"Usage: gflags /p [image.exe] [/enable|/disable [/full]]\n" L"\timage.exe:\tImage you want to deal with\n" L"\t/enable:\tenable page heap for the image\n" L"\t/disable:\tdisable page heap for the image\n" L"\t/full:\t\tactivate full debug page heap\n"); } static BOOL ParseCmdline(int argc, LPWSTR argv[]) { INT i; BOOL UsePageHeap = FALSE; if (argc < 2) { wprintf(L"Not enough args!\n", argc); Usage(); return FALSE; } for (i = 1; i < argc; i++) { if (argv[i][0] == L'/') { if (argv[i][1] == L'p' && argv[i][2] == UNICODE_NULL) { UsePageHeap = TRUE; } else if (argv[i][1] == L'p' && argv[i][2] != UNICODE_NULL) { wprintf(L"Invalid option: %s\n", argv[i]); Usage(); return FALSE; } else { if (wcscmp(argv[i], L"/enable") == 0) { Set = TRUE; } else if (wcscmp(argv[i], L"/disable") == 0) { Unset = TRUE; } else if (wcscmp(argv[i], L"/full") == 0) { Full = TRUE; } } } else if (Image == NULL) { Image = argv[i]; } else { wprintf(L"Invalid option: %s\n", argv[i]); Usage(); return FALSE; } } if (!UsePageHeap) { wprintf(L"Only page heap flags are supported\n"); Usage(); return FALSE; } if (Set && Unset) { wprintf(L"ENABLE and DISABLED cannot be set together\n"); Usage(); return FALSE; } if (Image == NULL && (Set || Unset || Full)) { wprintf(L"Can't ENABLE or DISABLE with no image\n"); Usage(); return FALSE; } if (!Set && !Unset && Full) { wprintf(L"Cannot deal with full traces with no other indication\n"); Usage(); return FALSE; } return TRUE; } int wmain(int argc, LPWSTR argv[]) { if (!ParseCmdline(argc, argv)) { return 1; } if (!Set && !Unset) { DisplayStatus(); } else { ModifyStatus(); } return 0; }