ReactOS 0.4.16-dev-1636-g0502e33
wlntfytests.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Tests
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Tests for Winlogon notifications
5 * COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
6 *
7 * REFERENCES:
8 * - https://learn.microsoft.com/en-us/windows/win32/secauthn/creating-a-winlogon-notification-package
9 * - https://learn.microsoft.com/en-us/windows/win32/secauthn/winlogon-notification-events
10 * - https://rsdn.org/article/baseserv/winlogon.xml
11 */
12
13/* HEADERS *******************************************************************/
14
15/* C Headers */
16#include <stdlib.h>
17
18/* PSDK/NDK Headers */
19#define WIN32_NO_STATUS
20#include <windef.h>
21#include <winbase.h>
22#include <winreg.h>
23#include <winuser.h>
24#include <windowsx.h> // For GetInstanceModule()
25#include <winwlx.h>
26
27#define NTOS_MODE_USER
28#include <ndk/rtlfuncs.h> // For RtlAnsiStringToUnicodeString()
29
30#include <strsafe.h>
31
32#define STANDALONE
33#include "minitest.h" // Includes also <wine/debug.h>
34
35#define WINE_DEFAULT_DEBUG_CHANNEL_EX(ch, flags) \
36 static struct __wine_debug_channel __wine_dbch_##ch = { (unsigned char)(flags), #ch }; \
37 static struct __wine_debug_channel * const __wine_dbch___default = &__wine_dbch_##ch
38
39// WINE_DEFAULT_DEBUG_CHANNEL(wlnotify_tests);
41 (1 << __WINE_DBCL_TRACE) | (1 << __WINE_DBCL_WARN) |
42 (1 << __WINE_DBCL_ERR) | (1 << __WINE_DBCL_FIXME));
43
44
45/* GLOBALS *******************************************************************/
46
47#define NOTIFY_PKG_NAME L"WLNotifyTests"
48#define NOTIFY_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify\\" NOTIFY_PKG_NAME
49
50#define DEFAULT_WINSTA0 L"WinSta0"
51#define DESKTOP_WINLOGON L"Winlogon"
52#define DESKTOP_DEFAULT L"Default"
53#define DESKTOP_SCRSAVE L"Screen-saver"
54
55typedef enum _WLNOTIFY_STATE
56{
72
73static const PCSTR NotifyStateName[] =
74{
75 "Startup",
76 "Shutdown",
77 "Logon",
78 "Logoff",
79 "StartShell",
80 "PostShell",
81 "Lock",
82 "Unlock",
83 "StartScreenSaver",
84 "StopScreenSaver",
85 "Disconnect",
86 "Reconnect",
87 "NON-INITIALIZED",
88};
89
95static struct {
99} g_fFlags = {0};
100
102BOOL
105{
106 /*
107 * - The user is not logged in when State is either of:
108 * WLNotify_NonInitialized, WLNotify_Startup, WLNotify_Shutdown,
109 * WLNotify_Logoff, and perhaps (TODO TBD.): WLNotify_Disconnect,
110 * WLNotify_Reconnect.
111 *
112 * - The user is logged in when State is either of:
113 * WLNotify_Logon, WLNotify_StartShell, WLNotify_PostShell,
114 * WLNotify_Lock, WLNotify_Unlock.
115 *
116 * Note that WLNotify_StartScreenSaver and WLNotify_StopScreenSaver
117 * are not reliable for this test, because they can be invoked from
118 * either a logged-off or a logged-on state.
119 */
120 return ((State == WLNotify_Logon) ||
122}
123
124
125/* DEBUGGING HELPERS *********************************************************/
126
127#if 0
128void DPRINTF_FN(PCSTR FunctionName, PCWSTR Format, ...)
129{
130 WCHAR Buffer[512];
131 WCHAR* Current = Buffer;
132 size_t Length = _countof(Buffer);
133
134 StringCchPrintfExW(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, L"[%-20S] ", FunctionName);
135 va_list ArgList;
136 va_start(ArgList, Format);
137 StringCchVPrintfExW(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList);
138 va_end(ArgList);
140}
141
142#define DPRINTF(fmt, ...) DPRINTF_FN(__FUNCTION__, fmt, ##__VA_ARGS__ )
143#endif
144
146VOID
148{
149 if (IsDebuggerPresent())
151}
152
163static PCSTR
166{
167 UINT i;
168
170 i = State;
171 else
173
174 return NotifyStateName[i];
175}
176
177
178/* SYSTEM INFORMATION HELPERS ************************************************/
179
184static VOID
186{
187 HKEY hNotifyKey;
188 LSTATUS lError;
189 DWORD dwValue, dwSize, dwType;
190
192 return;
193
196 0,
198 &hNotifyKey);
199 if (lError != ERROR_SUCCESS)
200 {
201 ERR("RegOpenKeyExW() failed; error %lu\n", lError);
202 return; // HRESULT_FROM_WIN32(lError);
203 }
204
205 dwSize = sizeof(dwValue);
206 lError = RegQueryValueExW(hNotifyKey,
207 L"Asynchronous",
208 NULL,
209 &dwType,
210 (PBYTE)&dwValue,
211 &dwSize);
212 if ((lError == ERROR_SUCCESS) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue)))
213 g_fFlags.bAsync = !!dwValue;
214
215 dwSize = sizeof(dwValue);
216 lError = RegQueryValueExW(hNotifyKey,
217 L"Impersonate",
218 NULL,
219 &dwType,
220 (PBYTE)&dwValue,
221 &dwSize);
222 if ((lError == ERROR_SUCCESS) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue)))
223 g_fFlags.bImpersonate = !!dwValue;
224
225#if 0
226 dwSize = sizeof(dwValue);
227 lError = RegQueryValueExW(hNotifyKey,
228 L"MaxWait",
229 NULL,
230 &dwType,
231 (PBYTE)&dwValue,
232 &dwSize);
233 if ((lError == ERROR_SUCCESS) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue)))
234 g_dwMaxWait = !!dwValue;
235#endif
236
237 RegCloseKey(hNotifyKey);
238
239 return; // S_OK;
240}
241
265static PWSTR
267 _In_ HANDLE hObj,
268 _Out_writes_opt_z_(cchBufLength) PWSTR PreAllocBuffer, // _Inout_updates_opt_z_
269 _In_range_(0, MAXDWORD / sizeof(WCHAR)) DWORD cchBufLength)
270{
271 PWSTR pszBuffer = (cchBufLength ? PreAllocBuffer : NULL);
272 DWORD dwBufSize = (pszBuffer ? cchBufLength * sizeof(WCHAR) : 0);
273 DWORD dwReqSize = 0;
274
276 UOI_NAME,
277 pszBuffer,
278 dwBufSize,
279 &dwReqSize))
280 {
281 return pszBuffer;
282 }
283
284 if (dwReqSize > dwBufSize)
285 {
286 /* The call failed because the buffer was too small: reallocate it */
287 dwBufSize = dwReqSize;
288 pszBuffer = LocalAlloc(LMEM_FIXED, dwBufSize);
289 }
290 else
291 {
292 /* The call failed but the buffer was large enough: something else
293 * failed and we won't retrieve the object name */
294 pszBuffer = NULL;
295 }
296 if (!pszBuffer ||
298 UOI_NAME,
299 pszBuffer,
300 dwBufSize,
301 &dwReqSize))
302 {
303 if (pszBuffer)
304 LocalFree(pszBuffer);
305 pszBuffer = NULL;
306 }
307 return pszBuffer;
308}
309
334static BOOL
336 _In_ HANDLE hToken,
337 _Out_ PWSTR* UserName,
338 _Out_ PWSTR* DomainName)
339{
340 BOOL bRet = FALSE;
341 DWORD cbTokenBuffer = 0;
342 PTOKEN_USER pUserToken;
343
345 PWSTR pDomainName = NULL;
346 DWORD cbUserName = 0;
347 DWORD cbDomainName = 0;
348
349 SID_NAME_USE SidNameUse;
350
351 /* Retrieve token's information */
352 if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &cbTokenBuffer))
353 {
355 return FALSE;
356 }
357
358 pUserToken = LocalAlloc(LMEM_FIXED, cbTokenBuffer);
359 if (!pUserToken)
360 return FALSE;
361
362 if (!GetTokenInformation(hToken, TokenUser, pUserToken, cbTokenBuffer, &cbTokenBuffer))
363 {
364 LocalFree(pUserToken);
365 return FALSE;
366 }
367
368 /* Retrieve the domain and user name */
370 pUserToken->User.Sid,
371 NULL,
372 &cbUserName,
373 NULL,
374 &cbDomainName,
375 &SidNameUse))
376 {
378 goto done;
379 }
380
381 pUserName = LocalAlloc(LPTR, cbUserName * sizeof(WCHAR));
382 if (!pUserName)
383 goto done;
384
385 pDomainName = LocalAlloc(LPTR, cbDomainName * sizeof(WCHAR));
386 if (!pDomainName)
387 goto done;
388
390 pUserToken->User.Sid,
391 pUserName,
392 &cbUserName,
393 pDomainName,
394 &cbDomainName,
395 &SidNameUse))
396 {
397 goto done;
398 }
399
400 *UserName = pUserName;
401 *DomainName = pDomainName;
402 bRet = TRUE;
403
404done:
405 if (bRet == FALSE)
406 {
407 if (pUserName)
409 if (pDomainName)
410 LocalFree(pDomainName);
411 }
412 LocalFree(pUserToken);
413
414 return bRet;
415}
416
417
418typedef struct _SYSTEM_USER_INFO
419{
424 HWINSTA hWinSta;
427 // BYTE Data[ANYSIZE_ARRAY];
429
432 _In_ HANDLE hNotifToken,
433 _In_ HDESK hNotifDesktop)
434{
435 SYSTEM_USER_INFO LocalInfo = {NULL}, *pSysUserInfo;
438 WCHAR szBuffer0[MAX_PATH], szBuffer1[MAX_PATH], szBuffer2[MAX_PATH], szBuffer3[MAX_PATH];
439
440 /* Retrieve the process' token and the corresponding user/domain */
442 {
443 GetUserAndDomainName(LocalInfo.hProcToken, &LocalInfo.pProcUserName, &LocalInfo.pProcDomainName);
444 // CloseHandle(LocalInfo.hProcToken);
445 }
446
447 /* Retrieve the current thread's impersonation token, if any (otherwise
448 * no impersonation occurs), and the corresponding user/domain */
450 {
451 GetUserAndDomainName(LocalInfo.hThrdToken, &LocalInfo.pThrdUserName, &LocalInfo.pThrdDomainName);
452 // CloseHandle(LocalInfo.hThrdToken);
453 }
454
455 /* Retrieve the notification's corresponding user/domain */
456 GetUserAndDomainName(hNotifToken, &LocalInfo.pNotifUserName, &LocalInfo.pNotifDomainName);
457
458 /* Retrieve the process' window station name */
459 LocalInfo.hWinSta = GetProcessWindowStation();
460 LocalInfo.pszWinSta = GetUserObjectName(LocalInfo.hWinSta, szBuffer0, _countof(szBuffer0));
461
462 /* Retrieve the thread desktop name */
464 LocalInfo.pszThreadDesk = GetUserObjectName(LocalInfo.hThreadDesk, szBuffer1, _countof(szBuffer1));
465
466 /* Retrieve the input desktop name */
468 LocalInfo.pszInputDesk = GetUserObjectName(LocalInfo.hInputDesk, szBuffer2, _countof(szBuffer2));
469 // CloseDesktop(LocalInfo.hInputDesk);
470
471 /* Retrieve the notification desktop name */
472 LocalInfo.pszNotifDesk = GetUserObjectName(hNotifDesktop, szBuffer3, _countof(szBuffer3));
473
474
475 /* Allocate a single buffer to hold all the retrieved information */
476 BufSize = sizeof(*pSysUserInfo) +
477 ((LocalInfo.pProcUserName ? wcslen(LocalInfo.pProcUserName) + 1 : 0) +
478 (LocalInfo.pProcDomainName ? wcslen(LocalInfo.pProcDomainName) + 1 : 0) +
479 (LocalInfo.pThrdUserName ? wcslen(LocalInfo.pThrdUserName) + 1 : 0) +
480 (LocalInfo.pThrdDomainName ? wcslen(LocalInfo.pThrdDomainName) + 1 : 0) +
481 (LocalInfo.pNotifUserName ? wcslen(LocalInfo.pNotifUserName) + 1 : 0) +
482 (LocalInfo.pNotifDomainName ? wcslen(LocalInfo.pNotifDomainName) + 1 : 0) +
483 (LocalInfo.pszWinSta ? wcslen(LocalInfo.pszWinSta) + 1 : 0) +
484 (LocalInfo.pszThreadDesk ? wcslen(LocalInfo.pszThreadDesk) + 1 : 0) +
485 (LocalInfo.pszInputDesk ? wcslen(LocalInfo.pszInputDesk) + 1 : 0) +
486 (LocalInfo.pszNotifDesk ? wcslen(LocalInfo.pszNotifDesk) + 1 : 0)) * sizeof(WCHAR);
487 pSysUserInfo = LocalAlloc(LMEM_FIXED, BufSize);
488 if (!pSysUserInfo)
489 goto Done;
490
491 /* Copy the fixed part of the structure */
492 *pSysUserInfo = LocalInfo;
493
494 /* Copy the strings and adjust the pointers */
495 pString = (PWSTR)(pSysUserInfo + 1);
496 if (LocalInfo.pProcUserName)
497 {
498 wcscpy(pString, LocalInfo.pProcUserName);
499 pSysUserInfo->pProcUserName = pString;
500 pString += wcslen(pString) + 1;
501 }
502 if (LocalInfo.pProcDomainName)
503 {
504 wcscpy(pString, LocalInfo.pProcDomainName);
505 pSysUserInfo->pProcDomainName = pString;
506 pString += wcslen(pString) + 1;
507 }
508 if (LocalInfo.pThrdUserName)
509 {
510 wcscpy(pString, LocalInfo.pThrdUserName);
511 pSysUserInfo->pThrdUserName = pString;
512 pString += wcslen(pString) + 1;
513 }
514 if (LocalInfo.pThrdDomainName)
515 {
516 wcscpy(pString, LocalInfo.pThrdDomainName);
517 pSysUserInfo->pThrdDomainName = pString;
518 pString += wcslen(pString) + 1;
519 }
520 if (LocalInfo.pNotifUserName)
521 {
522 wcscpy(pString, LocalInfo.pNotifUserName);
523 pSysUserInfo->pNotifUserName = pString;
524 pString += wcslen(pString) + 1;
525 }
526 if (LocalInfo.pNotifDomainName)
527 {
528 wcscpy(pString, LocalInfo.pNotifDomainName);
529 pSysUserInfo->pNotifDomainName = pString;
530 pString += wcslen(pString) + 1;
531 }
532 if (LocalInfo.pszWinSta)
533 {
534 wcscpy(pString, LocalInfo.pszWinSta);
535 pSysUserInfo->pszWinSta = pString;
536 pString += wcslen(pString) + 1;
537 }
538 if (LocalInfo.pszThreadDesk)
539 {
540 wcscpy(pString, LocalInfo.pszThreadDesk);
541 pSysUserInfo->pszThreadDesk = pString;
542 pString += wcslen(pString) + 1;
543 }
544 if (LocalInfo.pszInputDesk)
545 {
546 wcscpy(pString, LocalInfo.pszInputDesk);
547 pSysUserInfo->pszInputDesk = pString;
548 pString += wcslen(pString) + 1;
549 }
550 if (LocalInfo.pszNotifDesk)
551 {
552 wcscpy(pString, LocalInfo.pszNotifDesk);
553 pSysUserInfo->pszNotifDesk = pString;
554 }
555
556Done:
557 if (LocalInfo.pszNotifDesk != szBuffer3)
558 LocalFree(LocalInfo.pszNotifDesk);
559 if (LocalInfo.pszInputDesk != szBuffer2)
560 LocalFree(LocalInfo.pszInputDesk);
561 if (LocalInfo.pszThreadDesk != szBuffer1)
562 LocalFree(LocalInfo.pszThreadDesk);
563 if (LocalInfo.pszWinSta != szBuffer0)
564 LocalFree(LocalInfo.pszWinSta);
565
566 if (LocalInfo.pNotifUserName)
567 LocalFree(LocalInfo.pNotifUserName);
568 if (LocalInfo.pNotifDomainName)
569 LocalFree(LocalInfo.pNotifDomainName);
570 if (LocalInfo.pThrdUserName)
571 LocalFree(LocalInfo.pThrdUserName);
572 if (LocalInfo.pThrdDomainName)
573 LocalFree(LocalInfo.pThrdDomainName);
574 if (LocalInfo.pProcUserName)
575 LocalFree(LocalInfo.pProcUserName);
576 if (LocalInfo.pProcDomainName)
577 LocalFree(LocalInfo.pProcDomainName);
578
579 /* If we failed to allocate the buffer, close the opened handles */
580 if (!pSysUserInfo)
581 {
582 CloseDesktop(LocalInfo.hInputDesk);
583 CloseHandle(LocalInfo.hThrdToken);
584 CloseHandle(LocalInfo.hProcToken);
585 }
586
587 return pSysUserInfo;
588}
589
590static VOID
592 _Inout_ PSYSTEM_USER_INFO SysUserInfo)
593{
594 CloseHandle(SysUserInfo->hProcToken);
595 CloseHandle(SysUserInfo->hThrdToken);
596 CloseDesktop(SysUserInfo->hInputDesk);
597 LocalFree(SysUserInfo);
598}
599
600
601static VOID
604 _In_ INT LineNum,
606 _In_ PSYSTEM_USER_INFO SysUserInfo,
608{
609 /*
610 * Dump the information and the WLX_NOTIFICATION_INFO structure.
611 */
612 // TRACE(
613 ros_dbg_log(__WINE_DBCL_ERR, __wine_dbch___default,
614 FileName, FuncName, LineNum,
615 "\nWLNOTIFY(%lx.%lx) [Async: %s, Impers: %s]: Entering `%s`\n"
616 "\tProcess Token : 0x%p - User: '%S\\%S'\n"
617 "\tThread Token : 0x%p - User: '%S\\%S'\n"
618 "\tNotif Token : 0x%p - User: '%S\\%S'\n"
619 "\tProcess WinSta : 0x%p '%S'\n"
620 "\tThread Desktop : 0x%p '%S'\n"
621 "\tInput Desktop : 0x%p '%S'\n"
622 "\tNotif Desktop : 0x%p '%S'\n",
623 GetCurrentProcessId(), // NtCurrentTeb()->ClientId.UniqueProcess
624 GetCurrentThreadId(), // NtCurrentTeb()->ClientId.UniqueThread
625 g_fFlags.bAsync ? "TRUE" : "FALSE",
626 g_fFlags.bImpersonate ? "TRUE" : "FALSE",
627 FuncName,
628 SysUserInfo->hProcToken, SysUserInfo->pProcDomainName, SysUserInfo->pProcUserName,
629 SysUserInfo->hThrdToken, SysUserInfo->pThrdDomainName, SysUserInfo->pThrdUserName,
630 pInfo->hToken, SysUserInfo->pNotifDomainName, SysUserInfo->pNotifUserName,
631 SysUserInfo->hWinSta, SysUserInfo->pszWinSta,
632 SysUserInfo->hThreadDesk, SysUserInfo->pszThreadDesk,
633 SysUserInfo->hInputDesk, SysUserInfo->pszInputDesk,
634 pInfo->hDesktop, SysUserInfo->pszNotifDesk);
635 // if (__WINE_IS_DEBUG_ON(_ERR, __wine_dbch___default))
636 DPRINTF(
637 "\tInfo.Size : %lu\n"
638 "\tInfo.Flags : 0x%lx\n"
639 "\tInfo.UserName : '%S'\n"
640 "\tInfo.Domain : '%S'\n"
641 "\tInfo.WindowStation : '%S'\n"
642 "\tInfo.hToken : 0x%p\n"
643 "\tInfo.hDesktop : 0x%p\n"
644 "\tInfo.pStatusCallback: 0x%p\n",
645 pInfo->Size, pInfo->Flags, pInfo->UserName,
646 pInfo->Domain, pInfo->WindowStation, pInfo->hToken,
647 pInfo->hDesktop, pInfo->pStatusCallback);
648}
649
650#define DUMP_WLX_NOTIFICATION(SysUserInfo, pInfo) \
651 DumpNotificationState(__RELFILE__, __LINE__, __FUNCTION__, (SysUserInfo), (pInfo))
652
653
654static VOID
657 _In_ INT LineNum,
659 _In_ BOOL bChange,
660 _In_ WLNOTIFY_STATE NewState)
661{
662 // TRACE(
663 ros_dbg_log(__WINE_DBCL_ERR, __wine_dbch___default,
664 FileName, FuncName, LineNum,
665 "**** %s: %s state %s %s %s\n",
666 FuncName,
667 bChange ? "Changing" : "Restoring",
669 bChange ? "to" : "back to",
670 NotifyStateToName(NewState));
671
673}
674
675#define CHANGE_STATE(bChange, NewState) \
676 ChangeNotificationState(__RELFILE__, __LINE__, __FUNCTION__, (bChange), (NewState))
677
678
679static DWORD
681 _In_opt_ PFNMSGECALLBACK pStatusCallback,
683 _In_ PCWSTR pMessage)
684{
685 DWORD dwRet;
686
687 if (!pStatusCallback)
688 return (DWORD)(-1);
689
690 dwRet = pStatusCallback(bVerbose, (LPWSTR)pMessage);
691
692 /* Do a 1-second delay so that the message can be seen while testing */
693 Sleep(1000);
694
695 return dwRet;
696}
697
698static DWORD
700 _In_opt_ PFNMSGECALLBACK pStatusCallback,
702 _In_ PCSTR pMessage)
703{
705 DWORD dwRet;
706 ANSI_STRING MessageA;
707 UNICODE_STRING MessageU;
708
709 if (!pStatusCallback)
710 return (DWORD)(-1);
711
712 RtlInitAnsiString(&MessageA, pMessage);
713 Status = RtlAnsiStringToUnicodeString(&MessageU, &MessageA, TRUE);
714 if (!NT_SUCCESS(Status))
715 return (DWORD)(-1);
716
717 dwRet = DisplayWlxMessageW(pStatusCallback, bVerbose, MessageU.Buffer);
718
719 RtlFreeUnicodeString(&MessageU);
720
721 return dwRet;
722}
723
724
725/* TESTING SUPPORT HELPERS ***************************************************/
726
727#define BEGIN_TEST \
728do { \
729 static const struct test winetest_testlist[] = { { __FUNCTION__, NULL } }; \
730 init_test( &winetest_testlist[0] ); \
731 winetest_push_context("**** %s", __FUNCTION__); \
732 {
733
734#define END_TEST \
735 } \
736 winetest_pop_context(); \
737 (void)fini_test(); \
738} while(0);
739
740#define ok_state_1(state1) \
741 ok(g_CurrentState == (state1), \
742 "ERROR: Wrong state %s, expected %s\n", \
743 NotifyStateToName(g_CurrentState), \
744 NotifyStateToName(state1))
745
746#define ok_state_2(state1, state2) \
747 ok(g_CurrentState == (state1) || g_CurrentState == (state2), \
748 "ERROR: Wrong state %s, expected %s or %s\n", \
749 NotifyStateToName(g_CurrentState), \
750 NotifyStateToName(state1), \
751 NotifyStateToName(state2))
752
753#define ok_state_3(state1, state2, state3) \
754 ok(g_CurrentState == (state1) || g_CurrentState == (state2) || g_CurrentState == (state3), \
755 "ERROR: Wrong state %s, expected %s or %s or %s\n", \
756 NotifyStateToName(g_CurrentState), \
757 NotifyStateToName(state1), \
758 NotifyStateToName(state2), \
759 NotifyStateToName(state3))
760
761typedef struct _TEST_ENTRY
762{
763 _Field_size_(NumStates) WLNOTIFY_STATE* AllowedStates;
764 ULONG NumStates;
765 // BOOL bProcToken;
766 // PCWSTR pProcUserName, pProcDomainName;
767 BOOL bThrdToken, bUserLoggedIn;
768 PCWSTR pszWinSta, pszThreadDesk;
769 _Maybenull_ PCWSTR pszInputDesk;
770 PCWSTR pszNotifDesk;
772
773static void
774DoTest(const char* file, int line, const char* funcname,
775 _In_ PSYSTEM_USER_INFO SysUserInfo,
777 _In_ PTEST_ENTRY pTest)
778{
781 UNREFERENCED_PARAMETER(funcname); // Displayed via winetest_push_context()
782
783 if (pTest->NumStates == 1)
784 ok_state_1(pTest->AllowedStates[0]);
785 else if (pTest->NumStates == 2)
786 ok_state_2(pTest->AllowedStates[0], pTest->AllowedStates[1]);
787 else if (pTest->NumStates == 3)
788 ok_state_3(pTest->AllowedStates[0], pTest->AllowedStates[1], pTest->AllowedStates[2]);
789 else
790 skip("Unsupported number of allowed notify states: %lu\n", pTest->NumStates);
791
792 ok(SysUserInfo->hProcToken != NULL, "Expected hProcToken != NULL\n");
793 ok(SysUserInfo->pProcDomainName != NULL, "Expected pProcDomainName != NULL\n");
794 ok(SysUserInfo->pProcUserName != NULL, "Expected pProcUserName != NULL\n");
795
796 if (pTest->bThrdToken)
797 {
798 ok(SysUserInfo->hThrdToken != NULL, "Expected hThrdToken != NULL\n");
799
800 ok(SysUserInfo->pThrdDomainName != NULL, "Expected pThrdDomainName != NULL\n");
801 if (!SysUserInfo->pThrdDomainName || !SysUserInfo->pNotifDomainName)
802 skip("Skipped pThrdDomainName/pNotifDomainName test\n");
803 else
804 ok_wstr(SysUserInfo->pThrdDomainName, SysUserInfo->pNotifDomainName);
805
806 ok(SysUserInfo->pThrdUserName != NULL, "Expected pThrdUserName != NULL\n");
807 if (!SysUserInfo->pThrdUserName || !SysUserInfo->pNotifUserName)
808 skip("Skipped pThrdUserName/pNotifUserName test\n");
809 else
810 ok_wstr(SysUserInfo->pThrdUserName, SysUserInfo->pNotifUserName);
811 }
812 else
813 {
814 ok(SysUserInfo->hThrdToken == NULL, "Expected hThrdToken == NULL\n");
815 ok(SysUserInfo->pThrdDomainName == NULL, "Expected pThrdDomainName == NULL\n");
816 ok(SysUserInfo->pThrdUserName == NULL, "Expected pThrdUserName == NULL\n");
817 }
818
819 if (pTest->bUserLoggedIn)
820 {
821 /* See also pInfo->UserName and pInfo->Domain below */
822 ok(pInfo->hToken != NULL, "Expected pInfo->hToken != NULL\n");
823 ok(SysUserInfo->pNotifDomainName != NULL, "Expected pNotifDomainName != NULL\n");
824 ok(SysUserInfo->pNotifUserName != NULL, "Expected pNotifUserName != NULL\n");
825 }
826 else
827 {
828 ok(pInfo->hToken == NULL, "Expected pInfo->hToken == NULL\n");
829 ok(SysUserInfo->pNotifDomainName == NULL, "Expected pNotifDomainName == NULL\n");
830 ok(SysUserInfo->pNotifUserName == NULL, "Expected pNotifUserName == NULL\n");
831 }
832
833 // if (pTest->pszWinSta) // Expected winsta -- DEFAULT_WINSTA0
834 ok(SysUserInfo->hWinSta != NULL, "Expected hProcWinSta != NULL\n");
835 ok(SysUserInfo->pszWinSta != NULL, "Expected pszWinSta != NULL\n");
836 if (!SysUserInfo->pszWinSta)
837 skip("Skipped pszWinSta test\n");
838 else
839 ok_wstr(SysUserInfo->pszWinSta, /*pTest->pszWinSta*/ DEFAULT_WINSTA0);
840
841 // if (pTest->pszThreadDesk) // Expected thread desk -- DESKTOP_WINLOGON
842 ok(SysUserInfo->hThreadDesk != NULL, "Expected hThreadDesk != NULL\n");
843 ok(SysUserInfo->pszThreadDesk != NULL, "Expected pszThreadDesk != NULL\n");
844 if (!SysUserInfo->pszThreadDesk)
845 skip("Skipped pszThreadDesk test\n");
846 else
847 ok_wstr(SysUserInfo->pszThreadDesk, DESKTOP_WINLOGON);
848
849 if (pTest->pszInputDesk)
850 {
851 ok(SysUserInfo->hInputDesk != NULL, "Expected hInputDesk != NULL\n");
852 ok(SysUserInfo->pszInputDesk != NULL, "Expected pszInputDesk != NULL\n");
853 if (!SysUserInfo->pszInputDesk)
854 skip("Skipped pszInputDesk test\n");
855 else
856 ok_wstr(SysUserInfo->pszInputDesk, pTest->pszInputDesk);
857 }
858 else
859 {
860 ok(SysUserInfo->hInputDesk == NULL, "Expected hInputDesk == NULL\n");
861 ok(SysUserInfo->pszInputDesk == NULL, "Expected pszInputDesk == NULL\n");
862 }
863
864 // if (pTest->pszNotifDesk)
865 ok(pInfo->hDesktop != NULL, "Expected pInfo->hDesktop != NULL\n");
866 ok(SysUserInfo->pszNotifDesk != NULL, "Expected pszNotifDesk != NULL\n");
867 if (!SysUserInfo->pszNotifDesk)
868 skip("Skipped pszNotifDesk test\n");
869 else
870 ok_wstr(SysUserInfo->pszNotifDesk, pTest->pszNotifDesk);
871
872 ok_int(pInfo->Size, sizeof(*pInfo)); // == sizeof(WLX_NOTIFICATION_INFO);
873 // ok_int(pInfo->Flags, 0); // This is tested separately: more than one flag is possible.
874
875 if (pTest->bUserLoggedIn)
876 {
877 ok(pInfo->UserName != NULL, "Expected pInfo->UserName != NULL\n");
878 ok(pInfo->Domain != NULL, "Expected pInfo->Domain != NULL\n");
879 // ok(pInfo->hToken != NULL, "Expected pInfo->hToken != NULL\n");
880
881 if (!pInfo->UserName || !SysUserInfo->pNotifUserName)
882 skip("Skipped UserName/pNotifUserName test\n");
883 else
884 ok_wstr(pInfo->UserName, SysUserInfo->pNotifUserName);
885
886 if (!pInfo->Domain || !SysUserInfo->pNotifDomainName)
887 skip("Skipped Domain/pNotifDomainName test\n");
888 else
889 ok_wstr(pInfo->Domain, SysUserInfo->pNotifDomainName);
890 }
891 else
892 {
893 ok(pInfo->UserName == NULL, "Expected pInfo->UserName == NULL\n");
894 ok(pInfo->Domain == NULL, "Expected pInfo->Domain == NULL\n");
895 // ok(pInfo->hToken == NULL, "Expected pInfo->hToken == NULL\n");
896 }
897
898 ok(pInfo->WindowStation != NULL, "Expected pInfo->WindowStation != NULL\n");
899 if (!pInfo->WindowStation || !SysUserInfo->pszWinSta)
900 skip("Skipped WindowStation/pszWinSta test\n");
901 else
902 ok_wstr(pInfo->WindowStation, SysUserInfo->pszWinSta);
903
904 if (wcscmp(pTest->pszNotifDesk, /*pTest->pszThreadDesk*/ DESKTOP_WINLOGON) == 0)
905 ok(pInfo->hDesktop == SysUserInfo->hThreadDesk, "Expected pInfo->hDesktop == hThreadDesk\n");
906 else
907 ok(pInfo->hDesktop != SysUserInfo->hThreadDesk, "Expected pInfo->hDesktop != hThreadDesk\n");
908
909 if (g_fFlags.bAsync)
910 ok(pInfo->pStatusCallback == NULL, "Expected pStatusCallback == NULL, was: 0x%p\n", pInfo->pStatusCallback);
911 else
912 ok(pInfo->pStatusCallback != NULL, "Expected pStatusCallback != NULL\n");
913}
914
915
916/* NOTIFICATION HANDLERS *****************************************************/
917
918#define __HANDLER_PARAM(pNotifInfo)(_In_ PWLX_NOTIFICATION_INFO pNotifInfo)
919#define WLNOTIFY_HANDLER(name) \
920 VOID WINAPI name __HANDLER_PARAM
921
922#define BEGIN_HANDLER /*(SysUserInfo, pInfo)*/ \
923 PSYSTEM_USER_INFO SysUserInfo; \
924 SysUserInfo = GetSystemUserInfo(pInfo->hToken, pInfo->hDesktop); \
925 DUMP_WLX_NOTIFICATION(SysUserInfo, pInfo); \
926 DisplayWlxMessageA(pInfo->pStatusCallback, FALSE, __FUNCTION__); \
927 DbgBreakOnEvent();
928
929#define END_HANDLER(bChangeState, NewState) \
930 FreeSystemUserInfo(SysUserInfo); \
931 /* Change (bChangeState == TRUE) or Restore previous (FALSE) state */ \
932 CHANGE_STATE(bChangeState, NewState);
933
934
939{
940 /* Initially retrieve the notification registry settings */
941 GetSettings();
942
944
946 {
947 /* We must be called from the non-initialized state */
949 TEST_ENTRY StartupTest =
950 { States, _countof(States), FALSE, FALSE, DEFAULT_WINSTA0,
952
953 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &StartupTest);
954
955 ok_int(pInfo->Flags, 0);
956 }
958
959 /* Change state */
961}
962
967{
969
971 {
972 /* We must be called from either Startup or previous Logoff */
974 TEST_ENTRY ShutdownTest =
975 { States, _countof(States), FALSE, FALSE, DEFAULT_WINSTA0,
977
978 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &ShutdownTest);
979
980 /* Compare these flags with those from WLEventLogoff */
981 ok_int(pInfo->Flags, g_fLogoffShutdownFlags);
982 /*
983 * - If the logged-on user chooses to shutdown or reboot the computer,
984 * WLEventLogoff() is first invoked with pInfo->Flags == EWX_SHUTDOWN
985 * or EWX_SHUTDOWN | EWX_REBOOT (stored in g_fLogoffShutdownFlags),
986 * then WLEventShutdown() is invoked with the same values.
987 *
988 * - If the logged-on user chooses to log off only, WLEventLogoff()
989 * is invoked with pInfo->Flags == 0 (== EWX_LOGOFF).
990 *
991 * - Independently of whether the user chose to shutdown or reboot
992 * the computer at the SAS dialog before logging in first (thus,
993 * g_CurrentState == WLNotify_Startup), or when coming back at the
994 * SAS dialog after logged off (g_CurrentState == WLNotify_Logoff),
995 * WLEventShutdown() is invoked with pInfo->Flags == 0.
996 * (In both these cases, g_fLogoffShutdownFlags == 0 too.)
997 */
998 ok(pInfo->Flags == EWX_LOGOFF ||
999 pInfo->Flags == EWX_SHUTDOWN ||
1000 pInfo->Flags == (EWX_SHUTDOWN | EWX_REBOOT),
1001 "Expected pInfo->Flags == EWX_LOGOFF (0) or EWX_SHUTDOWN (1) or EWX_SHUTDOWN|EWX_REBOOT (3), got %lu\n",
1002 pInfo->Flags);
1003 }
1004 END_TEST
1005
1006 /* Change state */
1008}
1009
1010
1015{
1017
1019 {
1020 /* We must be called from either Startup or previous Logoff */
1022 PWSTR pszInputDesk = (g_fFlags.bImpersonate ? NULL : DESKTOP_WINLOGON);
1023 TEST_ENTRY LogonTest =
1024 { States, _countof(States), g_fFlags.bImpersonate, TRUE,
1026
1027 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &LogonTest);
1028
1029 ok_int(pInfo->Flags, 0);
1030 }
1031 END_TEST
1032
1033 /* Change state */
1035}
1036
1041{
1043
1044 /* Save the flags for comparison with those in WLEventShutdown */
1046
1048 {
1049 /* We must be called from PostShell, or StartShell if we failed to start
1050 * the shell (the PostShell notification isn't emitted in this case) */
1052 TEST_ENTRY LogoffTest =
1053 { States, _countof(States), g_fFlags.bImpersonate, TRUE,
1055
1056 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &LogoffTest);
1057
1058 ok(pInfo->Flags == EWX_LOGOFF ||
1059 pInfo->Flags == EWX_SHUTDOWN ||
1060 pInfo->Flags == (EWX_SHUTDOWN | EWX_REBOOT),
1061 "Expected pInfo->Flags == EWX_LOGOFF (0) or EWX_SHUTDOWN (1) or EWX_SHUTDOWN|EWX_REBOOT (3), got %lu\n",
1062 pInfo->Flags);
1063 }
1064 END_TEST
1065
1066 /* Change state */
1068}
1069
1070
1075{
1077
1079 {
1080 /* We must be called from Logon */
1081 WLNOTIFY_STATE States[] = {WLNotify_Logon};
1082 PWSTR pszInputDesk = (g_fFlags.bImpersonate ? NULL : DESKTOP_WINLOGON);
1083 TEST_ENTRY StartShellTest =
1084 { States, _countof(States), g_fFlags.bImpersonate, TRUE,
1086
1087 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &StartShellTest);
1088
1089 ok_int(pInfo->Flags, 0);
1090 }
1091 END_TEST
1092
1093 /* Change state */
1095}
1096
1101{
1103
1105 {
1106 /* We must be called from StartShell */
1108 PWSTR pszInputDesk =
1109 (g_fFlags.bAsync ? DESKTOP_DEFAULT
1110 : (g_fFlags.bImpersonate ? NULL : DESKTOP_WINLOGON));
1111 TEST_ENTRY PostShellTest =
1112 { States, _countof(States), g_fFlags.bImpersonate, TRUE,
1114
1115 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &PostShellTest);
1116
1117 ok_int(pInfo->Flags, 0);
1118 }
1119 END_TEST
1120
1121 /* Change state */
1123}
1124
1125
1130{
1132
1134 {
1135 /* We must be called from PostShell */
1137 PWSTR pszInputDesk = (g_fFlags.bImpersonate ? NULL : DESKTOP_WINLOGON);
1138 TEST_ENTRY LockTest =
1139 { States, _countof(States), g_fFlags.bImpersonate, TRUE,
1141
1142 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &LockTest);
1143
1144 ok_int(pInfo->Flags, 0);
1145 }
1146 END_TEST
1147
1148 /* Change state */
1150}
1151
1156{
1158
1160 {
1161 /* We must be called from Lock */
1162 WLNOTIFY_STATE States[] = {WLNotify_Lock};
1163 PWSTR pszInputDesk =
1164 (g_fFlags.bAsync ? DESKTOP_DEFAULT
1165 : (g_fFlags.bImpersonate ? NULL : DESKTOP_WINLOGON));
1166 TEST_ENTRY UnlockTest =
1167 { States, _countof(States), g_fFlags.bImpersonate, TRUE,
1169
1170 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &UnlockTest);
1171
1172 ok_int(pInfo->Flags, 0);
1173 }
1174 END_TEST
1175
1176 /* Restore previous state */
1178}
1179
1180
1185{
1187
1189 {
1190 /* We must be called from Startup, Logoff, PostShell.
1191 * In case of Startup or Logoff, no user is logged in,
1192 * therefore no notification user token is present. */
1194 BOOL bUserLoggedIn = IsUserLoggedIn(g_CurrentState);
1195 BOOL bImpersonate = (g_fFlags.bImpersonate && bUserLoggedIn);
1196 TEST_ENTRY StartScreenSaverTest =
1197 { States, _countof(States), bImpersonate, bUserLoggedIn,
1199
1200 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &StartScreenSaverTest);
1201
1202 ok_int(pInfo->Flags, 0);
1203 }
1204 END_TEST
1205
1206 /* Change state */
1208}
1209
1214{
1216
1218 {
1219 /* We must be called from StartScreenSaver.
1220 * In case StartScreenSaver was called originally from Startup or Logoff,
1221 * no user is logged in, therefore no notification user token is present. */
1223 BOOL bUserLoggedIn = IsUserLoggedIn(g_PreviousState);
1224 BOOL bImpersonate = (g_fFlags.bImpersonate && bUserLoggedIn);
1225 PWSTR pszInputDesk =
1227 : DESKTOP_SCRSAVE);
1228 TEST_ENTRY StopScreenSaverTest =
1229 { States, _countof(States), bImpersonate, bUserLoggedIn,
1231
1232 DoTest(__RELFILE__, __LINE__, __FUNCTION__, SysUserInfo, pInfo, &StopScreenSaverTest);
1233
1234 ok_int(pInfo->Flags, 0);
1235 }
1236 END_TEST
1237
1238 /* Restore previous state */
1240}
1241
1242
1247{
1249
1251 {
1252 ERR("**** %s: Previous state %s\n",
1254 }
1255 END_TEST
1256
1257 /* Change state */
1259}
1260
1265{
1267
1269 {
1270 /* We must be called from Disconnect */
1272 }
1273 END_TEST
1274
1275 /* Restore previous state */
1277}
1278
1279
1280/* ENTRY-POINT; (UN-)INSTALLATION ROUTINES ***********************************/
1281
1282BOOL
1283WINAPI
1287 _In_ PVOID pReserved)
1288{
1289 // DPRINTF
1290 TRACE("\nWLNOTIFY(%lx.%lx): Entering `%s`(hInst: 0x%p, dwReason: 0x%x, pReserved: 0x%p)\n",
1291 GetCurrentProcessId(), // NtCurrentTeb()->ClientId.UniqueProcess
1292 GetCurrentThreadId(), // NtCurrentTeb()->ClientId.UniqueThread
1293 __FUNCTION__, hInstance, dwReason, pReserved);
1294
1295 switch (dwReason)
1296 {
1297 case DLL_PROCESS_ATTACH:
1301
1302 case DLL_PROCESS_DETACH:
1303 {
1304 // DPRINTF
1305 ERR("\nWLNOTIFY(%lx.%lx): Entering `%s`(hInst: 0x%p, dwReason: 0x%x, pReserved: 0x%p)\n",
1306 GetCurrentProcessId(), // NtCurrentTeb()->ClientId.UniqueProcess
1307 GetCurrentThreadId(), // NtCurrentTeb()->ClientId.UniqueThread
1308 __FUNCTION__, hInstance, dwReason, pReserved);
1309
1310 /* Reset to detect any unwanted reloads */
1312 break;
1313 }
1314 }
1315
1316 return TRUE;
1317}
1318
1324static const struct
1325{
1328} NotifyEvents[] =
1329{
1330 {L"Startup" , L"WLEventStartup"},
1331 {L"Shutdown", L"WLEventShutdown"},
1332 {L"Logon" , L"WLEventLogon"},
1333 {L"Logoff", L"WLEventLogoff"},
1334 {L"StartShell", L"WLEventStartShell"},
1335 {L"PostShell" , L"WLEventPostShell"},
1336 {L"Lock" , L"WLEventLock"},
1337 {L"Unlock", L"WLEventUnlock"},
1338 {L"StartScreenSaver", L"WLEventStartScreenSaver"},
1339 {L"StopScreenSaver" , L"WLEventStopScreenSaver"},
1340 {L"Disconnect", L"WLEventDisconnect"},
1341 {L"Reconnect" , L"WLEventReconnect"},
1343
1345{
1346 HKEY hNotifyKey;
1347 LSTATUS lError;
1348 UINT i;
1349 DWORD dwValue;
1350 DWORD dwPathSize;
1351 WCHAR szModule[MAX_PATH];
1352
1353 dwPathSize = GetModuleFileNameW(g_hModule, szModule, _countof(szModule));
1354 szModule[_countof(szModule) - 1] = UNICODE_NULL; // Ensure NULL-termination (see WinXP bug)
1355
1356 if ( !((dwPathSize != 0) && (dwPathSize < _countof(szModule)) &&
1358 {
1359 /* Failed to retrieve the module path */
1360 return E_FAIL; // Cannot register.
1361 }
1362
1365 0,
1366 NULL,
1369 NULL,
1370 &hNotifyKey,
1371 NULL);
1372 if (lError != ERROR_SUCCESS)
1373 {
1374 ERR("RegCreateKeyExW() failed; error %lu\n", lError);
1375 return HRESULT_FROM_WIN32(lError); // Cannot register.
1376 }
1377
1378 RegSetValueExW(hNotifyKey, L"DllName", 0, REG_EXPAND_SZ,
1379 (PBYTE)szModule, (DWORD)(wcslen(szModule) + 1) * sizeof(WCHAR));
1380
1381 /* Make the notifications synchronous by default */
1382 dwValue = 0;
1383 RegSetValueExW(hNotifyKey, L"Asynchronous", 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue));
1384
1385 /* Don't impersonate the user when being invoked */
1386 dwValue = 0;
1387 RegSetValueExW(hNotifyKey, L"Impersonate", 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue));
1388
1389 /* Can be invoked also in SafeMode */
1390 dwValue = 1;
1391 RegSetValueExW(hNotifyKey, L"SafeMode", 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue));
1392
1393 // dwValue = 600;
1394 // RegSetValueExW(hNotifyKey, L"MaxWait", 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue));
1395
1396 for (i = 0; i < _countof(NotifyEvents); ++i)
1397 {
1399 0, REG_SZ,
1401 (DWORD)(wcslen(NotifyEvents[i].Value) + 1) * sizeof(WCHAR));
1402 }
1403
1404 RegCloseKey(hNotifyKey);
1405
1406 return S_OK; // Registration successful.
1407}
1408
1410{
1411 LSTATUS lError;
1412
1414 if (lError == ERROR_FILE_NOT_FOUND)
1415 return S_FALSE; // Nothing to unregister, not a failure per se.
1416 if (lError != ERROR_SUCCESS)
1417 {
1418 ERR("RegDeleteKeyW() failed; error %lu\n", lError);
1419 return HRESULT_FROM_WIN32(lError);
1420 }
1421 return S_OK; // Unregistration successful.
1422}
1423
1424/* EOF */
static LPWSTR pUserName
#define BufSize
Definition: FsRtlTunnel.c:28
unsigned char UINT8
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char * FunctionName
Definition: acpixf.h:1279
#define InterlockedExchange
Definition: armddk.h:54
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define ok_wstr(x, y)
Definition: atltest.h:130
#define ok_int(expression, result)
Definition: atltest.h:134
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
DWORD dwReason
Definition: misc.cpp:135
#define RegCloseKey(hKey)
Definition: registry.h:49
HINSTANCE hInstance
Definition: charmap.c:19
Definition: bufpool.h:45
wcscpy
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define E_FAIL
Definition: ddrawi.h:102
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1239
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
BOOL WINAPI LookupAccountSidW(LPCWSTR pSystemName, PSID pSid, LPWSTR pAccountName, LPDWORD pdwAccountName, LPWSTR pDomainName, LPDWORD pdwDomainName, PSID_NAME_USE peUse)
Definition: misc.c:537
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:411
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
BOOL WINAPI OpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, HANDLE *TokenHandle)
Definition: security.c:336
#define CloseHandle
Definition: compat.h:739
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define GetCurrentProcess()
Definition: compat.h:759
#define MAX_PATH
Definition: compat.h:34
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
BOOL WINAPI IsDebuggerPresent(void)
Definition: debug.c:167
#define L(x)
Definition: resources.c:13
#define __FUNCTION__
Definition: types.h:116
#define __RELFILE__
Definition: debug.h:11
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxString * pString
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
void WINAPI SHIM_OBJ_NAME() OutputDebugStringW(LPCWSTR lpOutputString)
Definition: ignoredbgout.c:23
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define S_OK
Definition: intsafe.h:52
macro IMPORT Name endm macro EXPORT Name global &Name endm macro TEXTAREA section rx align endm macro DATAAREA section rw endm macro RODATAAREA section rw endm macro NESTED_ENTRY Name FuncName equ &Name PrologName equ &Name &_Prolog FuncEndName equ &Name &_end global &FuncName align func &FuncName & FuncName
Definition: kxarm.h:221
#define REG_SZ
Definition: layer.c:22
BOOL bVerbose
Definition: logoff.c:26
enum _SID_NAME_USE SID_NAME_USE
#define LPTR
Definition: minwinbase.h:93
#define LMEM_FIXED
Definition: minwinbase.h:81
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
HRESULT WINAPI DllRegisterServer(void)
Definition: msctf.cpp:586
HRESULT WINAPI DllUnregisterServer(void)
Definition: msctf.cpp:594
unsigned int UINT
Definition: ndis.h:50
#define _Inout_
Definition: no_sal2.h:162
#define _Field_size_(s)
Definition: no_sal2.h:332
#define _Maybenull_
Definition: no_sal2.h:56
#define _Out_writes_opt_z_(s)
Definition: no_sal2.h:230
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _In_range_(l, h)
Definition: no_sal2.h:368
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define MAXDWORD
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STRSAFE_NULL_ON_FAILURE
Definition: ntstrsafe.h:34
BYTE * PBYTE
Definition: pedump.c:66
#define __fallthrough
Definition: sal_old.h:314
#define REG_DWORD
Definition: sdbapi.c:598
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
@ __WINE_DBCL_ERR
Definition: debug.h:52
@ __WINE_DBCL_TRACE
Definition: debug.h:54
@ __WINE_DBCL_FIXME
Definition: debug.h:51
@ __WINE_DBCL_WARN
Definition: debug.h:53
const char int int int ros_dbg_log(enum __wine_debug_class cls, struct __wine_debug_channel *ch, const char *file, const char *func, const int line, const char *format,...) __WINE_PRINTF_ATTR(6
#define DPRINTF
Definition: debug.h:414
#define funcname
Definition: shellext.h:96
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCchVPrintfExW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat, va_list argList)
Definition: strsafe.h:661
STRSAFEAPI StringCchPrintfExW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:585
Definition: cmd.c:13
SID_AND_ATTRIBUTES User
Definition: setypes.h:1022
Definition: fci.c:127
Definition: parser.c:49
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define FORCEINLINE
Definition: wdftypes.h:67
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1148
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
HWINSTA WINAPI GetProcessWindowStation(void)
Definition: ntwrapper.h:124
#define WINAPI
Definition: msvc.h:6
#define GetInstanceModule(hInstance)
Definition: windowsx.h:303
#define S_FALSE
Definition: winerror.h:3451
static HRESULT HRESULT_FROM_WIN32(unsigned int x)
Definition: winerror.h:210
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
HDESK WINAPI GetThreadDesktop(_In_ DWORD)
#define EWX_SHUTDOWN
Definition: winuser.h:647
#define UOI_NAME
Definition: winuser.h:1095
HDESK WINAPI OpenInputDesktop(_In_ DWORD, _In_ BOOL, _In_ DWORD)
#define EWX_LOGOFF
Definition: winuser.h:644
#define EWX_REBOOT
Definition: winuser.h:646
BOOL WINAPI GetUserObjectInformationW(_In_ HANDLE hObj, _In_ int nIndex, _Out_writes_bytes_opt_(nLength) PVOID pvInfo, _In_ DWORD nLength, _Out_opt_ LPDWORD lpnLengthNeeded)
BOOL WINAPI CloseDesktop(_In_ HDESK)
DWORD(CALLBACK * PFNMSGECALLBACK)(_In_ BOOL bVerbose, _In_ LPWSTR lpMessage)
Definition: winwlx.h:617
#define NOTIFY_REG_PATH
Definition: wlntfytests.c:48
static struct @1772 g_fFlags
static BOOL g_bInitialized
TRUE when the flags have been initialized.
Definition: wlntfytests.c:94
static VOID FreeSystemUserInfo(_Inout_ PSYSTEM_USER_INFO SysUserInfo)
Definition: wlntfytests.c:591
static const PCSTR NotifyStateName[]
Definition: wlntfytests.c:73
#define ok_state_2(state1, state2)
Definition: wlntfytests.c:746
FORCEINLINE VOID DbgBreakOnEvent(VOID)
Definition: wlntfytests.c:147
WLNOTIFY_HANDLER() WLEventReconnect(pInfo)
Invoked at workstation reconnect (Terminal Services).
Definition: wlntfytests.c:1264
static VOID ChangeNotificationState(_In_ PCSTR FileName, _In_ INT LineNum, _In_ PCSTR FuncName, _In_ BOOL bChange, _In_ WLNOTIFY_STATE NewState)
Definition: wlntfytests.c:655
WLNOTIFY_HANDLER() WLEventStartShell(pInfo)
Invoked just before starting the user shell.
Definition: wlntfytests.c:1074
static DWORD DisplayWlxMessageW(_In_opt_ PFNMSGECALLBACK pStatusCallback, _In_ BOOL bVerbose, _In_ PCWSTR pMessage)
Definition: wlntfytests.c:680
WLNOTIFY_HANDLER() WLEventShutdown(pInfo)
Invoked at system shutdown.
Definition: wlntfytests.c:966
WLNOTIFY_HANDLER() WLEventDisconnect(pInfo)
Invoked at workstation disconnect (Terminal Services).
Definition: wlntfytests.c:1246
static WLNOTIFY_STATE g_PreviousState
Definition: wlntfytests.c:91
struct _TEST_ENTRY TEST_ENTRY
static PSYSTEM_USER_INFO GetSystemUserInfo(_In_ HANDLE hNotifToken, _In_ HDESK hNotifDesktop)
Definition: wlntfytests.c:431
static ULONG g_fLogoffShutdownFlags
Definition: wlntfytests.c:92
WLNOTIFY_HANDLER() WLEventStopScreenSaver(pInfo)
Invoked at screensaver stop.
Definition: wlntfytests.c:1213
#define ok_state_1(state1)
Definition: wlntfytests.c:740
static VOID DumpNotificationState(_In_ PCSTR FileName, _In_ INT LineNum, _In_ PCSTR FuncName, _In_ PSYSTEM_USER_INFO SysUserInfo, _In_ PWLX_NOTIFICATION_INFO pInfo)
Definition: wlntfytests.c:602
UINT8 bAsync
Definition: wlntfytests.c:96
struct _SYSTEM_USER_INFO * PSYSTEM_USER_INFO
#define WLNOTIFY_HANDLER(name)
Definition: wlntfytests.c:919
static void DoTest(const char *file, int line, const char *funcname, _In_ PSYSTEM_USER_INFO SysUserInfo, _In_ PWLX_NOTIFICATION_INFO pInfo, _In_ PTEST_ENTRY pTest)
Definition: wlntfytests.c:774
static WLNOTIFY_STATE g_CurrentState
Definition: wlntfytests.c:90
WLNOTIFY_HANDLER() WLEventUnlock(pInfo)
Invoked at workstation unlocking.
Definition: wlntfytests.c:1155
WLNOTIFY_HANDLER() WLEventLogoff(pInfo)
Invoked at user logoff.
Definition: wlntfytests.c:1040
WLNOTIFY_HANDLER() WLEventLock(pInfo)
Invoked at workstation locking.
Definition: wlntfytests.c:1129
#define DESKTOP_WINLOGON
Definition: wlntfytests.c:51
#define BEGIN_TEST
Definition: wlntfytests.c:727
#define DESKTOP_DEFAULT
Definition: wlntfytests.c:52
static HMODULE g_hModule
Definition: wlntfytests.c:93
#define END_HANDLER(bChangeState, NewState)
Definition: wlntfytests.c:929
#define DEFAULT_WINSTA0
Definition: wlntfytests.c:50
#define ok_state_3(state1, state2, state3)
Definition: wlntfytests.c:753
PCWSTR Value
Definition: wlntfytests.c:1327
WLNOTIFY_HANDLER() WLEventPostShell(pInfo)
Invoked just after starting the user shell.
Definition: wlntfytests.c:1100
static PWSTR GetUserObjectName(_In_ HANDLE hObj, _Out_writes_opt_z_(cchBufLength) PWSTR PreAllocBuffer, _In_range_(0, MAXDWORD/sizeof(WCHAR)) DWORD cchBufLength)
Retrieves the name of the specified window station or desktop object.
Definition: wlntfytests.c:266
#define WINE_DEFAULT_DEBUG_CHANNEL_EX(ch, flags)
Definition: wlntfytests.c:35
UINT8 bImpersonate
Definition: wlntfytests.c:97
static PCSTR NotifyStateToName(_In_ WLNOTIFY_STATE State)
Maps a WLNOTIFY_STATE value to its human-readable name.
Definition: wlntfytests.c:164
WLNOTIFY_HANDLER() WLEventStartup(pInfo)
Invoked at system startup.
Definition: wlntfytests.c:938
#define DESKTOP_SCRSAVE
Definition: wlntfytests.c:53
PCWSTR ValueName
Definition: wlntfytests.c:1326
static VOID GetSettings(VOID)
Retrieves the notification settings from the registry.
Definition: wlntfytests.c:185
BOOL WINAPI DllMain(_In_ HINSTANCE hInstance, _In_ DWORD dwReason, _In_ PVOID pReserved)
Definition: wlntfytests.c:1284
WLNOTIFY_HANDLER() WLEventLogon(pInfo)
Invoked at user logon.
Definition: wlntfytests.c:1014
FORCEINLINE BOOL IsUserLoggedIn(_In_ WLNOTIFY_STATE State)
Definition: wlntfytests.c:103
_WLNOTIFY_STATE
Definition: wlntfytests.c:56
@ WLNotify_StartShell
Definition: wlntfytests.c:62
@ WLNotify_Disconnect
Definition: wlntfytests.c:68
@ WLNotify_Logoff
Definition: wlntfytests.c:61
@ WLNotify_PostShell
Definition: wlntfytests.c:63
@ WLNotify_StopScreenSaver
Definition: wlntfytests.c:67
@ WLNotify_Lock
Definition: wlntfytests.c:64
@ WLNotify_StartScreenSaver
Definition: wlntfytests.c:66
@ WLNotify_Startup
Definition: wlntfytests.c:58
@ WLNotify_Unlock
Definition: wlntfytests.c:65
@ WLNotify_NonInitialized
Definition: wlntfytests.c:57
@ WLNotify_Logon
Definition: wlntfytests.c:60
@ WLNotify_MaxState
Definition: wlntfytests.c:70
@ WLNotify_Shutdown
Definition: wlntfytests.c:59
@ WLNotify_Reconnect
Definition: wlntfytests.c:69
struct _TEST_ENTRY * PTEST_ENTRY
UINT8 Reserved
Definition: wlntfytests.c:98
WLNOTIFY_HANDLER() WLEventStartScreenSaver(pInfo)
Invoked at screensaver start.
Definition: wlntfytests.c:1184
enum _WLNOTIFY_STATE WLNOTIFY_STATE
static BOOL GetUserAndDomainName(_In_ HANDLE hToken, _Out_ PWSTR *UserName, _Out_ PWSTR *DomainName)
Retrieves the user and domain names corresponding to the given token.
Definition: wlntfytests.c:335
#define BEGIN_HANDLER
Definition: wlntfytests.c:922
#define END_TEST
Definition: wlntfytests.c:734
struct _SYSTEM_USER_INFO SYSTEM_USER_INFO
static const struct @1773 NotifyEvents[]
static DWORD DisplayWlxMessageA(_In_opt_ PFNMSGECALLBACK pStatusCallback, _In_ BOOL bVerbose, _In_ PCSTR pMessage)
Definition: wlntfytests.c:699
#define TOKEN_QUERY
Definition: setypes.h:940
@ TokenUser
Definition: setypes.h:978
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184