@@ -2838,6 +2838,132 @@ HotkeyThread(LPVOID Parameter)
28382838 return 0 ;
28392839}
28402840
2841+
2842+ static PCWSTR
2843+ GetLocalSetupDllPath (VOID )
2844+ {
2845+ static WCHAR SetupDllPath [MAX_PATH ] = L"" ;
2846+ static BOOL Init = FALSE;
2847+ BOOL Success ;
2848+ DWORD PathSize ;
2849+
2850+ /* Don't rebuild the path if we did it already */
2851+ if (Init )
2852+ return SetupDllPath ;
2853+ Init = TRUE;
2854+
2855+ /*
2856+ * Retrieve the full path of the current running Setup instance.
2857+ * From this we build the suitable path to the Setup DLL.
2858+ */
2859+ PathSize = GetModuleFileNameW (NULL , SetupDllPath , _countof (SetupDllPath ));
2860+ SetupDllPath [_countof (SetupDllPath ) - 1 ] = UNICODE_NULL ; // Ensure NULL-termination (see WinXP bug)
2861+
2862+ Success = ((PathSize != 0 ) && (PathSize < _countof (SetupDllPath )) &&
2863+ (GetLastError () != ERROR_INSUFFICIENT_BUFFER ));
2864+ if (Success )
2865+ {
2866+ /* Find the last path separator, remove it as well as the file name */
2867+ PWCHAR pch = wcsrchr (SetupDllPath , L'\\' );
2868+ if (!pch )
2869+ pch = SetupDllPath ;
2870+
2871+ /* The Setup DLL is inside the System32 sub-directory */
2872+ PathSize = _countof (SetupDllPath ) - (pch - SetupDllPath );
2873+ Success = SUCCEEDED (StringCchCopyW (pch , PathSize , L"\\system32" ));
2874+ }
2875+ if (!Success )
2876+ {
2877+ /* Failure: invalidate the path; the DLL won't be found and delay-loaded */
2878+ * SetupDllPath = UNICODE_NULL ;
2879+ }
2880+
2881+ return SetupDllPath ;
2882+ }
2883+
2884+ #ifndef DECLARE_UNICODE_STRING_SIZE
2885+ #define DECLARE_UNICODE_STRING_SIZE (_var , _size ) \
2886+ WCHAR _var ## _buffer[_size]; \
2887+ UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer }
2888+ #endif
2889+ #include <ndk/exfuncs.h> // For NtRaiseHardError()
2890+ #define DELAYIMP_INSECURE_WRITABLE_HOOKS
2891+ #include <delayimp.h>
2892+
2893+ /**
2894+ * @brief
2895+ * Controls the delay-loading of Setup DLLs from a suitable path.
2896+ *
2897+ * @see
2898+ * https://stackoverflow.com/a/75325443
2899+ * https://devblogs.microsoft.com/oldnewthing/20170126-00/?p=95265
2900+ **/
2901+ static FARPROC
2902+ WINAPI setupDelayHook (unsigned dliNotify , PDelayLoadInfo pdli )
2903+ {
2904+ static CHAR dllPath [MAX_PATH ];
2905+ static PCWSTR setupDllPath = NULL ;
2906+
2907+ switch (dliNotify )
2908+ {
2909+ case dliNotePreLoadLibrary :
2910+ {
2911+ // NOTE: Add any other needed setup-specific DLLs there.
2912+ if (_stricmp (pdli -> szDll , "setuplib.dll" ) == 0 )
2913+ {
2914+ if (!setupDllPath )
2915+ setupDllPath = GetLocalSetupDllPath ();
2916+ if (setupDllPath && * setupDllPath &&
2917+ SUCCEEDED (StringCchPrintfA (dllPath , _countof (dllPath ), "%S\\%s" ,
2918+ setupDllPath , pdli -> szDll )))
2919+ {
2920+ pdli -> szDll = dllPath ; /* Set szDll to the new path */
2921+ }
2922+ }
2923+ break ; /* Load the DLL using the modified path */
2924+ }
2925+
2926+ case dliFailLoadLib :
2927+ {
2928+ /*
2929+ * Library loading failed.
2930+ * Raise a hard error instead of the default
2931+ * exception, and "cleanly" kill the process.
2932+ */
2933+ ANSI_STRING DllPathA ;
2934+ DECLARE_UNICODE_STRING_SIZE (DllPathU , MAX_PATH );
2935+ ULONG_PTR Parameters [] = {(ULONG_PTR )& DllPathU };
2936+ ULONG Response ;
2937+
2938+ RtlInitAnsiString (& DllPathA , pdli -> szDll );
2939+ RtlAnsiStringToUnicodeString (& DllPathU , & DllPathA , FALSE);
2940+ NtRaiseHardError (STATUS_DLL_NOT_FOUND | HARDERROR_OVERRIDE_ERRORMODE ,
2941+ _countof (Parameters ),
2942+ 0x1 ,
2943+ Parameters ,
2944+ OptionOk ,
2945+ & Response );
2946+ ExitProcess (-1 );
2947+ break ;
2948+ }
2949+
2950+ default :
2951+ break ;
2952+ }
2953+
2954+ return NULL ;
2955+ }
2956+
2957+ /**
2958+ * @brief
2959+ * Custom delay-loading hooks for loading the Setup DLLs from a suitable path.
2960+ **/
2961+ // NOTE: MSVC 2015 Update 3 makes this a const variable.
2962+ // #if (_MSC_VER > 1900) || (_MSC_VER == 1900 && _MSC_FULL_VER >= 190024210) ...
2963+ /*ExternC*/ PfnDliHook __pfnDliNotifyHook2 = setupDelayHook ;
2964+ /*ExternC*/ PfnDliHook __pfnDliFailureHook2 = setupDelayHook ;
2965+
2966+
28412967int WINAPI
28422968_tWinMain (HINSTANCE hInst ,
28432969 HINSTANCE hPrevInstance ,
0 commit comments