1 /*
2  * Unit test suite for fault reporting in XP and above
3  *
4  * Copyright 2010 Detlef Riekenberg
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  */
21 
22 #include <stdarg.h>
23 #include <stdio.h>
24 
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "winreg.h"
29 
30 #include "errorrep.h"
31 #include "wine/test.h"
32 
33 static const char regpath_root[] = "Software\\Microsoft\\PCHealth\\ErrorReporting";
34 static const char regpath_exclude[] = "ExclusionList";
35 
36 
37 static BOOL is_process_limited(void)
38 {
39     static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL) = NULL;
40     static BOOL (WINAPI *pOpenProcessToken)(HANDLE, DWORD, PHANDLE) = NULL;
41     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
42     PSID Group;
43     BOOL IsInGroup;
44     HANDLE token;
45 
46     if (!pOpenProcessToken)
47     {
48         HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
49         pOpenProcessToken = (void*)GetProcAddress(hadvapi32, "OpenProcessToken");
50         pCheckTokenMembership = (void*)GetProcAddress(hadvapi32, "CheckTokenMembership");
51         if (!pCheckTokenMembership || !pOpenProcessToken)
52         {
53             /* Win9x (power to the masses) or NT4 (no way to know) */
54             trace("missing pOpenProcessToken or CheckTokenMembership\n");
55             return FALSE;
56         }
57     }
58 
59     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
60                                   DOMAIN_ALIAS_RID_ADMINS,
61                                   0, 0, 0, 0, 0, 0, &Group) ||
62         !pCheckTokenMembership(NULL, Group, &IsInGroup))
63     {
64         trace("Could not check if the current user is an administrator\n");
65         return FALSE;
66     }
67     if (!IsInGroup)
68     {
69         if (!AllocateAndInitializeSid(&NtAuthority, 2,
70                                       SECURITY_BUILTIN_DOMAIN_RID,
71                                       DOMAIN_ALIAS_RID_POWER_USERS,
72                                       0, 0, 0, 0, 0, 0, &Group) ||
73             !pCheckTokenMembership(NULL, Group, &IsInGroup))
74         {
75             trace("Could not check if the current user is a power user\n");
76             return FALSE;
77         }
78         if (!IsInGroup)
79         {
80             /* Only administrators and power users can be powerful */
81             return TRUE;
82         }
83     }
84 
85     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
86     {
87         BOOL ret;
88         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
89         DWORD size;
90 
91         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
92         CloseHandle(token);
93         return (ret && type == TokenElevationTypeLimited);
94     }
95     return FALSE;
96 }
97 
98 
99 /* ###### */
100 
101 static void test_AddERExcludedApplicationA(void)
102 {
103     BOOL res;
104     LONG lres;
105     HKEY hroot;
106     HKEY hexclude = 0;
107 
108     /* clean state */
109     lres = RegCreateKeyA(HKEY_LOCAL_MACHINE, regpath_root, &hroot);
110     if (lres == ERROR_ACCESS_DENIED)
111     {
112         skip("Not enough access rights\n");
113         return;
114     }
115 
116     if (!lres)
117         lres = RegOpenKeyA(hroot, regpath_exclude, &hexclude);
118 
119     if (!lres)
120         RegDeleteValueA(hexclude, "winetest_faultrep.exe");
121 
122 
123     SetLastError(0xdeadbeef);
124     res = AddERExcludedApplicationA(NULL);
125     ok(!res, "got %d and 0x%x (expected FALSE)\n", res, GetLastError());
126 
127     SetLastError(0xdeadbeef);
128     res = AddERExcludedApplicationA("");
129     ok(!res, "got %d and 0x%x (expected FALSE)\n", res, GetLastError());
130 
131     SetLastError(0xdeadbeef);
132     /* existence of the path doesn't matter this function succeeded */
133     res = AddERExcludedApplicationA("winetest_faultrep.exe");
134     if (is_process_limited())
135     {
136         /* LastError is not set! */
137         ok(!res, "AddERExcludedApplicationA should have failed got %d\n", res);
138     }
139     else
140     {
141         ok(res, "AddERExcludedApplicationA failed (le=0x%x)\n", GetLastError());
142 
143         /* add, when already present */
144         SetLastError(0xdeadbeef);
145         res = AddERExcludedApplicationA("winetest_faultrep.exe");
146         ok(res, "AddERExcludedApplicationA failed (le=0x%x)\n", GetLastError());
147     }
148 
149     /* cleanup */
150     RegDeleteValueA(hexclude, "winetest_faultrep.exe");
151 
152     RegCloseKey(hexclude);
153     RegCloseKey(hroot);
154 }
155 
156 /* ########################### */
157 
158 START_TEST(faultrep)
159 {
160     test_AddERExcludedApplicationA();
161 }
162