1 /*
2  * PROJECT:     Global Flags utility
3  * LICENSE:     GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
4  * PURPOSE:     Global Flags utility entrypoint
5  * COPYRIGHT:   Copyright 2017 Pierre Schweitzer (pierre@reactos.org)
6  *              Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
7  */
8 
9 #include "gflags.h"
10 
11 static BOOL UsePageHeap = FALSE;
12 static BOOL UseImageFile = FALSE;
13 
14 const WCHAR ImageExecOptionsString[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options";
15 
16 BOOL OpenImageFileExecOptions(IN REGSAM SamDesired, IN OPTIONAL PCWSTR ImageName, OUT HKEY* Key)
17 {
18     LONG Ret;
19     HKEY HandleKey, HandleSubKey;
20 
21     Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, ImageExecOptionsString, 0, SamDesired, &HandleKey);
22     if (Ret != ERROR_SUCCESS)
23     {
24         wprintf(L"OpenIFEO: RegOpenKeyEx failed (%d)\n", Ret);
25         return FALSE;
26     }
27 
28     if (ImageName == NULL)
29     {
30         *Key = HandleKey;
31         return TRUE;
32     }
33 
34     Ret = RegCreateKeyExW(HandleKey, ImageName, 0, NULL, REG_OPTION_NON_VOLATILE, SamDesired, NULL, &HandleSubKey, NULL);
35     CloseHandle(HandleKey);
36 
37     if (Ret != ERROR_SUCCESS)
38     {
39         wprintf(L"OpenIFEO: RegCreateKeyEx failed (%d)\n", Ret);
40         return FALSE;
41     }
42     *Key = HandleSubKey;
43     return TRUE;
44 }
45 
46 
47 DWORD ReadSZFlagsFromRegistry(HKEY SubKey, PWSTR Value)
48 {
49     WCHAR Buffer[20] = { 0 };
50     DWORD Len, Flags, Type;
51 
52     Len = sizeof(Buffer) - sizeof(WCHAR);
53     Flags = 0;
54     if (RegQueryValueExW(SubKey, Value, NULL, &Type, (BYTE*)Buffer, &Len) == ERROR_SUCCESS && Type == REG_SZ)
55     {
56         Flags = wcstoul(Buffer, NULL, 16);
57     }
58 
59     return Flags;
60 }
61 
62 static BOOL ParseCmdline(int argc, LPWSTR argv[])
63 {
64     INT i;
65 
66     if (argc < 2)
67     {
68         wprintf(L"Not enough args!\n");
69         return FALSE;
70     }
71 
72     for (i = 1; i < argc; i++)
73     {
74         if (argv[i][0] == L'/')
75         {
76             if (argv[i][1] == L'p' && argv[i][2] == UNICODE_NULL)
77             {
78                 UsePageHeap = TRUE;
79                 return PageHeap_ParseCmdline(i + 1, argc, argv);
80             }
81             if (argv[i][1] == L'i' && argv[i][2] == UNICODE_NULL)
82             {
83                 UseImageFile = TRUE;
84                 return ImageFile_ParseCmdline(i + 1, argc, argv);
85             }
86         }
87         else
88         {
89             wprintf(L"Invalid option: %s\n", argv[i]);
90             return FALSE;
91         }
92     }
93 
94     if (!UsePageHeap && !UseImageFile)
95     {
96         wprintf(L"Only page heap / image file flags are supported\n");
97         return FALSE;
98     }
99 
100     return TRUE;
101 }
102 
103 
104 int wmain(int argc, LPWSTR argv[])
105 {
106     if (!ParseCmdline(argc, argv))
107     {
108         wprintf(L"Usage: gflags [/p [image.exe] [/enable|/disable [/full]]]\n"
109                 L"              [/i <image.exe> [<Flags>]]\n"
110                 L"    image.exe:  Image you want to deal with\n"
111                 L"    /enable:    enable page heap for the image\n"
112                 L"    /disable:   disable page heap for the image\n"
113                 L"    /full:      activate full debug page heap\n"
114                 L"    <Flags>:    A 32 bit hex number (0x00000001) that specifies\n"
115                 L"                one or more global flags to set.\n"
116                 L"                Without any flags, the current settings are shown.\n"
117                 L"                Specify FFFFFFFF to delete the GlobalFlags entry.\n"
118                 L"                Additionally, instead of a single hex number,\n"
119                 L"                specify a list of abbreviations prefixed with\n"
120                 L"                a '+' to add, and '-' to remove a bit.\n"
121                 L"                Valid abbreviations:\n");
122         PrintFlags(~0, DEST_IMAGE);
123         return 1;
124     }
125 
126     if (UsePageHeap)
127     {
128         return PageHeap_Execute();
129     }
130     else if (UseImageFile)
131     {
132         return ImageFile_Execute();
133     }
134     return 2;
135 }
136