1 /*
2  * PROJECT:         ReactOS API tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test for GetUserObjectInformation
5  * PROGRAMMERS:     Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <apitest.h>
9 #include <wingdi.h>
10 #include <winuser.h>
11 #include <ndk/mmfuncs.h>
12 #include <ndk/pstypes.h>
13 #include <strsafe.h>
14 
15 static
16 BOOLEAN
17 CheckBuffer(
18     PVOID Buffer,
19     SIZE_T Size,
20     UCHAR Value)
21 {
22     PUCHAR Array = Buffer;
23     SIZE_T i;
24 
25     for (i = 0; i < Size; i++)
26         if (Array[i] != Value)
27         {
28             trace("Expected %x, found %x at offset %lu\n", Value, Array[i], (ULONG)i);
29             return FALSE;
30         }
31     return TRUE;
32 }
33 
34 static
35 PVOID
36 AllocateGuarded(
37     SIZE_T SizeRequested)
38 {
39     NTSTATUS Status;
40     SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
41     PVOID VirtualMemory = NULL;
42     PCHAR StartOfBuffer;
43 
44     Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
45 
46     if (!NT_SUCCESS(Status))
47         return NULL;
48 
49     Size -= PAGE_SIZE;
50     if (Size)
51     {
52         Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
53         if (!NT_SUCCESS(Status))
54         {
55             Size = 0;
56             Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
57             ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
58             return NULL;
59         }
60     }
61 
62     StartOfBuffer = VirtualMemory;
63     StartOfBuffer += Size - SizeRequested;
64 
65     return StartOfBuffer;
66 }
67 
68 static
69 VOID
70 FreeGuarded(
71     PVOID Pointer)
72 {
73     NTSTATUS Status;
74     PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
75     SIZE_T Size = 0;
76 
77     Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
78     ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
79 }
80 
81 #define xok ok // Make the test succeed on Win2003
82 //#define xok(...) // This should make the test succeed on all Windows versions
83 #define NOTSET 1234
84 
85 #define TestUserObjectInfo(Handle, Index, Buffer, Length, Ret, Error, LengthNeeded) do  \
86     {                                                                                   \
87         DWORD _LengthNeeded = NOTSET;                                                   \
88         DECLSPEC_ALIGN(16) CHAR _LengthBuffer[2 * sizeof(DWORD)];                       \
89         DWORD _Error;                                                                   \
90         BOOL _Ret;                                                                      \
91                                                                                         \
92         SetLastError(0xdeadbeef);                                                       \
93         _Ret = GetUserObjectInformationW(Handle, Index, Buffer, Length, NULL);          \
94         _Error = GetLastError();                                                        \
95         ok(_Ret == (Ret), "Ret = %d\n", _Ret);                                          \
96         xok(_Error == (Error), "Error = %lu\n", _Error);                                \
97                                                                                         \
98         SetLastError(0xdeadbeef);                                                       \
99         _Ret = GetUserObjectInformationW(Handle, Index, Buffer, Length, &_LengthNeeded);\
100         _Error = GetLastError();                                                        \
101         ok(_Ret == (Ret), "Ret = %d\n", _Ret);                                          \
102         xok(_Error == (Error), "Error = %lu\n", _Error);                                \
103         xok(_LengthNeeded == (LengthNeeded), "LengthNeeded = %lu\n", _LengthNeeded);    \
104                                                                                         \
105         SetLastError(0xdeadbeef);                                                       \
106         *(PDWORD)&_LengthBuffer[1] = NOTSET;                                            \
107         _Ret = GetUserObjectInformationW(Handle, Index, Buffer, Length,                 \
108                                          (PDWORD)&_LengthBuffer[1]);                    \
109         _Error = GetLastError();                                                        \
110         ok(_Ret == (Ret), "Ret = %d\n", _Ret);                                          \
111         xok(_Error == (Error), "Error = %lu\n", _Error);                                \
112         _LengthNeeded = *(PDWORD)&_LengthBuffer[1];                                     \
113         xok(_LengthNeeded == (LengthNeeded), "LengthNeeded = %lu\n", _LengthNeeded);    \
114                                                                                         \
115         SetLastError(0xdeadbeef);                                                       \
116         _Ret = GetUserObjectInformationW(Handle, Index, Buffer, Length, (PVOID)-4);     \
117         _Error = GetLastError();                                                        \
118         ok(_Ret == FALSE, "Ret = %d\n", _Ret);                                          \
119         ok(_Error == ERROR_NOACCESS, "Error = %lu\n", _Error);                          \
120     } while (0)
121 
122 #define TestUserObjectInfoWithString(Handle, Index, Buffer, BufferSize, String) do                                                          \
123     {                                                                                                                                       \
124         BOOLEAN _Check;                                                                                                                     \
125         ULONG SizeOfString = wcslen(String) * sizeof(WCHAR) + sizeof(UNICODE_NULL);                                                         \
126         TestUserObjectInfo(Handle,  Index,     NULL,             0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, SizeOfString);  \
127         TestUserObjectInfo(Handle,  Index,     (PVOID)1,         0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, SizeOfString);  \
128         TestUserObjectInfo(Handle,  Index,     NULL,             1,                       FALSE, ERROR_NOACCESS,            NOTSET);        \
129         TestUserObjectInfo(Handle,  Index,     (PVOID)1,         1,                       FALSE, ERROR_NOACCESS,            NOTSET);        \
130         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                            \
131         TestUserObjectInfo(Handle,  Index,     Buffer,           SizeOfString - 2,        FALSE, ERROR_INSUFFICIENT_BUFFER, SizeOfString);  \
132         _Check = CheckBuffer(Buffer, BufferSize, 0x55);                                                                                     \
133         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                         \
134         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                            \
135         TestUserObjectInfo(Handle,  Index,     Buffer,           SizeOfString - 1,        FALSE, ERROR_INSUFFICIENT_BUFFER, SizeOfString);  \
136         _Check = CheckBuffer(Buffer, BufferSize, 0x55);                                                                                     \
137         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                         \
138         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                            \
139         Buffer[BufferSize / sizeof(WCHAR) - 1] = UNICODE_NULL;                                                                              \
140         TestUserObjectInfo(Handle,  Index,     Buffer,           SizeOfString,            TRUE,  0xdeadbeef,                SizeOfString);  \
141         ok(wcscmp(Buffer, String) == 0, "Buffer '%ls', expected '%ls'\n", Buffer, String);                                                  \
142         _Check = CheckBuffer(Buffer + SizeOfString / sizeof(Buffer[0]), BufferSize - SizeOfString - sizeof(WCHAR), 0x55);                   \
143         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                         \
144         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                            \
145         Buffer[BufferSize / sizeof(WCHAR) - 1] = UNICODE_NULL;                                                                              \
146         TestUserObjectInfo(Handle,  Index,     Buffer,           BufferSize,              TRUE,  0xdeadbeef,                SizeOfString);  \
147         ok(wcscmp(Buffer, String) == 0, "Buffer '%ls', expected '%ls'\n", Buffer, String);                                                  \
148         _Check = CheckBuffer(Buffer + SizeOfString / sizeof(Buffer[0]), BufferSize - SizeOfString - sizeof(WCHAR), 0x55);                   \
149         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                         \
150     } while (0)
151 
152 static
153 void
154 TestGetUserObjectInfoW(void)
155 {
156     USEROBJECTFLAGS UserObjectFlags;
157     PWCHAR Buffer;
158     ULONG BufferSize = 64 * sizeof(WCHAR);
159     HDESK Desktop;
160     HDESK Desktop2;
161     HWINSTA WinSta;
162     HANDLE Token;
163     TOKEN_STATISTICS Statistics;
164     WCHAR WinStaName[64];
165     BOOL Success;
166     ULONG Length;
167 
168     Buffer = AllocateGuarded(BufferSize);
169 
170     TestUserObjectInfo(NULL,    5,         NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
171     TestUserObjectInfo(NULL,    UOI_FLAGS, NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
172     TestUserObjectInfo(NULL,    UOI_FLAGS, (PVOID)1,         0,                       FALSE, ERROR_INVALID_HANDLE,      0);
173     TestUserObjectInfo(NULL,    UOI_FLAGS, NULL,             1,                       FALSE, ERROR_NOACCESS,            NOTSET);
174     TestUserObjectInfo(NULL,    UOI_FLAGS, (PVOID)1,         1,                       FALSE, ERROR_NOACCESS,            NOTSET);
175     TestUserObjectInfo(NULL,    UOI_FLAGS, &UserObjectFlags, sizeof(UserObjectFlags), FALSE, ERROR_INVALID_HANDLE,      0);
176 
177     TestUserObjectInfo(NULL,    UOI_TYPE,  NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
178     TestUserObjectInfo(NULL,    UOI_TYPE,  (PVOID)1,         0,                       FALSE, ERROR_INVALID_HANDLE,      0);
179     TestUserObjectInfo(NULL,    UOI_TYPE,  NULL,             1,                       FALSE, ERROR_NOACCESS,            NOTSET);
180     TestUserObjectInfo(NULL,    UOI_TYPE,  (PVOID)1,         1,                       FALSE, ERROR_NOACCESS,            NOTSET);
181     TestUserObjectInfo(NULL,    UOI_TYPE,  Buffer,           BufferSize,              FALSE, ERROR_INVALID_HANDLE,      0);
182 
183     TestUserObjectInfo(NULL,    UOI_NAME,  NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
184     TestUserObjectInfo(NULL,    UOI_NAME,  (PVOID)1,         0,                       FALSE, ERROR_INVALID_HANDLE,      0);
185     TestUserObjectInfo(NULL,    UOI_NAME,  NULL,             1,                       FALSE, ERROR_NOACCESS,            NOTSET);
186     TestUserObjectInfo(NULL,    UOI_NAME,  (PVOID)1,         1,                       FALSE, ERROR_NOACCESS,            NOTSET);
187     TestUserObjectInfo(NULL,    UOI_NAME,  Buffer,           BufferSize,              FALSE, ERROR_INVALID_HANDLE,      0);
188 
189     Desktop = GetThreadDesktop(GetCurrentThreadId());
190     if (!Desktop)
191     {
192         skip("Failed to get desktop handle\n");
193         FreeGuarded(Buffer);
194         return;
195     }
196 
197     WinSta = GetProcessWindowStation();
198     if (!WinSta)
199     {
200         skip("Failed to get winsta handle\n");
201         FreeGuarded(Buffer);
202         return;
203     }
204 
205     TestUserObjectInfo(Desktop, 5,         NULL,             0,                       FALSE, ERROR_INVALID_PARAMETER,   0);
206     TestUserObjectInfo(Desktop, UOI_FLAGS, NULL,             0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(USEROBJECTFLAGS));
207     TestUserObjectInfo(Desktop, UOI_FLAGS, (PVOID)1,         0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(USEROBJECTFLAGS));
208     TestUserObjectInfo(Desktop, UOI_FLAGS, NULL,             1,                       FALSE, ERROR_NOACCESS,            NOTSET);
209     TestUserObjectInfo(Desktop, UOI_FLAGS, (PVOID)1,         1,                       FALSE, ERROR_NOACCESS,            NOTSET);
210     TestUserObjectInfo(Desktop, UOI_FLAGS, &UserObjectFlags, sizeof(UserObjectFlags), TRUE,  0xdeadbeef,                sizeof(USEROBJECTFLAGS));
211 
212     TestUserObjectInfoWithString(Desktop, UOI_TYPE, Buffer, BufferSize, L"Desktop");
213     TestUserObjectInfoWithString(Desktop, UOI_NAME, Buffer, BufferSize, L"Default");
214 
215     TestUserObjectInfoWithString(WinSta, UOI_TYPE, Buffer, BufferSize, L"WindowStation");
216     TestUserObjectInfoWithString(WinSta, UOI_NAME, Buffer, BufferSize, L"WinSta0");
217 
218     /* Autogenerated name will be Service-0x<luidhigh>-<luidlow>$ */
219     StringCbCopyW(WinStaName, sizeof(WinStaName), L"<failed>");
220     Success = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
221     ok(Success == TRUE, "OpenProcessToken failed with %lu\n", GetLastError());
222     if (Success)
223     {
224         Success = GetTokenInformation(Token,
225                                       TokenStatistics,
226                                       &Statistics,
227                                       sizeof(Statistics),
228                                       &Length);
229         ok(Success == TRUE, "GetTokenInformation failed with %lu\n", GetLastError());
230         if (Success)
231         {
232             StringCbPrintfW(WinStaName,
233                             sizeof(WinStaName),
234                             L"Service-0x%lx-%lx$",
235                             Statistics.AuthenticationId.HighPart,
236                             Statistics.AuthenticationId.LowPart);
237             trace("Expected autogenerated Winsta name: %ls\n", WinStaName);
238         }
239         CloseHandle(Token);
240     }
241 
242     /* Create our own Winsta */
243     WinSta = CreateWindowStationW(NULL, 0, WINSTA_READATTRIBUTES, NULL);
244     ok(WinSta != NULL, "CreateWindowStationW failed with %lu\n", GetLastError());
245     if (WinSta)
246     {
247         TestUserObjectInfoWithString(WinSta, UOI_TYPE, Buffer, BufferSize, L"WindowStation");
248         TestUserObjectInfoWithString(WinSta, UOI_NAME, Buffer, BufferSize, WinStaName);
249         CloseWindowStation(WinSta);
250     }
251     else
252     {
253         skip("Failed to create winsta\n");
254     }
255 
256     WinSta = CreateWindowStationW(L"", 0, WINSTA_READATTRIBUTES, NULL);
257     ok(WinSta != NULL, "CreateWindowStationW failed with %lu\n", GetLastError());
258     if (WinSta)
259     {
260         TestUserObjectInfoWithString(WinSta, UOI_TYPE, Buffer, BufferSize, L"WindowStation");
261         TestUserObjectInfoWithString(WinSta, UOI_NAME, Buffer, BufferSize, WinStaName);
262         CloseWindowStation(WinSta);
263     }
264     else
265     {
266         skip("Failed to create winsta\n");
267     }
268 
269     WinSta = CreateWindowStationW(L"GetUserObjectInformation_apitest_winsta", 0, WINSTA_READATTRIBUTES, NULL);
270     ok(WinSta != NULL, "CreateWindowStationW failed with %lu\n", GetLastError());
271     if (WinSta)
272     {
273         TestUserObjectInfoWithString(WinSta, UOI_TYPE, Buffer, BufferSize, L"WindowStation");
274         TestUserObjectInfoWithString(WinSta, UOI_NAME, Buffer, BufferSize, L"GetUserObjectInformation_apitest_winsta");
275         CloseWindowStation(WinSta);
276     }
277     else
278     {
279         skip("Failed to create winsta\n");
280     }
281 
282     WinSta = CreateWindowStationW(L"1", 0, WINSTA_READATTRIBUTES, NULL);
283     ok(WinSta != NULL, "CreateWindowStationW failed with %lu\n", GetLastError());
284     if (WinSta)
285     {
286         TestUserObjectInfoWithString(WinSta, UOI_TYPE, Buffer, BufferSize, L"WindowStation");
287         TestUserObjectInfoWithString(WinSta, UOI_NAME, Buffer, BufferSize, L"1");
288         CloseWindowStation(WinSta);
289     }
290     else
291     {
292         skip("Failed to create winsta\n");
293     }
294 
295     /* Create our own desktop */
296     Desktop2 = CreateDesktopW(NULL, NULL, NULL, 0, DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS, NULL);
297     ok(Desktop2 == NULL, "CreateDesktopW succeeded\n");
298     if (Desktop2) CloseDesktop(Desktop2);
299 
300     Desktop2 = CreateDesktopW(L"", NULL, NULL, 0, DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS, NULL);
301     ok(Desktop2 == NULL, "CreateDesktopW succeeded\n");
302     if (Desktop2) CloseDesktop(Desktop2);
303 
304     Desktop2 = CreateDesktopW(L"2", NULL, NULL, 0, DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS, NULL);
305     ok(Desktop2 != NULL, "CreateDesktopW failed with %lu\n", GetLastError());
306     if (Desktop2)
307     {
308         TestUserObjectInfoWithString(Desktop2, UOI_TYPE, Buffer, BufferSize, L"Desktop");
309         TestUserObjectInfoWithString(Desktop2, UOI_NAME, Buffer, BufferSize, L"2");
310     }
311     else
312     {
313         skip("Failed to create winsta\n");
314     }
315 
316     CloseDesktop(Desktop2);
317 
318     FreeGuarded(Buffer);
319 
320     /* Make sure nothing behind the needed buffer is touched */
321     BufferSize = sizeof(L"Desktop");
322     Buffer = AllocateGuarded(BufferSize);
323     TestUserObjectInfo(Desktop, UOI_TYPE,  Buffer,           BufferSize,              TRUE,  0xdeadbeef,                sizeof(L"Desktop"));
324     TestUserObjectInfo(Desktop, UOI_TYPE,  Buffer,           BufferSize + 1,          FALSE, ERROR_NOACCESS,            NOTSET);
325     FreeGuarded(Buffer);
326 }
327 
328 #undef TestUserObjectInfo
329 #define TestUserObjectInfo(Handle, Index, Buffer, Length, Ret, Error, LengthNeeded) do  \
330     {                                                                                   \
331         DWORD _LengthNeeded = NOTSET;                                                   \
332         DECLSPEC_ALIGN(16) CHAR _LengthBuffer[2 * sizeof(DWORD)];                       \
333         DWORD _Error;                                                                   \
334         BOOL _Ret;                                                                      \
335                                                                                         \
336         SetLastError(0xdeadbeef);                                                       \
337         _Ret = GetUserObjectInformationA(Handle, Index, Buffer, Length, NULL);          \
338         _Error = GetLastError();                                                        \
339         ok(_Ret == (Ret), "Ret = %d\n", _Ret);                                          \
340         xok(_Error == (Error), "Error = %lu\n", _Error);                                \
341                                                                                         \
342         SetLastError(0xdeadbeef);                                                       \
343         _Ret = GetUserObjectInformationA(Handle, Index, Buffer, Length, &_LengthNeeded);\
344         _Error = GetLastError();                                                        \
345         ok(_Ret == (Ret), "Ret = %d\n", _Ret);                                          \
346         xok(_Error == (Error), "Error = %lu\n", _Error);                                \
347         xok(_LengthNeeded == (LengthNeeded), "LengthNeeded = %lu\n", _LengthNeeded);    \
348                                                                                         \
349         SetLastError(0xdeadbeef);                                                       \
350         *(PDWORD)&_LengthBuffer[1] = NOTSET;                                            \
351         _Ret = GetUserObjectInformationA(Handle, Index, Buffer, Length,                 \
352                                          (PDWORD)&_LengthBuffer[1]);                    \
353         _Error = GetLastError();                                                        \
354         ok(_Ret == (Ret), "Ret = %d\n", _Ret);                                          \
355         xok(_Error == (Error), "Error = %lu\n", _Error);                                \
356         _LengthNeeded = *(PDWORD)&_LengthBuffer[1];                                     \
357         xok(_LengthNeeded == (LengthNeeded), "LengthNeeded = %lu\n", _LengthNeeded);    \
358                                                                                         \
359         SetLastError(0xdeadbeef);                                                       \
360         _Ret = GetUserObjectInformationA(Handle, Index, Buffer, Length, (PVOID)-4);     \
361         _Error = GetLastError();                                                        \
362         ok(_Ret == FALSE, "Ret = %d\n", _Ret);                                          \
363         ok(_Error == ERROR_NOACCESS, "Error = %lu\n", _Error);                          \
364     } while (0)
365 
366 #undef TestUserObjectInfoWithString
367 #define TestUserObjectInfoWithString(Handle, Index, Buffer, BufferSize, String) do                                                                          \
368     {                                                                                                                                                       \
369         BOOLEAN _Check;                                                                                                                                     \
370         TestUserObjectInfo(Handle,  Index,     NULL,             0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(String) * sizeof(WCHAR));\
371         TestUserObjectInfo(Handle,  Index,     (PVOID)1,         0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(String) * sizeof(WCHAR));\
372         TestUserObjectInfo(Handle,  Index,     NULL,             1,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(String) * sizeof(WCHAR));\
373         TestUserObjectInfo(Handle,  Index,     (PVOID)1,         1,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(String) * sizeof(WCHAR));\
374         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                                            \
375         TestUserObjectInfo(Handle,  Index,     Buffer,           sizeof(String) - 2,      FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(String) * sizeof(WCHAR));\
376         _Check = CheckBuffer(Buffer, BufferSize, 0x55);                                                                                                     \
377         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                                         \
378         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                                            \
379         TestUserObjectInfo(Handle,  Index,     Buffer,           sizeof(String) - 1,      FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(String) * sizeof(WCHAR));\
380         _Check = CheckBuffer(Buffer, BufferSize, 0x55);                                                                                                     \
381         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                                         \
382         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                                            \
383         TestUserObjectInfo(Handle,  Index,     Buffer,           sizeof(String),          TRUE,  0xdeadbeef,                sizeof(String));                \
384         ok(strcmp(Buffer, String) == 0, "Buffer '%s'\n", Buffer);                                                                                           \
385         _Check = CheckBuffer(Buffer + sizeof(String), BufferSize - sizeof(String), 0x55);                                                                   \
386         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                                         \
387         RtlFillMemory(Buffer, BufferSize, 0x55);                                                                                                            \
388         TestUserObjectInfo(Handle,  Index,     Buffer,           BufferSize,              TRUE,  0xdeadbeef,                sizeof(String));                \
389         ok(strcmp(Buffer, String) == 0, "Buffer '%s'\n", Buffer);                                                                                           \
390         _Check = CheckBuffer(Buffer + sizeof(String), BufferSize - sizeof(String), 0x55);                                                                   \
391         ok(_Check == TRUE, "CheckBuffer failed\n");                                                                                                         \
392     } while (0)
393 
394 static
395 void
396 TestGetUserObjectInfoA(void)
397 {
398     USEROBJECTFLAGS UserObjectFlags;
399     PCHAR Buffer;
400     ULONG BufferSize = 64;
401     HDESK Desktop;
402     HWINSTA WinSta;
403 
404     Buffer = AllocateGuarded(BufferSize);
405 
406     TestUserObjectInfo(NULL,    5,         NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
407     TestUserObjectInfo(NULL,    UOI_FLAGS, NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
408     TestUserObjectInfo(NULL,    UOI_FLAGS, (PVOID)1,         0,                       FALSE, ERROR_INVALID_HANDLE,      0);
409     TestUserObjectInfo(NULL,    UOI_FLAGS, NULL,             1,                       FALSE, ERROR_NOACCESS,            NOTSET);
410     TestUserObjectInfo(NULL,    UOI_FLAGS, (PVOID)1,         1,                       FALSE, ERROR_NOACCESS,            NOTSET);
411     TestUserObjectInfo(NULL,    UOI_FLAGS, &UserObjectFlags, sizeof(UserObjectFlags), FALSE, ERROR_INVALID_HANDLE,      0);
412 
413     TestUserObjectInfo(NULL,    UOI_TYPE,  NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
414     TestUserObjectInfo(NULL,    UOI_TYPE,  (PVOID)1,         0,                       FALSE, ERROR_INVALID_HANDLE,      0);
415     TestUserObjectInfo(NULL,    UOI_TYPE,  NULL,             1,                       FALSE, ERROR_INVALID_HANDLE,      0);
416     TestUserObjectInfo(NULL,    UOI_TYPE,  (PVOID)1,         1,                       FALSE, ERROR_INVALID_HANDLE,      0);
417     TestUserObjectInfo(NULL,    UOI_TYPE,  Buffer,           BufferSize,              FALSE, ERROR_INVALID_HANDLE,      0);
418 
419     TestUserObjectInfo(NULL,    UOI_NAME,  NULL,             0,                       FALSE, ERROR_INVALID_HANDLE,      0);
420     TestUserObjectInfo(NULL,    UOI_NAME,  (PVOID)1,         0,                       FALSE, ERROR_INVALID_HANDLE,      0);
421     TestUserObjectInfo(NULL,    UOI_NAME,  NULL,             1,                       FALSE, ERROR_INVALID_HANDLE,      0);
422     TestUserObjectInfo(NULL,    UOI_NAME,  (PVOID)1,         1,                       FALSE, ERROR_INVALID_HANDLE,      0);
423     TestUserObjectInfo(NULL,    UOI_NAME,  Buffer,           BufferSize,              FALSE, ERROR_INVALID_HANDLE,      0);
424 
425     Desktop = GetThreadDesktop(GetCurrentThreadId());
426     if (!Desktop)
427     {
428         skip("Failed to get desktop handle\n");
429         FreeGuarded(Buffer);
430         return;
431     }
432 
433     WinSta = GetProcessWindowStation();
434     if (!WinSta)
435     {
436         skip("Failed to get winsta handle\n");
437         FreeGuarded(Buffer);
438         return;
439     }
440 
441     TestUserObjectInfo(Desktop, 5,         NULL,             0,                       FALSE, ERROR_INVALID_PARAMETER,   0);
442     TestUserObjectInfo(Desktop, UOI_FLAGS, NULL,             0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(USEROBJECTFLAGS));
443     TestUserObjectInfo(Desktop, UOI_FLAGS, (PVOID)1,         0,                       FALSE, ERROR_INSUFFICIENT_BUFFER, sizeof(USEROBJECTFLAGS));
444     TestUserObjectInfo(Desktop, UOI_FLAGS, NULL,             1,                       FALSE, ERROR_NOACCESS,            NOTSET);
445     TestUserObjectInfo(Desktop, UOI_FLAGS, (PVOID)1,         1,                       FALSE, ERROR_NOACCESS,            NOTSET);
446     TestUserObjectInfo(Desktop, UOI_FLAGS, &UserObjectFlags, sizeof(UserObjectFlags), TRUE,  0xdeadbeef,                sizeof(USEROBJECTFLAGS));
447 
448     TestUserObjectInfoWithString(Desktop, UOI_TYPE, Buffer, BufferSize, "Desktop");
449     TestUserObjectInfoWithString(Desktop, UOI_NAME, Buffer, BufferSize, "Default");
450 
451     TestUserObjectInfoWithString(WinSta,  UOI_TYPE, Buffer, BufferSize, "WindowStation");
452     TestUserObjectInfoWithString(WinSta,  UOI_NAME, Buffer, BufferSize, "WinSta0");
453 
454     FreeGuarded(Buffer);
455 
456     /* Make sure nothing behind the needed buffer is touched */
457     BufferSize = sizeof("Desktop");
458     Buffer = AllocateGuarded(BufferSize);
459     TestUserObjectInfo(Desktop, UOI_TYPE,  Buffer,           BufferSize,              TRUE,  0xdeadbeef,                sizeof("Desktop"));
460     TestUserObjectInfo(Desktop, UOI_TYPE,  Buffer,           BufferSize + 1,          TRUE,  0xdeadbeef,                sizeof("Desktop"));
461     FreeGuarded(Buffer);
462 }
463 
464 START_TEST(GetUserObjectInformation)
465 {
466     TestGetUserObjectInfoW();
467     TestGetUserObjectInfoA();
468 }