Historical note:
Investigation shows that this functionality, introduced between builds
1902 and 1906 of Windows NT 5.0 (future 2000) Beta 3, has always been
"nop-ed" and has remained this way till Windows Server 2003.
The value read from the "SafeMode" registry value is unconditionally
overridden afterwards, causing the notification DLLs to always be loaded.
In ReactOS, this functionality is restored, and only the notifications
tagged as such are loaded in SafeMode.
Furthermore:
Analysis of strings in Win2000 and WinXP/2003 winlogon.exe, show that
the "Safe" registry value doesn't exist for notifications; instead,
it is named "SafeMode".
The "Safe" value appears only for the SensLogn (SENS Winlogon Event) handler
registry entry. My hypothesis is that the value name is a typo for the
"SafeMode" value. It has been introduced in the `\Winlogon\Notify\SensLogn`
registry entry for SensLogn around Windows NT 5.0 build 1946.
Analysis of strings in Win2000 and WinXP/2003 winlogon.exe, show that
the "Enabled" registry value doesn't exist for notifications.
This value is actually only used by the ScCertProp (Smart Card Certificate
Propagation) notifications, in wlnotify.dll, to enable or disable certificate
progagation.[^1]
Note that whatever the "Enabled" registry value is, the notification DLL
is still loaded within winlogon.exe.
We however keep the `bEnabled` internal flag, so as to be able to disable
at runtime notifications that could not be delay-loaded, or that behave
erratically, etc.
[WLNOTIFY] Add a comment about the "Enabled" value in scard.c!SCardStartCertProp()
[^1]: For more information, see:
https://www.microfocus.com/documentation/securelogin/9.0/administration_guide/blm54qb.html?view=printhttps://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/925884
Introduce and use a minimal testing framework (minitest.h) based on
an updated version of `wine/test.h`.
Each notification handler becomes its own test. Useful macro and
function helpers have been introduced to simplify the code that is
duplicated for each handler.
See commit 38d07d3a24 (PR #8234) for the details of how to install
and use the notification dll.
These tests can exercise the notifications in the four cases, where
asynchronous events and user impersonation can be independently
enabled or disabled. To do this, the `Asynchronous` and `Impersonate`
registry `REG_DWORD` values, inside the `WLNotifyTests` subkey of:
`HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify`
must be set to their intended values[^1].
----
[^1]: https://learn.microsoft.com/en-us/windows/win32/secauthn/registry-entries
----
Current test results:
- When each notification is emitted, the DLL is loaded then unloaded:
```
err:(modules\rostests\win32\winlogon\wlntfytests\wlntfytests.c:1307)
WLNOTIFY(ac.b0): Entering `DllMain`(hInst: 0x10000000, dwReason: 0x1, pReserved: 0x00000000)
...
err:(modules\rostests\win32\winlogon\wlntfytests\wlntfytests.c:1307)
WLNOTIFY(ac.b0): Entering `DllMain`(hInst: 0x10000000, dwReason: 0x0, pReserved: 0x00000000)
```
This doesn't happen on Windows. And indeed, it should _not_ happen,
because otherwise the DLL would loose any of its internal global state
between consecutive notification calls. This currently happens in
ReactOS, where we can observe the following:
```
modules\rostests\win32\winlogon\wlntfytests\wlntfytests.c:788: Test failed: **** WLEventLogon: ERROR: Wrong state NON-INITIALIZED, expected Startup or Logoff
...
err:(modules\rostests\win32\winlogon\wlntfytests\wlntfytests.c:1036) **** WLEventLogon: Changing state NON-INITIALIZED to Logon
```
and similar for every other notification.
- Test results for each notification:
```
WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped.
WLEventLogon: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventStartShell: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
-- Note: missing WLEventPostShell --
WLEventLock: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventUnlock: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventStartScreenSaver: 30 tests executed (0 marked as todo, 10 failures), 0 skipped.
WLEventStopScreenSaver: 30 tests executed (0 marked as todo, 9 failures), 0 skipped.
WLEventLogoff: 30 tests executed (0 marked as todo, 5 failures), 2 skipped.
WLEventShutdown: 31 tests executed (0 marked as todo, 5 failures), 0 skipped.
```
Add a `wlntfytests.dll` in `ReactOS\bin\suppl`, containing tests for Winlogon notifications.
To use it:
- Register the dll with `regsvr32 <path_to>\wlntfytests.dll` and reboot
the machine.
- With a debugger, observe the traces emitted by the dll, whenever any
Winlogon notification is emitted. If Winlogon debugging is enabled,
a debug-break is made everytime a notification is invoked.
- Once testing is done, unregister the dll with `regsvr32 /u <path_to>\wlntfytests.dll`
and reboot the machine.
For each received notification, the handlers dump the contents of the
`WLX_NOTIFICATION_INFO` structure, and verify that the notifications
are received in the correct expected order. This is done by keeping
what the previous received notification was, before comparing it with
the expected one(s) that must precede the new notification being received.
References:
- https://learn.microsoft.com/en-us/windows/win32/secauthn/creating-a-winlogon-notification-package
- https://learn.microsoft.com/en-us/windows/win32/secauthn/winlogon-notification-events
- https://rsdn.org/article/baseserv/winlogon.xml
URLs are getting old. We have to
update URLs for documentation
purpose.
JIRA issue: CORE-19963
- Refresh old URLs.
- Add " (DEAD_LINK)" labels
to dead links.
- Use MS Learn links rather
than MSDN ones.
- Some dead links revived by
Web Archive.
- Don't change Wine Tests
and Wine Sync.
- Don't change 3rd party libraries.
- Don't append "redirected" labels.
Tests adapted from https://stackoverflow.com/q/31987023/13530036
and from https://stackoverflow.com/a/38938416/13530036 .
- Test when CALL with a label containing /? actually calls GOTO's help,
and test when CALL's help is displayed instead.
- Test when CALL with a label containing /?, but specified by variables,
do NOT trigger GOTO's or CALL's help.
- Test the effect of the presence of escape carets in CALL label string.
- Test that CALL indeed supports double delayed expansion. Adapted from
https://stackoverflow.com/a/31990563/13530036 .
- Tests for GOTO across IF parenthesized block (parser test with line
continuation at closing parenthesis).
- Tests for showing how FOR-loops stop when a GOTO is encountered.
- Tests for EXIT command within IF block.
There is no need to compile our DLLs as shared libraries since we are
managing symbols exports and imports through spec files.
On my system, this reduces the configure-time by a factor of two.
Add a test program that shows how the *PSMTextOut() functions draw
the strings by a side by side comparison between LpkPSMTextOut() and
UserLpkPSMTextOut().
Add code that demonstrates the use of the lpOrder and lpCaretPos struct members of GCP_RESULTS w/ and w/o GCP_REORDER flag.
Changed demo string literals to arrays containing character unicode values.
Introduce BiDi (bi-directional text) support for ExtTextOut and GetCharacterPlacement, using Wine's GDI BIDI_Reorder function.
Solves the main issue with CORE-7003.
To be compatible with Win2k3+, introduce the "Language Pack" (LPK) dll.
- All the bidi code is removed from gdi32 and replaced by calls to LPK.
Gdi32 uses dynamic linking to lpk.dll. In case of linking failure no bidi processing will be available.
- Implemented LpkGetCharacterPlacement.
- Implement LpkExtTextOut.
- Add a demo test program to show how the apis should function.
- Added all the remaining code, added special case for lpDx calculation if also GCP_GLYPHSHAPE flag was called.
Applications that call GCP that use GCP_GLYPHSHAPE flags should also use the GCP_REORDER flag.
(As written in https://msdn.microsoft.com/en-us/library/windows/desktop/dd144860(v=vs.85).aspx )
- Add ETO_RTLREADING flag handling.
Imported the ETO_RTLREADING flag handling from wine, which changes the string part order (runs).
A RRR1LLLRRR2 string without will show as RRR1LLLRRR2 without it, with it RRR2LLLRRR1.
Indeed, rosautotest has an annoying tendency to fail with:
Invalid test file name: <testname>.exe
SYSREG_ROSAUTOTEST_FAILURE
when <testname>.exe is a test that do not comply with the rosautotest
interface.
This is indeed the case for all the tests under /rostests/win32/, with the
exception of cmd_rostest.
Addendum to 8dd89c7.
CORE-7998
Based on Wine's cmd_winetest code, this first bunch of tests check how the
"for" command should process the newlines inside its parenthesed set.
Adapted by Doug Lyons.