Also, capture in `CallNotificationDll()` the notify info structure template
before invoking each DLL handler: a malicious caller might modify its contents,
and so we need to re-initialize its contents for each call.
Test results:
- Test 1: `Asynchronous: FALSE, Impersonation: FALSE`
Before & After the fix, give the same results:
```
WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped.
WLEventLogon: 30 tests executed (0 marked as todo, 3 failures), 2 skipped.
WLEventStartShell: 30 tests executed (0 marked as todo, 3 failures), 2 skipped.
(NOTE: WLEventPostShell isn't yet implemented in ReactOS)
WLEventLock: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventUnlock: 30 tests executed (0 marked as todo, 3 failures), 2 skipped.
WLEventStartScreenSaver: 30 tests executed (0 marked as todo, 9 failures), 2 skipped.
WLEventStopScreenSaver: 30 tests executed (0 marked as todo, 7 failures), 2 skipped.
WLEventLogoff: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped.
```
* The current notification thread doesn't impersonate any user, the
dumped thread token shows:
`Thread Token : 0x00000000 - User: '(null)\(null)'`
(except for `WLEventStartScreenSaver` and `WLEventStopScreenSaver`
which currently in ReactOS, impersonate the logged user and shows e.g.,
`Thread Token : 0x00000250 - User: 'MYCOMPUTERNAME\Administrator' ).
- Test 2: `Asynchronous: FALSE, Impersonation: TRUE`
Before the fix:
```
WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped.
WLEventLogon: 29 tests executed (0 marked as todo, 8 failures), 4 skipped.
WLEventStartShell: 29 tests executed (0 marked as todo, 8 failures), 4 skipped.
(NOTE: WLEventPostShell isn't yet implemented in ReactOS)
WLEventLock: 29 tests executed (0 marked as todo, 9 failures), 4 skipped.
WLEventUnlock: 29 tests executed (0 marked as todo, 8 failures), 4 skipped.
WLEventStartScreenSaver: 32 tests executed (0 marked as todo, 6 failures), 2 skipped.
WLEventStopScreenSaver: 32 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventLogoff: 30 tests executed (0 marked as todo, 7 failures), 4 skipped.
WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped.
```
* There are more failures (and skipped tests), because in impersonation
mode, the tests expect that the current thread is impersonating the
logged-on user, and validate whether this impersonated user matches
what the WLX notification `Domain` and `UserName` information structure
members are. However, these two fields aren't set yet, and the thread
isn't impersonating any user yet.
* The dumped thread token shows the same information as in Test 1.
- Test 3: `Asynchronous: FALSE, Impersonation: TRUE`
After the fix:
```
WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped.
WLEventLogon: 31 tests executed (0 marked as todo, 5 failures), 2 skipped.
WLEventStartShell: 31 tests executed (0 marked as todo, 5 failures), 2 skipped.
(NOTE: WLEventPostShell isn't yet implemented in ReactOS)
WLEventLock: 31 tests executed (0 marked as todo, 6 failures), 2 skipped.
WLEventUnlock: 31 tests executed (0 marked as todo, 5 failures), 2 skipped.
WLEventStartScreenSaver: 32 tests executed (0 marked as todo, 6 failures), 2 skipped.
WLEventStopScreenSaver: 32 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventLogoff: 32 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped.
```
* There are now less skipped tests than in Test 2, as much as in Test 1.
* There are also less failed tests than in Test 2; however, there are
few more failed tests than in Test 1, but this is balanced by new
tests being executed.
The reason is that now, compared to Test 2 in impersonation mode, the
current thread is correctly impersonating the logged-on user, if any.
However, the WLX notification `Domain` and `UserName` information
structure members still aren't set yet, thus some of the tests fail.
* The dumped thread token for all notifications now show e.g.,
`Thread Token : 0x00000360 - User: 'MYCOMPUTERNAME\Administrator'`
(`WLEventStartup`, `WLEventShutdown` don't show any, since no user
is logged-in at these stages.)
And retrieve all its exported notification handlers.
This reverts parts of commit 5d4f69bf35.
Because notification DLLs can keep internal state between successive
notifications, they are kept loaded until Winlogon termination.
The SFC notification DLL is also loaded. Because sfc.dll redirects to
sfc_os.dll, the latter is then automatically loaded. This allows doing
what commit 88ee639b06 (r68615) was aiming at, in a less hackish manner.
CORE-9598
Test results:
- Before:
We observe the repeated loading/unloading of the DLL at each
notification call:
```
WLNOTIFY(ac.b0): Entering `DllMain`(hInst: 0x10000000, dwReason: 0x1, pReserved: 0x00000000)
...
WLNOTIFY(ac.b0): Entering `DllMain`(hInst: 0x10000000, dwReason: 0x0, pReserved: 0x00000000)
```
The global state of the notification DLL is lost between each
notification, and such testing errors happen:
```
modules\rostests\win32\winlogon\wlntfytests\wlntfytests.c:786: Test failed: **** WLEventLogon: ERROR: Wrong state NON-INITIALIZED, expected Startup or Logoff
err:(modules\rostests\win32\winlogon\wlntfytests\wlntfytests.c:1034) **** WLEventLogon: Changing state NON-INITIALIZED to Logon
```
The previous notification state is always reset to `NON-INITIALIZED` (its initial value).
Test results for all the notifications:
```
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: WLEventPostShell isn't yet implemented in ReactOS)
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.
```
- After:
The DLL is loaded only once, at the first notification, then stays
loaded for the whole life of winlogon.exe:
```
WLNOTIFY(ac.b0): Entering `DllMain`(hInst: 0x10000000, dwReason: 0x1, pReserved: 0x00000000)
```
and the global state of the notification DLL is now kept between each
notification, there are no `ERROR: Wrong state NON-INITIALIZED, expected ...`
errors anymore.
Test results for all the notifications:
```
WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped.
WLEventLogon: 30 tests executed (0 marked as todo, 3 failures), 2 skipped.
WLEventStartShell: 30 tests executed (0 marked as todo, 3 failures), 2 skipped.
(NOTE: WLEventPostShell isn't yet implemented in ReactOS)
WLEventLock: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventUnlock: 30 tests executed (0 marked as todo, 3 failures), 2 skipped.
WLEventStartScreenSaver: 30 tests executed (0 marked as todo, 9 failures), 2 skipped.
WLEventStopScreenSaver: 30 tests executed (0 marked as todo, 7 failures), 2 skipped.
WLEventLogoff: 30 tests executed (0 marked as todo, 4 failures), 2 skipped.
WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped.
```
Split Windows Server 2003 and Windows Vista behaviour in two different cases and make them used separately: when ReactOS target version is NT 5.2, use the 1st case, otherwise use the 2nd one instead.
Also, handle NdisPhysicalMediumNative802_11 case only for NT 6.0 and newer, since that's actually supported starting from NDIS 6.0, according to MSDN:
https://learn.microsoft.com/en-us/windows-hardware/drivers/network/oid-gen-physical-medium
while for NDIS 5.1 and newer it's:
https://learn.microsoft.com/en-us/previous-versions/windows/hardware/network/ff560255(v=vs.85)
This fixes:
1. A critical regression with unavailable networking in ReactOS when 3rd-party NT5-compatible Ethernet/Wi-Fi drivers are used (both in VM and on real hardware) caused by commit 3842b59f75 from @EricKohl.
2. Failure to open Network Properties and Network Status from the Network tray icon (caused by the same commit too).
MSDN tells us this is done so for Windows XP and Server 2003 as well, and IF_TYPE_IEEE80211 is returned only in Windows Vista and newer, so the following Microsoft documentation is actually correct in this case:
https://learn.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_info
(see the information about "IP_ADAPTER_INFO.Type" member below on that page)
!!!Please note that the behaviour of Vista+ case (e. g., when compiling ReactOS targeted as NT 6.0 and newer) remains unchanged after this fix (networking still may not work), so it still requires the proper support of 3rd-party NT6+ compatible network miniport drivers (by handling this case via the Vista/NDIS6-style way) for NT6 target!!!
CORE-20244
Expand the "DllName" notification DLL path string, independently of
whether it is REG_SZ or REG_EXPAND_SZ, before loading it, similarly
to Windows' winlogon.exe.
Validate also the type/size of the retrieved registry value.
Use a KSEMAPHORE instead of a NotificationEvent to signal availability. This is to prevent satisfying the wait for multiple waiters, when only a single entry is on the list.
Fixes crashes on SMP builds.
IpReleaseAddress: Use DhcpReleaseParameters instead of DhcpReleaseIpAddressLease.
IpRenewAddress: Use DhcpAcquireParameters instead of DhcpRenewIpAddressLease.
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
Fix the shell32 apitests so that they pass on Windows Server 2003 - Windows 10. Many of these fixes are for Vista+, but the most important fixes are for ShellExecCmdLine and FindExecutable which had issues closing windows after tests and deleting test files. Failing to delete these files breaks the other test (i.e. running ShellExecCmdLine would break FindExecutable and vis-versa.)