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