This commit is contained in:
Vichingo455 2025-03-23 15:26:15 +01:00
parent cacf40b6cd
commit ad8366918e
72 changed files with 10255 additions and 2 deletions

10
.editorconfig Normal file
View File

@ -0,0 +1,10 @@
# http://editorconfig.org
root = true
[*]
indent_style = tab
tab_width = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

3
.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
* text=auto eol=lf
*.sln eol=crlf
*.vcxproj eol=crlf

122
.gitignore vendored Normal file
View File

@ -0,0 +1,122 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
*.userprefs
# Build results
Debug/
Debug-VC08/
Debug-VC17/
Release/
*.exe
*.dll
!setup/modern_aerowizard.exe
!setup/x86-unicode/*.dll
setup/x86-unicode/LegacyUpdateNSIS.dll
obj/
*_layout.inf
# Visual Studio 2015/2017 cache/options directory
.vs/
# Visual Studio 2017 auto generated files
Generated\ Files/
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*idl.h
*.i
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp

View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/.idea.LegacyUpdate.iml
/modules.xml
/contentModel.xml
/projectSettingsUpdater.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT" />
<option name="description" value="" />
</component>
</project>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" fill="none"><image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAnYSURBVHgBlVdpbFzVFf7u22cfL7HHjkkcQpzYhCw1JBC3bGFLQA1QEK2gLCq/oD+qFlUtQkUt+dNWVZHKnwJCatUWaBGpWhFUmoaWCkJShyROYiBx4gTHdsbL7Ntbb899b8axnQbRJx+/O/Pm3vPd73zn3PMYPv+SOjo6jO7tqzv7H93yoB4zBtSQ1ispUlc6uwY7OtahS+0s9oStidcOTB784a5T+6Z/dcfueDyeKxQKZZpvkfHPc8Au5bi7u1vrevbZWweuPf8DWZO3NB5M5jtxMr0aUaOIzsQE3jq6Aw+sVPHUOg33vWlhbLKc5vn8geqBV57P7915pL+/vzA4OOgwxvgXAnD//ffLe4z+pR23bv3RLf2D3xKOGtdsuQWHPrsGpVocd2/4IyxXJ9N8ELIVp/1KKBZpSZOBlWpp8/QHL5feuOcV0zTP0/QambfYn7zY+XurHu+V+7+6a0vPx7enkhML+AurFaxoOYkQ3ePaLCTmYCTdg0Q4B5MzZMpxcHLBhElaVIlffr3Sva3bPvabIc/zKrSEjUUhkeaP96x6pBerNu9e0Tx75UD7aSQIn9YgiXOMj2zCuRNXI6WfgV2zYVctxNXzKJRDSMXPQVVrYDIPtiVxGjNoHet3JB7a/zx9s6q5uTm6yOccA8JLLPHYC28viZhXPNn7b0QVJ/BLjxxy7pFxz0KNKHZqFSRUF6ViKw6dXYnR6ctxvriU+FXBOK3v1sn2aFmXwmG0dOvLt3WWDr900HXdYp2JCwD6+vo09swHz7FwYsfdy45hc9OU/1Cs4RIEm3g1bQEoA1X6DKpbwgO9j6NVvRq7BkuwXfIoyUQ7LUcAmCeM+QAYFyCIFaO9x3H5uDxz4JTjOKVGKAQdbHL7T9awZOq74ov+SAUGfU17gUqTBaNwPLiWC6toopIpY/vKO2HI7VjZEsETm9vhFmeBagHcrlGknEAEUmN1cScgZJF1T3yHJ9f2JZPJ2HwNaMoVA0+jDmm8ZsCp68Sju+N6sEwbZqmGaq6MaztvwNLkdeQoCOUdVy7FIxvb4JYy8KpFcCcAwQV/lHlcZB+rA9GircamHz+Wy+WW0CdFzFeS9+5MSUp4e0MII6UmdCVCCOkFVD0Xe06ux7GxJGza5bYVKWztW4ayiQXXowM9KBFDb36cAY/QunI9FHUaLoBgUNquuZNGL5KJOBckdfVtNzNXifkxo2vCMrA3vRwFz0beNPHR2RQKGRspRceTN/WhZhsLnDdy6ts39WJdCzkrZYmJMjFhkWhdiPpDRahuQnVaOLzx+9fTKCkgSXL8sm1w6IkTrDY424lZW8KMVcPwVIxUX0GXnsPPv9ZLsbL8ChjSynMA5leynTs2ok2ugldz4CalPW1CgOAigzifmyF33DCgqqoAoEiM61cxm5YhYy5R5nk4PtWB0wVRA05jS/sQXnxwNVKJMCxHQ77SRBlhIB7KIRnOEqgL8YjqKn75wJcQsgrEQh6eSWBc2hn3FnAmhTqX27bdRB9UiXn6UkYM+GYRXTZHrqziT/u34cPja/HULQPobDKgU5Fp7NzjMgrVJHIExnL0BSERQJ+750qgkvdZ4I7pg2B1BsSNGckWWZYTQpYSc9WYv3uq48xiNIlAmESbZeKuvhuRCF1BtT9GmeRCZt5F8WfsovKODcub8cTNy4lVcu7YPqsiBJ7HAy2qiSQVpFA0GlUUbgciCXYGXzScBo+sb8d969v8702HUtNTEKP460qV6oqMsFaBLLn+go4XFNRSNUZOgvG9m5aibOn43T4SoyiNVJxETri+D9+fUiqVJMWtViYVFu4Q4pAoEzxKobiq0QQFv90/SWAEhaZfZHraw9i6oYuKkAlVnqumNPZwaGQI49kpcDkM022iY3k1OdJJFzKKNeZT74uRNuc5FZNCwIkFrni16oSrGB2SyFtFlFAFZUfF7w/WiBESEVVNz6ICU83itjXNGOhb5e9+8XV87DiOpIdhUA3RojreOpiC41CYuUqOme+Yi+3Tn1fL5sh5lRoXR/KqhWGPiogwTpuSHIWyQRTjMCQpAUltJWuBpCQpaUmMColRL18EQDFUGMkQwk1hhJJh3HvfX3DN5kEsWzFOTmVyDt984ZTPTdL/oqZptuSeP/R3bnuUsoG5AoRLILwQnagRAhKlWMeJzog4HaCRRsQ5sbiTkRQZCqWhGtGhRTSE4xxrN3yMrXf8DR2dE/7JJhgQYbAn9x6lOpCdmZmxpdzub7znmXbRswgAGbfEwUNxskRtEGxQR0AhkcSdgLnEkOBHWwRCHDayKkGmMEqkI0mEUw4OoenJFoq754fBF/XIG4epDmRpaAth5p3ZT1/1AVD6iVPPNQMgghm/rRQ/81mRUbE0OLZGACQ6TdgCAEwKjj82D9m+d7fArKhB/MVSU/uPsMrZERrmRFKIGeXKf3a+xE2r3ADBbddnQwDxWRGCdyT/gBFUpksRAqH6IOR5IZDJxK4bVzEfw9CBtbR7jkZLah3auVuSpDHh158nlrbHdo+6M4dfFih9HfiORTGqA7FFEVEpK3S/lNlUNc/lYhQOclpngTpn3wQTDQo+PdrjUy8KjPBvj+56z536cJDoFyK0fObEP9ERDQ8Pr0h8/cTrktG6HnVokizi6BNHZNUQUasIy9T3OVUIWh7/8jFIS2aRNjzYGoE0OLSQhmymDe/vuQ7jo6mgSSUv3KIu4A+XP0PKf3fZsmWnRkZG/EPEX356elokiEkCGJFTA7cwSY0KyEHueoGCKZfFzsumRGe/irKt48Y1aegtJczqNjyd+VkgBLjnzzeT845AG4HzfOkfD73glcf+Rfl/OpPJzBWS+W25684cnJadwlG5/Ss3MUmJzj0RfZ0ffzrv/UaGQkFV7s6NUwinTGR1D0xTqA+RcOLoGhyhuDeUwM1cvvLPh1+wz7//Dn38REgD894P5gPww2RPf5R20vveV5p6l0jhjlUX+ikRWwLBFH8aYypu3zgBvbWEDJXiQjGGV37xMEZPdM85d8bfGazs/eaveX74XXov+KSh/Hk+F76Y1EFYRNWsN/rqQWf68BBruapLMlpSwUMWZD/xGjUcfO+uY6jQKTky1oa3/no9KqWwv4hXOHW2euinr1cOPP2aZ+U+JOci7fKLnYtLwcWX+FGRlHoSY29nzLG3j+iXbVsvX3b7JrVtcz+0ZCvTE00rUiVDVESjxs1P9rdX00Mnzrj50XFz6GcfOMWzJ2mNs2QT9I45c+bMGROXeEm91MvpfIZEEyja6KSiKM1USkUjESMxqbIIOm2YxiKlSvQ8Tz1/NhKJZMrlsoj1/3wf/H8ANK5Gl19XIAIhBPN5LBZzybmTzWb9uomARf5FFv4vtN/QnyTNBIYAAAAASUVORK5CYII=" width="32" height="32"/></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders>
<Path>.</Path>
</attachedFolders>
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

37
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,37 @@
{
"configurations": [
{
"name": "MinGW",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/shared"
],
"compilerPath": "/usr/bin/i686-w64-mingw32-g++",
"cStandard": "c17",
"cppStandard": "c++11",
"intelliSenseMode": "windows-gcc-x86",
"compilerArgs": [
"-std=c++11",
"-mwindows",
"-municode",
"-s",
"-fPIE",
"-ffunction-sections",
"-fdata-sections",
"-fno-unwind-tables",
"-fno-asynchronous-unwind-tables",
"-fno-exceptions",
"-fno-rtti",
"-flto",
"-Wno-write-strings",
"-include stdafx.h"
],
"defines": [
"UNICODE",
"_UNICODE",
"_USRDLL"
]
}
],
"version": 4
}

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"files.associations": {
"*.rc": "cpp",
"*.idl": "cpp"
}
}

8
.vsconfig Normal file
View File

@ -0,0 +1,8 @@
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"Microsoft.VisualStudio.Component.WinXP",
"Microsoft.VisualStudio.Component.VC.v141.ATL"
]
}

View File

@ -0,0 +1,650 @@
#pragma once
#include <wuapi.h>
// Copied from wuapi.h in Windows SDK 10.0.19041.0
#ifndef __IUpdateInstaller3_FWD_DEFINED__
#define __IUpdateInstaller3_FWD_DEFINED__
typedef interface IUpdateInstaller3 IUpdateInstaller3;
#endif /* __IUpdateInstaller3_FWD_DEFINED__ */
#ifndef __IUpdateInstaller4_FWD_DEFINED__
#define __IUpdateInstaller4_FWD_DEFINED__
typedef interface IUpdateInstaller4 IUpdateInstaller4;
#endif /* __IUpdateInstaller4_FWD_DEFINED__ */
// {16d11c35-099a-48d0-8338-5fae64047f8e}
DEFINE_GUID(IID_IUpdateInstaller3,0x16d11c35,0x099a,0x48d0,0x83,0x38,0x5f,0xae,0x64,0x04,0x7f,0x8e);
// {EF8208EA-2304-492D-9109-23813B0958E1}
DEFINE_GUID(IID_IUpdateInstaller4, 0xef8208ea, 0x2304, 0x492d, 0x91, 0x9, 0x23, 0x81, 0x3b, 0x9, 0x58, 0xe1);
#ifndef __IUpdateInstaller3_INTERFACE_DEFINED__
#define __IUpdateInstaller3_INTERFACE_DEFINED__
/* interface IUpdateInstaller3 */
/* [hidden][unique][uuid][nonextensible][dual][oleautomation][object][helpstring] */
EXTERN_C const IID IID_IUpdateInstaller3;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("16d11c35-099a-48d0-8338-5fae64047f8e")
IUpdateInstaller3 : public IUpdateInstaller2
{
public:
virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AttemptCloseAppsIfNecessary(
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval) = 0;
virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AttemptCloseAppsIfNecessary(
/* [in] */ VARIANT_BOOL value) = 0;
};
#else /* C style interface */
typedef struct IUpdateInstaller3Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
__RPC__in IUpdateInstaller3 * This);
ULONG ( STDMETHODCALLTYPE *Release )(
__RPC__in IUpdateInstaller3 * This);
HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )(
__RPC__in IUpdateInstaller3 * This,
/* [out] */ __RPC__out UINT *pctinfo);
HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo);
HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in REFIID riid,
/* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
/* [range][in] */ __RPC__in_range(0,16384) UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )(
IUpdateInstaller3 * This,
/* [annotation][in] */
_In_ DISPID dispIdMember,
/* [annotation][in] */
_In_ REFIID riid,
/* [annotation][in] */
_In_ LCID lcid,
/* [annotation][in] */
_In_ WORD wFlags,
/* [annotation][out][in] */
_In_ DISPPARAMS *pDispParams,
/* [annotation][out] */
_Out_opt_ VARIANT *pVarResult,
/* [annotation][out] */
_Out_opt_ EXCEPINFO *pExcepInfo,
/* [annotation][out] */
_Out_opt_ UINT *puArgErr);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ClientApplicationID )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__deref_out_opt BSTR *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ClientApplicationID )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in BSTR value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_IsForced )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_IsForced )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ VARIANT_BOOL value);
/* [helpstring][restricted][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ParentHwnd )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__deref_out_opt HWND *retval);
/* [helpstring][restricted][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ParentHwnd )(
__RPC__in IUpdateInstaller3 * This,
/* [unique][in] */ __RPC__in_opt HWND value);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ParentWindow )(
__RPC__in IUpdateInstaller3 * This,
/* [unique][in] */ __RPC__in_opt IUnknown *value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ParentWindow )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__deref_out_opt IUnknown **retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Updates )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__deref_out_opt IUpdateCollection **retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Updates )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in_opt IUpdateCollection *value);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *BeginInstall )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in_opt IUnknown *onProgressChanged,
/* [in] */ __RPC__in_opt IUnknown *onCompleted,
/* [in] */ VARIANT state,
/* [retval][out] */ __RPC__deref_out_opt IInstallationJob **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *BeginUninstall )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in_opt IUnknown *onProgressChanged,
/* [in] */ __RPC__in_opt IUnknown *onCompleted,
/* [in] */ VARIANT state,
/* [retval][out] */ __RPC__deref_out_opt IInstallationJob **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *EndInstall )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in_opt IInstallationJob *value,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *EndUninstall )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ __RPC__in_opt IInstallationJob *value,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Install )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *RunWizard )(
__RPC__in IUpdateInstaller3 * This,
/* [defaultvalue][unique][in] */ __RPC__in_opt BSTR dialogTitle,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_IsBusy )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Uninstall )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AllowSourcePrompts )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AllowSourcePrompts )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ VARIANT_BOOL value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_RebootRequiredBeforeInstallation )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ForceQuiet )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ForceQuiet )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ VARIANT_BOOL value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AttemptCloseAppsIfNecessary )(
__RPC__in IUpdateInstaller3 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AttemptCloseAppsIfNecessary )(
__RPC__in IUpdateInstaller3 * This,
/* [in] */ VARIANT_BOOL value);
END_INTERFACE
} IUpdateInstaller3Vtbl;
interface IUpdateInstaller3
{
CONST_VTBL struct IUpdateInstaller3Vtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IUpdateInstaller3_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IUpdateInstaller3_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IUpdateInstaller3_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IUpdateInstaller3_GetTypeInfoCount(This,pctinfo) \
( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) )
#define IUpdateInstaller3_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) )
#define IUpdateInstaller3_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) )
#define IUpdateInstaller3_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) )
#define IUpdateInstaller3_get_ClientApplicationID(This,retval) \
( (This)->lpVtbl -> get_ClientApplicationID(This,retval) )
#define IUpdateInstaller3_put_ClientApplicationID(This,value) \
( (This)->lpVtbl -> put_ClientApplicationID(This,value) )
#define IUpdateInstaller3_get_IsForced(This,retval) \
( (This)->lpVtbl -> get_IsForced(This,retval) )
#define IUpdateInstaller3_put_IsForced(This,value) \
( (This)->lpVtbl -> put_IsForced(This,value) )
#define IUpdateInstaller3_get_ParentHwnd(This,retval) \
( (This)->lpVtbl -> get_ParentHwnd(This,retval) )
#define IUpdateInstaller3_put_ParentHwnd(This,value) \
( (This)->lpVtbl -> put_ParentHwnd(This,value) )
#define IUpdateInstaller3_put_ParentWindow(This,value) \
( (This)->lpVtbl -> put_ParentWindow(This,value) )
#define IUpdateInstaller3_get_ParentWindow(This,retval) \
( (This)->lpVtbl -> get_ParentWindow(This,retval) )
#define IUpdateInstaller3_get_Updates(This,retval) \
( (This)->lpVtbl -> get_Updates(This,retval) )
#define IUpdateInstaller3_put_Updates(This,value) \
( (This)->lpVtbl -> put_Updates(This,value) )
#define IUpdateInstaller3_BeginInstall(This,onProgressChanged,onCompleted,state,retval) \
( (This)->lpVtbl -> BeginInstall(This,onProgressChanged,onCompleted,state,retval) )
#define IUpdateInstaller3_BeginUninstall(This,onProgressChanged,onCompleted,state,retval) \
( (This)->lpVtbl -> BeginUninstall(This,onProgressChanged,onCompleted,state,retval) )
#define IUpdateInstaller3_EndInstall(This,value,retval) \
( (This)->lpVtbl -> EndInstall(This,value,retval) )
#define IUpdateInstaller3_EndUninstall(This,value,retval) \
( (This)->lpVtbl -> EndUninstall(This,value,retval) )
#define IUpdateInstaller3_Install(This,retval) \
( (This)->lpVtbl -> Install(This,retval) )
#define IUpdateInstaller3_RunWizard(This,dialogTitle,retval) \
( (This)->lpVtbl -> RunWizard(This,dialogTitle,retval) )
#define IUpdateInstaller3_get_IsBusy(This,retval) \
( (This)->lpVtbl -> get_IsBusy(This,retval) )
#define IUpdateInstaller3_Uninstall(This,retval) \
( (This)->lpVtbl -> Uninstall(This,retval) )
#define IUpdateInstaller3_get_AllowSourcePrompts(This,retval) \
( (This)->lpVtbl -> get_AllowSourcePrompts(This,retval) )
#define IUpdateInstaller3_put_AllowSourcePrompts(This,value) \
( (This)->lpVtbl -> put_AllowSourcePrompts(This,value) )
#define IUpdateInstaller3_get_RebootRequiredBeforeInstallation(This,retval) \
( (This)->lpVtbl -> get_RebootRequiredBeforeInstallation(This,retval) )
#define IUpdateInstaller3_get_ForceQuiet(This,retval) \
( (This)->lpVtbl -> get_ForceQuiet(This,retval) )
#define IUpdateInstaller3_put_ForceQuiet(This,value) \
( (This)->lpVtbl -> put_ForceQuiet(This,value) )
#define IUpdateInstaller3_get_AttemptCloseAppsIfNecessary(This,retval) \
( (This)->lpVtbl -> get_AttemptCloseAppsIfNecessary(This,retval) )
#define IUpdateInstaller3_put_AttemptCloseAppsIfNecessary(This,value) \
( (This)->lpVtbl -> put_AttemptCloseAppsIfNecessary(This,value) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IUpdateInstaller3_INTERFACE_DEFINED__ */
#ifndef __IUpdateInstaller4_INTERFACE_DEFINED__
#define __IUpdateInstaller4_INTERFACE_DEFINED__
/* interface IUpdateInstaller4 */
/* [hidden][unique][uuid][nonextensible][dual][oleautomation][object][helpstring] */
EXTERN_C const IID IID_IUpdateInstaller4;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("EF8208EA-2304-492D-9109-23813B0958E1")
IUpdateInstaller4 : public IUpdateInstaller3
{
public:
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Commit(
/* [in] */ DWORD dwFlags) = 0;
};
#else /* C style interface */
typedef struct IUpdateInstaller4Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
__RPC__in IUpdateInstaller4 * This);
ULONG ( STDMETHODCALLTYPE *Release )(
__RPC__in IUpdateInstaller4 * This);
HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )(
__RPC__in IUpdateInstaller4 * This,
/* [out] */ __RPC__out UINT *pctinfo);
HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo);
HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in REFIID riid,
/* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
/* [range][in] */ __RPC__in_range(0,16384) UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )(
IUpdateInstaller4 * This,
/* [annotation][in] */
_In_ DISPID dispIdMember,
/* [annotation][in] */
_In_ REFIID riid,
/* [annotation][in] */
_In_ LCID lcid,
/* [annotation][in] */
_In_ WORD wFlags,
/* [annotation][out][in] */
_In_ DISPPARAMS *pDispParams,
/* [annotation][out] */
_Out_opt_ VARIANT *pVarResult,
/* [annotation][out] */
_Out_opt_ EXCEPINFO *pExcepInfo,
/* [annotation][out] */
_Out_opt_ UINT *puArgErr);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ClientApplicationID )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__deref_out_opt BSTR *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ClientApplicationID )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in BSTR value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_IsForced )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_IsForced )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ VARIANT_BOOL value);
/* [helpstring][restricted][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ParentHwnd )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__deref_out_opt HWND *retval);
/* [helpstring][restricted][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ParentHwnd )(
__RPC__in IUpdateInstaller4 * This,
/* [unique][in] */ __RPC__in_opt HWND value);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ParentWindow )(
__RPC__in IUpdateInstaller4 * This,
/* [unique][in] */ __RPC__in_opt IUnknown *value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ParentWindow )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__deref_out_opt IUnknown **retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_Updates )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__deref_out_opt IUpdateCollection **retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_Updates )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in_opt IUpdateCollection *value);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *BeginInstall )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in_opt IUnknown *onProgressChanged,
/* [in] */ __RPC__in_opt IUnknown *onCompleted,
/* [in] */ VARIANT state,
/* [retval][out] */ __RPC__deref_out_opt IInstallationJob **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *BeginUninstall )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in_opt IUnknown *onProgressChanged,
/* [in] */ __RPC__in_opt IUnknown *onCompleted,
/* [in] */ VARIANT state,
/* [retval][out] */ __RPC__deref_out_opt IInstallationJob **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *EndInstall )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in_opt IInstallationJob *value,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *EndUninstall )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ __RPC__in_opt IInstallationJob *value,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Install )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *RunWizard )(
__RPC__in IUpdateInstaller4 * This,
/* [defaultvalue][unique][in] */ __RPC__in_opt BSTR dialogTitle,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_IsBusy )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Uninstall )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__deref_out_opt IInstallationResult **retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AllowSourcePrompts )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AllowSourcePrompts )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ VARIANT_BOOL value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_RebootRequiredBeforeInstallation )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_ForceQuiet )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_ForceQuiet )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ VARIANT_BOOL value);
/* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_AttemptCloseAppsIfNecessary )(
__RPC__in IUpdateInstaller4 * This,
/* [retval][out] */ __RPC__out VARIANT_BOOL *retval);
/* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_AttemptCloseAppsIfNecessary )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ VARIANT_BOOL value);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Commit )(
__RPC__in IUpdateInstaller4 * This,
/* [in] */ DWORD dwFlags);
END_INTERFACE
} IUpdateInstaller4Vtbl;
interface IUpdateInstaller4
{
CONST_VTBL struct IUpdateInstaller4Vtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IUpdateInstaller4_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IUpdateInstaller4_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IUpdateInstaller4_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IUpdateInstaller4_GetTypeInfoCount(This,pctinfo) \
( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) )
#define IUpdateInstaller4_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) )
#define IUpdateInstaller4_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) )
#define IUpdateInstaller4_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) )
#define IUpdateInstaller4_get_ClientApplicationID(This,retval) \
( (This)->lpVtbl -> get_ClientApplicationID(This,retval) )
#define IUpdateInstaller4_put_ClientApplicationID(This,value) \
( (This)->lpVtbl -> put_ClientApplicationID(This,value) )
#define IUpdateInstaller4_get_IsForced(This,retval) \
( (This)->lpVtbl -> get_IsForced(This,retval) )
#define IUpdateInstaller4_put_IsForced(This,value) \
( (This)->lpVtbl -> put_IsForced(This,value) )
#define IUpdateInstaller4_get_ParentHwnd(This,retval) \
( (This)->lpVtbl -> get_ParentHwnd(This,retval) )
#define IUpdateInstaller4_put_ParentHwnd(This,value) \
( (This)->lpVtbl -> put_ParentHwnd(This,value) )
#define IUpdateInstaller4_put_ParentWindow(This,value) \
( (This)->lpVtbl -> put_ParentWindow(This,value) )
#define IUpdateInstaller4_get_ParentWindow(This,retval) \
( (This)->lpVtbl -> get_ParentWindow(This,retval) )
#define IUpdateInstaller4_get_Updates(This,retval) \
( (This)->lpVtbl -> get_Updates(This,retval) )
#define IUpdateInstaller4_put_Updates(This,value) \
( (This)->lpVtbl -> put_Updates(This,value) )
#define IUpdateInstaller4_BeginInstall(This,onProgressChanged,onCompleted,state,retval) \
( (This)->lpVtbl -> BeginInstall(This,onProgressChanged,onCompleted,state,retval) )
#define IUpdateInstaller4_BeginUninstall(This,onProgressChanged,onCompleted,state,retval) \
( (This)->lpVtbl -> BeginUninstall(This,onProgressChanged,onCompleted,state,retval) )
#define IUpdateInstaller4_EndInstall(This,value,retval) \
( (This)->lpVtbl -> EndInstall(This,value,retval) )
#define IUpdateInstaller4_EndUninstall(This,value,retval) \
( (This)->lpVtbl -> EndUninstall(This,value,retval) )
#define IUpdateInstaller4_Install(This,retval) \
( (This)->lpVtbl -> Install(This,retval) )
#define IUpdateInstaller4_RunWizard(This,dialogTitle,retval) \
( (This)->lpVtbl -> RunWizard(This,dialogTitle,retval) )
#define IUpdateInstaller4_get_IsBusy(This,retval) \
( (This)->lpVtbl -> get_IsBusy(This,retval) )
#define IUpdateInstaller4_Uninstall(This,retval) \
( (This)->lpVtbl -> Uninstall(This,retval) )
#define IUpdateInstaller4_get_AllowSourcePrompts(This,retval) \
( (This)->lpVtbl -> get_AllowSourcePrompts(This,retval) )
#define IUpdateInstaller4_put_AllowSourcePrompts(This,value) \
( (This)->lpVtbl -> put_AllowSourcePrompts(This,value) )
#define IUpdateInstaller4_get_RebootRequiredBeforeInstallation(This,retval) \
( (This)->lpVtbl -> get_RebootRequiredBeforeInstallation(This,retval) )
#define IUpdateInstaller4_get_ForceQuiet(This,retval) \
( (This)->lpVtbl -> get_ForceQuiet(This,retval) )
#define IUpdateInstaller4_put_ForceQuiet(This,value) \
( (This)->lpVtbl -> put_ForceQuiet(This,value) )
#define IUpdateInstaller4_get_AttemptCloseAppsIfNecessary(This,retval) \
( (This)->lpVtbl -> get_AttemptCloseAppsIfNecessary(This,retval) )
#define IUpdateInstaller4_put_AttemptCloseAppsIfNecessary(This,value) \
( (This)->lpVtbl -> put_AttemptCloseAppsIfNecessary(This,value) )
#define IUpdateInstaller4_Commit(This,dwFlags) \
( (This)->lpVtbl -> Commit(This,dwFlags) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IUpdateInstaller4_INTERFACE_DEFINED__ */

39
LegacyUpdate/wuapi.idl Normal file
View File

@ -0,0 +1,39 @@
import "oaidl.idl";
// Just types we need from wuapi.idl
[
helpstring("IUpdateInstaller Interface"),
object,
oleautomation,
dual,
nonextensible,
uuid(7b929c68-ccdc-4226-96b1-8724600b54c2),
pointer_default(unique),
]
interface IUpdateInstaller : IDispatch {
[id(0x60020003), propget, restricted]
HRESULT ParentHwnd([out, retval] HWND *retval);
[id(0x60020003), propput, restricted]
HRESULT ParentHwnd([in, unique] HWND value);
};
[
uuid(B596CC9F-56E5-419E-A622-E01BB457431E),
version(2.0),
helpstring("WUAPI 2.0 Type Library")
]
library WUApiLib
{
importlib("stdole2.tlb");
[
helpstring("UpdateInstaller Class"),
uuid(D2E0FE7F-D23E-48E1-93C0-6FA8CC346474)
]
coclass UpdateInstaller
{
[default] interface IUpdateInstaller2;
};
};

3943
LegacyUpdate/wuerror.mc Normal file

File diff suppressed because it is too large Load Diff

35
build/fix-nsis.sh Normal file
View File

@ -0,0 +1,35 @@
#!/bin/bash
# Fixes NSIS binaries so they run on Pentium/486. Debian's build of NSIS is compiled with MinGW,
# but they lack any -mcpu flag, so the binaries receive a default of i686. To fix this, we'll
# download the official Windows build of NSIS and extract its binaries. We only handle stubs though,
# because we provide our own plugin builds in this repo.
set -e
if [[ $UID != 0 ]]; then
echo "This script needs to be run as root (sorry)" >&2
exit 1
fi
if [[ ! -d /usr/share/nsis/Stubs ]]; then
echo "NSIS not installed, or Stubs directory is broken" >&2
exit 1
fi
if [[ -d /usr/share/nsis/Stubs_old ]]; then
echo "NSIS stubs are already fixed" >&2
exit 0
fi
apt-get install -qy curl p7zip-full
mkdir /tmp/nsis
cd /tmp/nsis
curl -fSL https://prdownloads.sourceforge.net/nsis/NSIS%203/3.10/nsis-3.10-setup.exe -o nsis.exe
7z x nsis.exe
mv /usr/share/nsis/Stubs{,_old}
cp -ra Stubs /usr/share/nsis/Stubs
rm -rf /tmp/nsis

BIN
build/fix-vc08-aslr.reg Normal file

Binary file not shown.

1360
include/licdll.h Normal file

File diff suppressed because it is too large Load Diff

170
include/licdll.idl Normal file
View File

@ -0,0 +1,170 @@
import "oaidl.idl";
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: licdll.dll
[
uuid(C7879482-F798-4A74-AF43-E887FBDCED40),
version(1.0),
helpstring("licdll 1.0 Type Library")
]
library LICDLLLib
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface ICOMLicenseAgent;
interface ICOMLicenseAgent2;
[
uuid(ACADF079-CBCD-4032-83F2-FA47C4DB096F),
helpstring("COMLicenseAgent Class")
]
coclass COMLicenseAgent {
[default] interface ICOMLicenseAgent;
interface ICOMLicenseAgent2;
};
[
odl,
uuid(B8CBAD79-3F1F-481A-BB0C-E7BBD77BDDD1),
helpstring("ICOMLicenseAgent Interface"),
dual,
oleautomation
]
interface ICOMLicenseAgent : IDispatch {
[id(0x00000001), helpstring("method Initialize")]
HRESULT Initialize(
[in] unsigned long dwBPC,
[in] unsigned long dwMode,
[in] BSTR bstrLicSource,
[out, retval] unsigned long* pdwRetCode);
[id(0x00000003), helpstring("method GetFirstName")]
HRESULT GetFirstName([out, retval] BSTR* pbstrVal);
[id(0x00000004), helpstring("method SetFirstName")]
HRESULT SetFirstName([in] BSTR bstrNewVal);
[id(0x00000005), helpstring("method GetLastName")]
HRESULT GetLastName([out, retval] BSTR* pbstrVal);
[id(0x00000006), helpstring("method SetLastName")]
HRESULT SetLastName([in] BSTR bstrNewVal);
[id(0x00000007), helpstring("method GetOrgName")]
HRESULT GetOrgName([out, retval] BSTR* pbstrVal);
[id(0x00000008), helpstring("method SetOrgName")]
HRESULT SetOrgName([in] BSTR bstrNewVal);
[id(0x00000009), helpstring("method GetEmail")]
HRESULT GetEmail([out, retval] BSTR* pbstrVal);
[id(0x0000000a), helpstring("method SetEmail")]
HRESULT SetEmail([in] BSTR bstrNewVal);
[id(0x0000000b), helpstring("method GetPhone")]
HRESULT GetPhone([out, retval] BSTR* pbstrVal);
[id(0x0000000c), helpstring("method SetPhone")]
HRESULT SetPhone([in] BSTR bstrNewVal);
[id(0x0000000d), helpstring("method GetAddress1")]
HRESULT GetAddress1([out, retval] BSTR* pbstrVal);
[id(0x0000000e), helpstring("method SetAddress1")]
HRESULT SetAddress1([in] BSTR bstrNewVal);
[id(0x0000000f), helpstring("method GetCity")]
HRESULT GetCity([out, retval] BSTR* pbstrVal);
[id(0x00000010), helpstring("method SetCity")]
HRESULT SetCity([in] BSTR bstrNewVal);
[id(0x00000011), helpstring("method GetState")]
HRESULT GetState([out, retval] BSTR* pbstrVal);
[id(0x00000012), helpstring("method SetState")]
HRESULT SetState([in] BSTR bstrNewVal);
[id(0x00000013), helpstring("method GetCountryCode")]
HRESULT GetCountryCode([out, retval] BSTR* pbstrVal);
[id(0x00000014), helpstring("method SetCountryCode")]
HRESULT SetCountryCode([in] BSTR bstrNewVal);
[id(0x00000015), helpstring("method GetCountryDesc")]
HRESULT GetCountryDesc([out, retval] BSTR* pbstrVal);
[id(0x00000016), helpstring("method SetCountryDesc")]
HRESULT SetCountryDesc([in] BSTR bstrNewVal);
[id(0x00000017), helpstring("method GetZip")]
HRESULT GetZip([out, retval] BSTR* pbstrVal);
[id(0x00000018), helpstring("method SetZip")]
HRESULT SetZip([in] BSTR bstrNewVal);
[id(0x00000019), helpstring("method GetIsoLanguage")]
HRESULT GetIsoLanguage([out, retval] unsigned long* pdwVal);
[id(0x0000001a), helpstring("method SetIsoLanguage")]
HRESULT SetIsoLanguage([in] unsigned long dwNewVal);
[id(0x00000020), helpstring("method GetMSUpdate")]
HRESULT GetMSUpdate([out, retval] BSTR* pbstrVal);
[id(0x00000021), helpstring("method SetMSUpdate")]
HRESULT SetMSUpdate([in] BSTR bstrNewVal);
[id(0x00000022), helpstring("method GetMSOffer")]
HRESULT GetMSOffer([out, retval] BSTR* pbstrVal);
[id(0x00000023), helpstring("method SetMSOffer")]
HRESULT SetMSOffer([in] BSTR bstrNewVal);
[id(0x00000024), helpstring("method GetOtherOffer")]
HRESULT GetOtherOffer([out, retval] BSTR* pbstrVal);
[id(0x00000025), helpstring("method SetOtherOffer")]
HRESULT SetOtherOffer([in] BSTR bstrNewVal);
[id(0x00000026), helpstring("method GetAddress2")]
HRESULT GetAddress2([out, retval] BSTR* pbstrVal);
[id(0x00000027), helpstring("method SetAddress2")]
HRESULT SetAddress2([in] BSTR bstrNewVal);
[id(0x00000052), helpstring("method AsyncProcessHandshakeRequest")]
HRESULT AsyncProcessHandshakeRequest([in] long bReviseCustInfo);
[id(0x00000053), helpstring("method AsyncProcessNewLicenseRequest")]
HRESULT AsyncProcessNewLicenseRequest();
[id(0x00000054), helpstring("method AsyncProcessReissueLicenseRequest")]
HRESULT AsyncProcessReissueLicenseRequest();
[id(0x00000056), helpstring("method AsyncProcessReviseCustInfoRequest")]
HRESULT AsyncProcessReviseCustInfoRequest();
[id(0x0000005a), helpstring("method GetAsyncProcessReturnCode")]
HRESULT GetAsyncProcessReturnCode([out, retval] unsigned long* pdwRetCode);
[id(0x0000005d), helpstring("method AsyncProcessDroppedLicenseRequest")]
HRESULT AsyncProcessDroppedLicenseRequest();
[id(0x00000064), helpstring("method GenerateInstallationId")]
HRESULT GenerateInstallationId([out, retval] BSTR* pbstrVal);
[id(0x00000065), helpstring("method DepositConfirmationId")]
HRESULT DepositConfirmationId(
[in] BSTR bstrVal,
[out, retval] unsigned long* pdwRetCode);
[id(0x00000066), helpstring("method GetExpirationInfo")]
HRESULT GetExpirationInfo(
[out] unsigned long* pdwWPALeft,
[out, retval] unsigned long* pdwEvalLeft);
[id(0x00000067), helpstring("method AsyncProcessRegistrationRequest")]
HRESULT AsyncProcessRegistrationRequest();
[id(0x00000068), helpstring("method ProcessHandshakeRequest")]
HRESULT ProcessHandshakeRequest([in] long bReviseCustInfo);
[id(0x00000069), helpstring("method ProcessNewLicenseRequest")]
HRESULT ProcessNewLicenseRequest();
[id(0x0000006a), helpstring("method ProcessDroppedLicenseRequest")]
HRESULT ProcessDroppedLicenseRequest();
[id(0x0000006b), helpstring("method ProcessReissueLicenseRequest")]
HRESULT ProcessReissueLicenseRequest();
[id(0x0000006d), helpstring("method ProcessReviseCustInfoRequest")]
HRESULT ProcessReviseCustInfoRequest();
[id(0x0000006e), helpstring("method EnsureInternetConnection")]
HRESULT EnsureInternetConnection();
[id(0x0000006f), helpstring("method SetProductKey")]
HRESULT SetProductKey([in] LPWSTR pszNewProductKey);
[id(0x00000070), helpstring("method GetProductID")]
HRESULT GetProductID([out, retval] BSTR* pbstrVal);
[id(0x00000071), helpstring("method VerifyCheckDigits")]
HRESULT VerifyCheckDigits(
BSTR bstrCIDIID,
[out, retval] long* pbValue);
};
[
odl,
uuid(6A07C5A3-9C67-4BB6-B020-ECBE7FDFD326),
helpstring("ICOMLicenseAgent Interface 2"),
dual,
oleautomation
]
interface ICOMLicenseAgent2 : ICOMLicenseAgent {
[id(0x00000072), helpstring("method SetReminders")]
HRESULT SetReminders(long bValue);
[id(0x00000073), helpstring("method GetReminders")]
HRESULT GetReminders(long* pbValue);
[id(0x00000074), helpstring("method GetKeyType")]
HRESULT GetKeyType([out, retval] unsigned long* pdwKeyType);
};
};

33
include/slpublic.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef GUID SLID;
typedef PVOID HSLC;
DEFINE_GUID(WINDOWS_SLID, 0x55c92734, 0xd682, 0x4d71, 0x98, 0x3e, 0xd6, 0xec, 0x3f, 0x16, 0x05, 0x9f);
typedef enum _tagSLLICENSINGSTATUS {
SL_LICENSING_STATUS_UNLICENSED,
SL_LICENSING_STATUS_LICENSED,
SL_LICENSING_STATUS_IN_GRACE_PERIOD,
SL_LICENSING_STATUS_NOTIFICATION,
SL_LICENSING_STATUS_LAST
} SLLICENSINGSTATUS;
typedef struct _tagSL_LICENSING_STATUS {
SLID SkuId;
SLLICENSINGSTATUS eStatus;
DWORD dwGraceTime;
DWORD dwTotalGraceDays;
HRESULT hrReason;
UINT64 qwValidityExpiration;
} SL_LICENSING_STATUS;
#ifdef __cplusplus
}
#endif

18
launcher/CplTasks.xml Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<applications xmlns="http://schemas.microsoft.com/windows/cpltasks/v1" xmlns:sh="http://schemas.microsoft.com/windows/tasks/v1">
<application id="{FFBE8D44-E9CF-4DD8-9FD6-976802C94D9C}">
<sh:task id="{9943E8C8-748D-47CE-AE10-9FA4A80ED28B}" needsElevation="true">
<sh:name>@&quot;%ProgramFiles%\Legacy Update\LegacyUpdate.exe&quot;,-3</sh:name>
<sh:keywords>legacy update;legacyupdate;update;windows;microsoft;driver;security;software;</sh:keywords>
<sh:command>&quot;%ProgramFiles%\Legacy Update\LegacyUpdate.exe&quot;</sh:command>
</sh:task>
<category id="5">
<sh:task idref="{9943E8C8-748D-47CE-AE10-9FA4A80ED28B}" />
</category>
<category id="10">
<sh:task idref="{9943E8C8-748D-47CE-AE10-9FA4A80ED28B}" />
</category>
</application>
</applications>

298
launcher/InitRunOnce.c Normal file
View File

@ -0,0 +1,298 @@
#include <windows.h>
#include <commctrl.h>
#include "MsgBox.h"
#include "VersionInfo.h"
#include "LoadImage.h"
#define HK_RUNCMD 1
typedef DWORD (__fastcall *_ThemeWaitForServiceReady)(DWORD timeout);
typedef DWORD (__fastcall *_ThemeWatchForStart)();
static const COLORREF WallpaperColorWin2k = RGB(58, 110, 165); // #3a6ea5
static const COLORREF WallpaperColorWinXP = RGB( 0, 78, 152); // #004e98
static const COLORREF WallpaperColorWin8 = RGB(32, 103, 178); // #2067b2
static const COLORREF WallpaperColorWin10 = RGB(24, 0, 82); // #180052
static const WCHAR RunOnceClassName[] = L"LegacyUpdateRunOnce";
static HANDLE g_cmdHandle;
static void StartThemes() {
// Ask UxInit.dll to ask the Themes service to start a session for this desktop. Themes doesn't automatically start a
// session for the SYSTEM desktop, so we need to ask it to. This matches what msoobe.exe does on first boot.
// Windows 7 moves this to UxInit.dll
HMODULE shsvcs = LoadLibrary(L"UxInit.dll");
if (!shsvcs) {
shsvcs = LoadLibrary(L"shsvcs.dll");
if (!shsvcs) {
return;
}
}
// Get functions by ordinals
_ThemeWaitForServiceReady $ThemeWaitForServiceReady = (_ThemeWaitForServiceReady)GetProcAddress(shsvcs, MAKEINTRESOURCEA(2));
_ThemeWatchForStart $ThemeWatchForStart = (_ThemeWatchForStart)GetProcAddress(shsvcs, MAKEINTRESOURCEA(1));
// 1. Wait up to 1000ms for Themes to start
if ($ThemeWaitForServiceReady) {
$ThemeWaitForServiceReady(1000);
}
// 2. Prompt Themes to start a session for the SYSTEM desktop
if ($ThemeWatchForStart) {
$ThemeWatchForStart();
}
FreeLibrary(shsvcs);
}
static BOOL RunCmd(LPPROCESS_INFORMATION processInfo) {
WCHAR cmd[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\cmd.exe", cmd, ARRAYSIZE(cmd));
STARTUPINFO startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, processInfo)) {
MsgBox(NULL, L"Launching cmd.exe failed", NULL, MB_OK | MB_ICONERROR);
return FALSE;
}
CloseHandle(processInfo->hThread);
g_cmdHandle = processInfo->hProcess;
return TRUE;
}
static LRESULT CALLBACK RunOnceWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_NCHITTEST:
// Don't accept any mouse input
return HTNOWHERE;
case WM_HOTKEY: {
// Shift-F10 to run cmd
if (wParam == HK_RUNCMD) {
DWORD exitCode;
if (!g_cmdHandle || (GetExitCodeProcess(g_cmdHandle, &exitCode) && exitCode != STILL_ACTIVE)) {
PROCESS_INFORMATION processInfo;
RunCmd(&processInfo);
}
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);;
}
static void CreateRunOnceWindow() {
// Init common controls
INITCOMMONCONTROLSEX initComctl = {0};
initComctl.dwSize = sizeof(initComctl);
initComctl.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&initComctl);
// Create window
WNDCLASS wndClass = {0};
wndClass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_NOCLOSE;
wndClass.lpfnWndProc = RunOnceWndProc;
wndClass.hInstance = GetModuleHandle(NULL);
wndClass.lpszClassName = RunOnceClassName;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClass(&wndClass)) {
TRACE(L"RegisterClass failed: %d", GetLastError());
return;
}
HWND hwnd = CreateWindowEx(
WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE,
wndClass.lpszClassName,
L"Legacy Update",
WS_POPUP,
0, 0, 0, 0,
NULL, NULL,
wndClass.hInstance,
NULL
);
if (!hwnd) {
TRACE(L"CreateWindow failed: %d", GetLastError());
return;
}
// Register hotkey
RegisterHotKey(hwnd, HK_RUNCMD, MOD_SHIFT, VK_F10);
// Check if the display is 8-bit color or lower
HDC dc = GetDC(NULL);
int bpp = GetDeviceCaps(dc, BITSPIXEL);
ReleaseDC(NULL, dc);
if (bpp >= 8) {
// Set the wallpaper color
COLORREF color = GetSysColor(COLOR_DESKTOP);
if (AtLeastWin10()) {
color = WallpaperColorWin10;
} else if (AtLeastWin8()) {
color = WallpaperColorWin8;
} else if ((IsWinXP2002() || IsWinXP2003()) && color == RGB(0, 0, 0)) {
// XP uses a black wallpaper in fast user switching mode. Override to the default blue.
color = WallpaperColorWinXP;
}
SetSysColors(1, (const INT[1]){COLOR_DESKTOP}, (const COLORREF[1]){color});
DWORD width = GetSystemMetrics(SM_CXSCREEN);
DWORD height = GetSystemMetrics(SM_CYSCREEN);
HBITMAP wallpaper;
if (IsWin7()) {
// 7: Bitmap in oobe dir
WCHAR bmpPath[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\oobe\\background.bmp", bmpPath, ARRAYSIZE(bmpPath));
wallpaper = LoadImage(NULL, bmpPath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
} else if (IsWinVista()) {
// Vista: Resources in ooberesources.dll
WCHAR ooberesPath[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\oobe\\ooberesources.dll", ooberesPath, ARRAYSIZE(ooberesPath));
HMODULE ooberes = LoadLibrary(ooberesPath);
if (ooberes) {
// Width logic is the same used by Vista msoobe.dll
LPWSTR resource = GetSystemMetrics(SM_CXSCREEN) < 1200 ? L"OOBE_BACKGROUND_0" : L"OOBE_BACKGROUND_LARGE_0";
wallpaper = LoadPNGResource(ooberes, resource, RT_RCDATA);
}
FreeLibrary(ooberes);
}
if (wallpaper) {
// Write to disk
WCHAR tempPath[MAX_PATH];
ExpandEnvironmentStrings(L"%ProgramData%\\Legacy Update\\background.bmp", tempPath, ARRAYSIZE(tempPath));
if (GetFileAttributes(tempPath) != INVALID_FILE_ATTRIBUTES || ScaleAndWriteToBMP(wallpaper, width, height, tempPath)) {
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)tempPath, SPIF_SENDWININICHANGE);
}
DeleteObject(wallpaper);
}
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
}
static BOOL IsSystemUser() {
BOOL result = FALSE;
PTOKEN_USER tokenInfo;
PSID systemSid;
HANDLE token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
goto end;
}
DWORD tokenInfoLen;
GetTokenInformation(token, TokenUser, NULL, 0, &tokenInfoLen);
tokenInfo = (PTOKEN_USER)LocalAlloc(LPTR, tokenInfoLen);
if (!GetTokenInformation(token, TokenUser, tokenInfo, tokenInfoLen, &tokenInfoLen)) {
goto end;
}
DWORD sidSize = SECURITY_MAX_SID_SIZE;
systemSid = LocalAlloc(LPTR, sidSize);
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, systemSid, &sidSize)) {
goto end;
}
result = EqualSid(tokenInfo->User.Sid, systemSid);
end:
if (tokenInfo) {
LocalFree(tokenInfo);
}
if (systemSid) {
LocalFree(systemSid);
}
if (token) {
CloseHandle(token);
}
return result;
}
void RunOnce() {
#ifndef _DEBUG
// Only relevant if we're SYSTEM
if (!IsSystemUser()) {
PostQuitMessage(1);
return;
}
#endif
// Start Themes on this desktop
StartThemes();
// Find and hide the FirstUxWnd window, if it exists (Windows 7+)
HWND firstUxWnd = FindWindow(L"FirstUxWndClass", NULL);
if (firstUxWnd) {
ShowWindow(firstUxWnd, SW_HIDE);
}
// Set up our window
CreateRunOnceWindow();
// Construct path to LegacyUpdateSetup.exe
WCHAR setupPath[MAX_PATH];
GetModuleFileName(NULL, setupPath, ARRAYSIZE(setupPath));
wcsrchr(setupPath, L'\\')[1] = L'\0';
wcsncat(setupPath, L"LegacyUpdateSetup.exe", ARRAYSIZE(setupPath) - wcslen(setupPath) - 1);
// Execute and wait for completion
STARTUPINFO startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
PROCESS_INFORMATION processInfo = {0};
LPWSTR cmdLine = (LPWSTR)LocalAlloc(LPTR, 4096 * sizeof(WCHAR));
wsprintf(cmdLine, L"\"%ls\" /runonce", setupPath);
if (!CreateProcess(setupPath, cmdLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &processInfo)) {
#ifdef _DEBUG
// Run cmd.exe instead
if (!RunCmd(&processInfo)) {
PostQuitMessage(0);
return;
}
#else
MsgBox(NULL, L"Continuing Legacy Update setup failed", NULL, MB_OK | MB_ICONERROR);
PostQuitMessage(0);
return;
#endif
}
CloseHandle(processInfo.hThread);
// Wait for it to finish, while running a message loop
MSG msg;
while (WaitForSingleObject(processInfo.hProcess, 100) == WAIT_TIMEOUT) {
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CloseHandle(processInfo.hProcess);
// Don't let SYSTEM cmd keep running beyond runonce
if (g_cmdHandle) {
TerminateProcess(g_cmdHandle, 0);
CloseHandle(g_cmdHandle);
}
// Show FirstUxWnd again
if (firstUxWnd) {
ShowWindow(firstUxWnd, SW_SHOW);
}
PostQuitMessage(0);
}

205
launcher/LaunchUpdateSite.c Normal file
View File

@ -0,0 +1,205 @@
#include "stdafx.h"
#include "main.h"
#include "resource.h"
#include <exdisp.h>
#include "Exec.h"
#include "HResult.h"
#include "MsgBox.h"
#include "RegisterServer.h"
#include "Registry.h"
#include "SelfElevate.h"
#include "User.h"
#include "VersionInfo.h"
const LPWSTR UpdateSiteURLHttp = L"http://legacyupdate.net/windowsupdate/v6/";
const LPWSTR UpdateSiteURLHttps = L"https://legacyupdate.net/windowsupdate/v6/";
const LPWSTR UpdateSiteFirstRunFlag = L"?firstrun=true";
DEFINE_GUID(IID_ILegacyUpdateCtrl, 0xC33085BB, 0xC3E1, 0x4D27, 0xA2, 0x14, 0xAF, 0x01, 0x95, 0x3D, 0xF5, 0xE5);
DEFINE_GUID(CLSID_LegacyUpdateCtrl, 0xAD28E0DF, 0x5F5A, 0x40B5, 0x94, 0x32, 0x85, 0xEF, 0xD9, 0x7D, 0x1F, 0x9F);
static const LPWSTR GetUpdateSiteURL() {
// Fallback: Use SSL only on Vista and up
BOOL useHTTPS = AtLeastWinVista();
// Get the Windows Update website URL set by Legacy Update setup
LPWSTR data;
DWORD size;
HRESULT hr = GetRegistryString(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate", L"URL", KEY_WOW64_64KEY, &data, &size);
if (SUCCEEDED(hr)) {
// Return based on the URL value
if (wcscmp(data, UpdateSiteURLHttps) == 0) {
useHTTPS = TRUE;
} else if (wcscmp(data, UpdateSiteURLHttp) == 0) {
useHTTPS = FALSE;
}
LocalFree(data);
}
return useHTTPS ? UpdateSiteURLHttps : UpdateSiteURLHttp;
}
void LaunchUpdateSite(int argc, LPWSTR *argv, int nCmdShow) {
HRESULT hr = S_OK;
IWebBrowser2 *browser;
VARIANT url;
VARIANT flags;
VARIANT nullVariant;
LPTSTR siteURL;
HMONITOR monitor;
// If running on 2k/XP, make sure we're elevated. If not, show Run As prompt.
if (!AtLeastWinVista() && !IsUserAdmin()) {
LPWSTR args = (LPWSTR)LocalAlloc(LPTR, 512 * sizeof(WCHAR));
wsprintf(args, L"/launch %ls", argc > 0 ? argv[0] : L"");
hr = SelfElevate(args, NULL);
// Access denied happens when the user clicks No/Cancel.
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
hr = S_OK;
}
goto end;
}
// Can we instantiate our own ActiveX control? If not, try to register it.
hr = CoCreateInstance(&CLSID_LegacyUpdateCtrl, NULL, CLSCTX_LOCAL_SERVER, &IID_ILegacyUpdateCtrl, (void **)&browser);
if (hr == REGDB_E_CLASSNOTREG) {
hr = RegisterServer(0, TRUE, TRUE);
if (!SUCCEEDED(hr)) {
goto end;
}
hr = CoCreateInstance(&CLSID_LegacyUpdateCtrl, NULL, CLSCTX_LOCAL_SERVER, &IID_ILegacyUpdateCtrl, (void **)&browser);
if (!SUCCEEDED(hr)) {
goto end;
}
IUnknown_Release(browser);
} else if (!SUCCEEDED(hr)) {
goto end;
}
// Spawn an IE window via the COM interface. This ensures the page opens in IE (ShellExecute uses
// default browser), and avoids hardcoding a path to iexplore.exe. Also conveniently allows testing
// on Windows 11 (iexplore.exe redirects to Edge, but COM still works). Same strategy as used by
// Wupdmgr.exe and Muweb.dll,LaunchMUSite.
hr = CoCreateInstance(&CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, &IID_IWebBrowser2, (void **)&browser);
if (hr == REGDB_E_CLASSNOTREG) {
// Handle case where the user has uninstalled Internet Explorer using Programs and Features.
OSVERSIONINFOEX *versionInfo = GetVersionInfo();
// Windows 8+: Directly prompt to reinstall IE using Fondue.exe.
if (AtLeastWin8()) {
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
LPCTSTR archSuffix = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? L"amd64" : L"x86";
WCHAR fondue[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\fondue.exe", fondue, ARRAYSIZE(fondue));
WCHAR fondueArgs[256];
wsprintf(fondueArgs, L"/enable-feature:Internet-Explorer-Optional-%ls", archSuffix);
hr = Exec(NULL, fondue, fondueArgs, NULL, SW_SHOWDEFAULT, FALSE, NULL);
if (SUCCEEDED(hr)) {
goto end;
}
}
// Tell the user what they need to do, then open the Optional Features dialog.
WCHAR message[4096];
LoadString(GetModuleHandle(NULL), IDS_IENOTINSTALLED, message, ARRAYSIZE(message));
MsgBox(NULL, message, NULL, MB_OK | MB_ICONEXCLAMATION);
WCHAR optionalFeatures[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\OptionalFeatures.exe", optionalFeatures, ARRAYSIZE(optionalFeatures));
Exec(NULL, optionalFeatures, NULL, NULL, SW_SHOWDEFAULT, FALSE, NULL);
hr = S_OK;
goto end;
} else if (!SUCCEEDED(hr)) {
goto end;
}
// Can we connect with https? WinInet will throw an error if not.
siteURL = GetUpdateSiteURL();
// Is this a first run launch? Append first run flag if so.
if (argc > 0 && lstrcmpi(argv[0], L"/firstrun") == 0) {
WCHAR newSiteURL[256];
wsprintf(newSiteURL, L"%s%s", siteURL, UpdateSiteFirstRunFlag);
siteURL = newSiteURL;
}
VariantInit(&url);
url.vt = VT_BSTR;
url.bstrVal = SysAllocString(siteURL);
VariantInit(&flags);
flags.vt = VT_I4;
flags.lVal = 0;
VariantInit(&nullVariant);
hr = IWebBrowser2_Navigate2(browser, &url, &flags, &nullVariant, &nullVariant, &nullVariant);
if (!SUCCEEDED(hr)) {
goto end;
}
HWND ieHwnd;
hr = IWebBrowser2_get_HWND(browser, (SHANDLE_PTR *)&ieHwnd);
if (!SUCCEEDED(hr)) {
goto end;
}
// Are we on a small display? If so, resize and maximise the window.
monitor = MonitorFromWindow(ieHwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
if (GetMonitorInfo(monitor, &monitorInfo) > 0) {
LONG workWidth = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
LONG workHeight = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
LONG width, height;
IWebBrowser2_get_Width(browser, &width);
IWebBrowser2_get_Height(browser, &height);
if (width < 800) {
width = workWidth < 800 ? workWidth : 800;
IWebBrowser2_put_Width(browser, width);
}
if (height < 600) {
height = workHeight < 600 ? workHeight : 600;
IWebBrowser2_put_Height(browser, height);
}
LONG left, top;
IWebBrowser2_get_Left(browser, &left);
IWebBrowser2_get_Top(browser, &top);
if (left + width > workWidth) {
IWebBrowser2_put_Left(browser, 0);
}
if (top + height > workHeight) {
IWebBrowser2_put_Top(browser, 0);
}
if (workWidth <= 1152) {
ShowWindow(ieHwnd, SW_MAXIMIZE);
}
}
IWebBrowser2_put_Visible(browser, TRUE);
// Focus the window, since it seems to not always get focus as it should.
SetForegroundWindow(ieHwnd);
end:
if (!SUCCEEDED(hr)) {
MsgBox(NULL, GetMessageForHresult(hr), NULL, MB_ICONEXCLAMATION);
}
browser = NULL;
CoUninitialize();
PostQuitMessage(0);
}

11
launcher/Log.c Normal file
View File

@ -0,0 +1,11 @@
#include "WULog.h"
#include "MsgBox.h"
void LaunchLog(int nCmdShow) {
HRESULT hr = ViewWindowsUpdateLog(nCmdShow);
if (!SUCCEEDED(hr)) {
MsgBox(NULL, GetMessageForHresult(hr), NULL, MB_OK);
}
PostQuitMessage(hr);
}

8
launcher/Makefile Normal file
View File

@ -0,0 +1,8 @@
all:
+$(MAKE) -f Makefile.actual ARCH=32
+$(MAKE) -f Makefile.actual ARCH=64
clean:
rm -rf obj
.PHONY: all clean

126
launcher/Makefile.actual Normal file
View File

@ -0,0 +1,126 @@
FILES = \
$(wildcard *.c) \
../shared/Exec.c \
../shared/HResult.c \
../shared/LegacyUpdate.c \
../shared/LoadImage.c \
../shared/Registry.c \
../shared/VersionInfo.c \
../shared/Wow64.c
RCFILES = resource.rc
DEFFILES = ../LegacyUpdate/LegacyUpdate.def
ARCH ?= 32
ifeq ($(ARCH),64)
TAG = x86_64
else
TAG = i686
endif
PREFIX = $(TAG)-w64-mingw32-
BIN = obj/LegacyUpdate$(ARCH).exe
OBJ = $(foreach file,$(FILES),obj/$(notdir $(basename $(file)).$(TAG).o))
RES = $(foreach file,$(RCFILES),obj/$(notdir $(basename $(file)).$(TAG).res))
DEFDLL = $(foreach file,$(DEFFILES),obj/lib$(notdir $(basename $(file)).$(TAG).a))
CC = $(PREFIX)g++
RC = $(PREFIX)windres
DLLTOOL = $(PREFIX)dlltool
override DEBUG := $(or $(DEBUG),1)
CFLAGS = \
-mwindows \
-municode \
-DUNICODE \
-D_UNICODE \
$(if $(filter 1,$(DEBUG)),-D_DEBUG -g,-DNDEBUG -Os) \
-s \
-fPIE \
-ffunction-sections \
-fdata-sections \
-fno-unwind-tables \
-fno-asynchronous-unwind-tables \
-fno-exceptions \
-flto \
-Wno-write-strings \
-I../include \
-I../shared \
-include stdafx.h
CXXFLAGS = \
$(CFLAGS) \
-std=c++11 \
-fno-rtti
LDFLAGS = \
-nodefaultlibs \
-nostartfiles \
-nostdlib \
-Wl,--gc-sections \
-Wl,--no-seh \
-Wl,--nxcompat \
-Wl,--enable-auto-image-base \
-Wl,--enable-stdcall-fixup \
-Wl,--strip-all \
-Lobj \
-lmsvcrt \
-lgcc \
-lpsapi \
-lkernel32 \
-luser32 \
-lole32 \
-loleaut32 \
-ladvapi32 \
-lcomctl32 \
-lshell32 \
-lversion \
-lgdi32 \
-lmsimg32
RCFLAGS = \
-O coff \
-I../shared
ifeq ($(ARCH),64)
LDFLAGS += -Wl,-ewWinMain
RCFLAGS += -F pe-x86-64
else
CFLAGS += -march=i486
LDFLAGS += -Wl,-e_wWinMain
RCFLAGS += -F pe-i386
endif
all: before-all $(DEFDLL) $(BIN)
ifeq ($(SIGN),1)
../build/sign.sh $(BIN)
endif
before-all:
mkdir -p obj
$(BIN): $(OBJ) $(RES)
$(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@
obj/%.$(TAG).o: %.c
$(CC) -x c $< $(CFLAGS) -c -o $@
obj/%.$(TAG).o: ../shared/%.c
$(CC) -x c $< $(CFLAGS) -c -o $@
obj/%.$(TAG).res: %.rc
$(RC) $< $(RCFLAGS) -o $@
obj/lib%.$(TAG).a: ../LegacyUpdate/%.def
$(DLLTOOL) -d $< -l $@ -D $(notdir $(basename $<).dll)
clean:
rm -rf obj
test:
+$(MAKE) DEBUG=$(DEBUG)
./obj/LegacyUpdate.exe
.PHONY: all before-all clean test

82
launcher/MsgBox.c Normal file
View File

@ -0,0 +1,82 @@
#include "stdafx.h"
#include "main.h"
#include "resource.h"
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#include <commctrl.h>
typedef HRESULT (WINAPI *_TaskDialogIndirect)(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton, int *pnRadioButton, BOOL *pfVerificationFlagChecked);
static BOOL _loadedTaskDialog = FALSE;
static _TaskDialogIndirect $TaskDialogIndirect;
int MsgBox(HWND hwnd, LPCTSTR instruction, LPCTSTR body, UINT type) {
if (!_loadedTaskDialog) {
_loadedTaskDialog = TRUE;
$TaskDialogIndirect = (_TaskDialogIndirect)GetProcAddress(LoadLibrary(L"comctl32.dll"), "TaskDialogIndirect");
}
// Play the sound matching the icon, because MB_USERICON doesn't play a sound
MessageBeep(type & 0x000000F0);
type = (type & ~0x000000F0) | MB_USERICON;
if (!$TaskDialogIndirect) {
LPWSTR finalBody = (LPWSTR)instruction;
if (body && lstrlen(body) > 0) {
size_t length = lstrlen(instruction) + lstrlen(body) + 3;
finalBody = (LPWSTR)LocalAlloc(LPTR, length * sizeof(TCHAR));
wsprintf(finalBody, L"%s\n\n%s", instruction, body);
}
MSGBOXPARAMS params = { 0 };
params.cbSize = sizeof(MSGBOXPARAMS);
params.hwndOwner = hwnd;
params.hInstance = GetModuleHandle(NULL);
params.lpszText = finalBody;
params.lpszCaption = L"Legacy Update";
params.dwStyle = type;
params.lpszIcon = MAKEINTRESOURCE(IDI_APPICON);
int result = MessageBoxIndirect(&params);
if (finalBody != body) {
LocalFree(finalBody);
}
return result;
}
TASKDIALOG_COMMON_BUTTON_FLAGS buttons;
DWORD flags = TDF_POSITION_RELATIVE_TO_WINDOW;
switch (type & 0x0000000F) {
case MB_OK:
buttons = TDCBF_OK_BUTTON;
flags |= TDF_ALLOW_DIALOG_CANCELLATION;
break;
case MB_OKCANCEL:
buttons = TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON;
flags |= TDF_ALLOW_DIALOG_CANCELLATION;
break;
case MB_YESNO:
buttons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;
break;
default:
break;
}
TASKDIALOGCONFIG config = { 0 };
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.hwndParent = hwnd;
config.hInstance = GetModuleHandle(NULL);
config.dwFlags = flags;
config.dwCommonButtons = buttons;
config.pszWindowTitle = L"Legacy Update";
config.pszMainInstruction = instruction;
config.pszContent = body;
config.pszMainIcon = MAKEINTRESOURCE(IDI_APPICON);
int button;
$TaskDialogIndirect(&config, &button, NULL, NULL);
return button;
}

5
launcher/MsgBox.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <windows.h>
int MsgBox(HWND hwnd, LPCTSTR instruction, LPCTSTR body, UINT type);

40
launcher/Options.c Normal file
View File

@ -0,0 +1,40 @@
#include <windows.h>
#include "Exec.h"
#include "VersionInfo.h"
#include "Wow64.h"
void LaunchOptions(int nCmdShow) {
#if !_WIN64
// Some issues arise from the working directory being SysWOW64 rather than System32. Notably,
// Windows Vista - 8.1 don't have wuauclt.exe in SysWOW64. Disable WOW64 redirection temporarily
// to work around this.
PVOID oldValue;
BOOL isRedirected = DisableWow64FsRedirection(&oldValue);
#endif
HRESULT hr;
if (AtLeastWin10()) {
// Windows 10+: Open Settings app
hr = Exec(NULL, L"ms-settings:windowsupdate-options", NULL, NULL, SW_SHOWDEFAULT, FALSE, NULL);
} else if (AtLeastWinVista()) {
// Windows Vista, 7, 8: Open Windows Update control panel
WCHAR wuauclt[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\wuauclt.exe", wuauclt, ARRAYSIZE(wuauclt));
hr = Exec(NULL, wuauclt, L"/ShowOptions", NULL, SW_SHOWDEFAULT, FALSE, NULL);
} else {
// Windows 2000, XP: Open Automatic Updates control panel
WCHAR wuaucpl[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\wuaucpl.cpl", wuaucpl, ARRAYSIZE(wuaucpl));
hr = Exec(NULL, wuaucpl, NULL, NULL, SW_SHOWDEFAULT, FALSE, NULL);
}
#if !_WIN64
// Revert WOW64 redirection if we changed it
if (isRedirected) {
RevertWow64FsRedirection(oldValue);
}
#endif
PostQuitMessage(hr);
}

153
launcher/RegisterServer.c Normal file
View File

@ -0,0 +1,153 @@
#include <windows.h>
#include "Exec.h"
#include "HResult.h"
#include "LegacyUpdate.h"
#include "MsgBox.h"
#include "Registry.h"
#include "SelfElevate.h"
#include "User.h"
#include "VersionInfo.h"
#include "Wow64.h"
static HRESULT RegisterDllInternal(LPWSTR path, BOOL state) {
HMODULE module = LoadLibrary(path);
if (!module) {
return HRESULT_FROM_WIN32(GetLastError());
}
HRESULT hr = S_OK;
FARPROC proc = GetProcAddress(module, state ? "DllRegisterServer" : "DllUnregisterServer");
if (!proc) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = ((HRESULT (WINAPI *)())proc)();
end:
if (module) {
FreeLibrary(module);
}
return hr;
}
static HRESULT RegisterDllExternal(LPWSTR path, BOOL state) {
WCHAR regsvr32[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\regsvr32.exe", regsvr32, ARRAYSIZE(regsvr32));
LPWSTR args = (LPWSTR)LocalAlloc(LPTR, (lstrlen(path) + 6) * sizeof(WCHAR));
wsprintf(args, L"/s %ls\"%ls\"", state ? L"" : L"/u ", path);
DWORD status;
HRESULT hr = Exec(NULL, regsvr32, args, NULL, SW_HIDE, TRUE, &status);
if (!SUCCEEDED(hr)) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
if (status != 0) {
// Run again without /s, so the user can see the error
wsprintf(args, L"%ls\"%ls\"", state ? L"" : L"/u ", path);
hr = Exec(NULL, regsvr32, args, NULL, SW_SHOWDEFAULT, TRUE, &status);
}
return status == 0 ? S_OK : E_FAIL;
}
HRESULT RegisterServer(HWND hwnd, BOOL state, BOOL forLaunch) {
// Ensure elevation
HRESULT hr = S_OK;
LPWSTR installPath;
LPWSTR dllPath;
if (!IsUserAdmin()) {
LPWSTR args = (LPWSTR)LocalAlloc(LPTR, 512 * sizeof(WCHAR));
wsprintf(args, L"%ls %i", state ? L"/regserver" : L"/unregserver", hwnd);
DWORD code;
hr = SelfElevate(args, &code);
if (!SUCCEEDED(hr)) {
// Ignore error on cancelling UAC dialog
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
hr = S_OK;
}
goto end;
}
hr = HRESULT_FROM_WIN32(code);
goto end;
}
hr = GetInstallPath(&installPath);
if (!SUCCEEDED(hr)) {
goto end;
}
dllPath = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
wsprintf(dllPath, L"%ls\\LegacyUpdate.dll", installPath);
#ifdef _DEBUG
// Warn if registration path differs, to help with debugging
LPWSTR currentPath;
hr = GetRegistryString(HKEY_CLASSES_ROOT, L"CLSID\\{AD28E0DF-5F5A-40B5-9432-85EFD97D1F9F}\\InprocServer32", NULL, KEY_WOW64_64KEY, &currentPath, NULL);
if (SUCCEEDED(hr) && wcscmp(currentPath, dllPath) != 0) {
if (MsgBox(hwnd, L"DEBUG: Native dll currently registered at a different path. Override?", currentPath, MB_YESNO) != IDYES) {
hr = S_OK;
goto end;
}
}
#endif
hr = RegisterDllInternal(dllPath, state);
if (!SUCCEEDED(hr)) {
// Try external registration
if (SUCCEEDED(RegisterDllExternal(dllPath, state))) {
hr = S_OK;
} else {
goto end;
}
}
#if _WIN64
if (!SUCCEEDED(hr)) {
goto end;
}
wsprintf(dllPath, L"%ls\\LegacyUpdate32.dll", installPath);
#ifdef _DEBUG
// Warn if registration path differs, to help with debugging
hr = GetRegistryString(HKEY_CLASSES_ROOT, L"CLSID\\{AD28E0DF-5F5A-40B5-9432-85EFD97D1F9F}\\InprocServer32", NULL, KEY_WOW64_32KEY, &currentPath, NULL);
if (SUCCEEDED(hr) && wcscmp(currentPath, dllPath) != 0) {
if (MsgBox(hwnd, L"DEBUG: 32-bit dll currently registered at a different path. Override?", currentPath, MB_YESNO) != IDYES) {
hr = S_OK;
goto end;
}
}
#endif
hr = RegisterDllExternal(dllPath, state);
#endif
end:
if (installPath) {
LocalFree(installPath);
}
if (dllPath) {
LocalFree(dllPath);
}
if (!SUCCEEDED(hr)) {
LPWSTR title = state
? L"Failed to register Legacy Update ActiveX control"
: L"Failed to unregister Legacy Update ActiveX control";
MsgBox(hwnd, title, GetMessageForHresult(hr), MB_ICONERROR);
}
if (!forLaunch) {
PostQuitMessage(hr);
}
return hr;
}

View File

@ -0,0 +1,5 @@
#pragma once
#include <windows.h>
HRESULT RegisterServer(HWND hwnd, BOOL state, BOOL forLaunch);

12
launcher/SelfElevate.c Normal file
View File

@ -0,0 +1,12 @@
#include "SelfElevate.h"
#include <windows.h>
#include "Exec.h"
#include "VersionInfo.h"
HRESULT SelfElevate(LPWSTR args, LPDWORD code) {
LPWSTR fileName;
GetOwnFileName(&fileName);
HRESULT hr = Exec(L"runas", fileName, args, NULL, SW_SHOWDEFAULT, TRUE, code);
LocalFree(fileName);
return hr;
}

5
launcher/SelfElevate.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <windows.h>
HRESULT SelfElevate(LPWSTR args, LPDWORD code);

138
launcher/main.c Normal file
View File

@ -0,0 +1,138 @@
#include "stdafx.h"
#include "main.h"
#include "resource.h"
#include <windows.h>
#include <commctrl.h>
#include "MsgBox.h"
#include "RegisterServer.h"
#include "Startup.h"
HINSTANCE g_hInstance;
extern void LaunchUpdateSite(int argc, LPWSTR *argv, int nCmdShow);
extern void LaunchOptions(int nCmdShow);
extern void LaunchLog(int nCmdShow);
extern void RunOnce();
typedef enum Action {
ActionLaunch,
ActionOptions,
ActionLog,
ActionRunOnce,
ActionRegServer,
ActionUnregServer
} Action;
static const LPWSTR actions[] = {
L"/launch",
L"/options",
L"/log",
L"/runonce",
L"/regserver",
L"/unregserver",
NULL
};
EXTERN_C __declspec(dllexport)
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
g_hInstance = hInstance;
Startup();
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (!SUCCEEDED(hr)) {
ExitProcess(hr);
return hr;
}
int argc;
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
LPWSTR actionFlag = L"/launch";
if (argc > 1) {
actionFlag = argv[1];
}
// All remaining args past the action
LPWSTR *flags = {0};
int flagsCount = 0;
if (argc > 2) {
flags = &argv[2];
flagsCount = argc - 2;
}
Action action = -1;
for (int i = 0; actions[i] != NULL; i++) {
if (wcscmp(actionFlag, actions[i]) == 0) {
action = i;
break;
}
}
switch (action) {
case ActionLaunch:
LaunchUpdateSite(flagsCount, flags, nCmdShow);
break;
case ActionOptions:
LaunchOptions(nCmdShow);
break;
case ActionLog:
LaunchLog(nCmdShow);
break;
case ActionRunOnce:
RunOnce();
break;
case ActionRegServer:
case ActionUnregServer: {
BOOL state = action == ActionRegServer;
HWND hwnd = flagsCount > 0 ? (HWND)(intptr_t)wcstol(flags[0], NULL, 10) : 0;
RegisterServer(hwnd, state, FALSE);
break;
}
default: {
const LPWSTR usage = L""
L"LegacyUpdate.exe [/launch|/regserver|/unregserver]\n"
L"\n"
L"/launch\n"
L" Launch Legacy Update website in Internet Explorer\n"
L"\n"
L"/options\n"
L" Open the Windows Update Options control panel\n"
L"\n"
L"/log\n"
L" Open the Windows Update log file\n"
L"\n"
L"/regserver\n"
L" Register ActiveX control\n"
L"\n"
L"/unregserver\n"
L" Unregister ActiveX control\n"
L"\n"
L"If no parameters are provided, /launch is assumed.";
MsgBox(NULL, L"LegacyUpdate.exe usage", usage, MB_OK);
PostQuitMessage(1);
break;
}
}
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) == 1) {
TranslateMessage(&msg);
DispatchMessage(&msg);
switch (msg.message) {
case WM_QUIT:
case WM_DESTROY:
break;
}
}
CoUninitialize();
ExitProcess(msg.wParam);
return msg.wParam;
}

1
launcher/main.h Normal file
View File

@ -0,0 +1 @@
EXTERN_C HINSTANCE g_hInstance;

30
launcher/manifest.xml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<dependency>
<dependentAssembly>
<assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!-- Windows Vista -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- Windows 7 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <!-- Windows 8 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!-- Windows 8.1 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> <!-- Windows 10 -->
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>

11
launcher/resource.h Normal file
View File

@ -0,0 +1,11 @@
#define IDR_CPLTASKS 202
#define IDI_APPICON 100
#define IDS_LEGACYUPDATEOCX 1
#define IDS_LEGACYUPDATE 2
#define IDS_CHECKFORUPDATES 3
#define IDS_CHECKFORUPDATES_ALT 4
#define IDS_IENOTINSTALLED 5
#define ID_MANIFEST 1

95
launcher/resource.rc Normal file
View File

@ -0,0 +1,95 @@
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include <windows.h>
#include "Version.h"
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(65001)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,VERSION_BUILD
PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,VERSION_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Hashbang Productions"
VALUE "FileDescription", "Legacy Update"
VALUE "FileVersion", VERSION_STRING
VALUE "InternalName", "LegacyUpdate.exe"
VALUE "LegalCopyright", "© Hashbang Productions. All rights reserved."
VALUE "OriginalFilename", "LegacyUpdate.exe"
VALUE "ProductName", "Legacy Update"
VALUE "ProductVersion", VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPICON ICON "../LegacyUpdate/icon.ico"
/////////////////////////////////////////////////////////////////////////////
//
// XML
//
IDR_CPLTASKS XML "CplTasks.xml"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_LEGACYUPDATEOCX "Legacy Update Control"
IDS_LEGACYUPDATE "Legacy Update"
IDS_CHECKFORUPDATES "Check for updates"
IDS_CHECKFORUPDATES_ALT "Check for software and driver updates via Legacy Update."
IDS_IENOTINSTALLED "Internet Explorer is not installed. Use Optional Features in Control Panel to install it before using Legacy Update."
END
/////////////////////////////////////////////////////////////////////////////
//
// Manifest
//
ID_MANIFEST RT_MANIFEST "manifest.xml"
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////

23
launcher/stdafx.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#ifndef STRICT
#define STRICT
#endif
#define WINVER _WIN32_WINNT_WIN2K
#define _WIN32_WINNT _WIN32_WINNT_WIN2K
// Use msvcrt stdio functions
#define __USE_MINGW_ANSI_STDIO 0
// Enable comctl 6.0 (visual styles)
#define ISOLATION_AWARE_ENABLED 1
// Enable COM C interfaces
#define CINTERFACE
#define COBJMACROS
#define INITGUID
#include "resource.h"
#include <windows.h>
#include "Trace.h"

View File

@ -0,0 +1,64 @@
#include <windows.h>
#include <nsis/pluginapi.h>
#include <exdisp.h>
const LPWSTR LegacyUpdateSiteURLHttp = L"http://legacyupdate.net/";
const LPWSTR LegacyUpdateSiteURLHttps = L"https://legacyupdate.net/";
PLUGIN_METHOD(CloseIEWindows) {
PLUGIN_INIT();
// Find and close IE windows that might have the ActiveX control loaded
IShellWindows *windows;
HRESULT hr = CoCreateInstance(&CLSID_ShellWindows, NULL, CLSCTX_ALL, &IID_IShellWindows, (void **)&windows);
if (!SUCCEEDED(hr)) {
goto end;
}
long count;
hr = IShellWindows_get_Count(windows, &count);
if (!SUCCEEDED(hr)) {
goto end;
}
VARIANT index = {0};
index.vt = VT_I4;
for (long i = 0; i <= count; i++) {
IDispatch *item;
index.lVal = i;
hr = IShellWindows_Item(windows, index, &item);
if (!SUCCEEDED(hr) || !item) {
continue;
}
IWebBrowser2 *browser;
hr = IDispatch_QueryInterface(item, &IID_IWebBrowser2, (void **)&browser);
IDispatch_Release(item);
if (!SUCCEEDED(hr)) {
continue;
}
BSTR location;
hr = IWebBrowser2_get_LocationURL(browser, &location);
if (!SUCCEEDED(hr)) {
IWebBrowser2_Release(browser);
continue;
}
if (wcsstr(location, LegacyUpdateSiteURLHttp) != NULL || wcsstr(location, LegacyUpdateSiteURLHttps) != NULL) {
hr = IWebBrowser2_Quit(browser);
}
SysFreeString(location);
IWebBrowser2_Release(browser);
}
end:
if (windows) {
IShellWindows_Release(windows);
}
pushint(hr);
}

377
nsisplugin/DialogInit.c Normal file
View File

@ -0,0 +1,377 @@
#include "stdafx.h"
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#include <windows.h>
#include <nsis/pluginapi.h>
#include <shlwapi.h>
#include <uxtheme.h>
#include <vsstyle.h>
#include <windowsx.h>
#include "main.h"
#include "LoadImage.h"
#include "Registry.h"
#include "VersionInfo.h"
#ifndef WM_DWMCOMPOSITIONCHANGED
#define WM_DWMCOMPOSITIONCHANGED 0x031e
#endif
#define DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 19
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#define DWMWA_CAPTION_COLOR 35
#define DWMWA_SYSTEMBACKDROP_TYPE 38
#define DWMWA_COLOR_NONE 0xFFFFFFFE
#define DWMSBT_MAINWINDOW 2
#define IDI_BANNER_WORDMARK_LIGHT 1337
#define IDI_BANNER_WORDMARK_DARK 1338
#define IDI_BANNER_WORDMARK_GLOW 1339
typedef HRESULT (WINAPI *_DwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset);
typedef HRESULT (WINAPI *_DwmIsCompositionEnabled)(BOOL *pfEnabled);
typedef HRESULT (WINAPI *_DwmDefWindowProc)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
typedef HRESULT (WINAPI *_DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
typedef HRESULT (WINAPI *_SetWindowThemeAttribute)(HWND hwnd, enum WINDOWTHEMEATTRIBUTETYPE eAttribute, PVOID pvAttribute, DWORD cbAttribute);
typedef BOOL (WINAPI *_IsThemeActive)();
typedef HTHEME (WINAPI *_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
typedef HRESULT (WINAPI *_CloseThemeData)(HTHEME hTheme);
typedef HRESULT (WINAPI *_DrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect);
static _DwmExtendFrameIntoClientArea $DwmExtendFrameIntoClientArea;
static _DwmIsCompositionEnabled $DwmIsCompositionEnabled;
static _DwmDefWindowProc $DwmDefWindowProc;
static _DwmSetWindowAttribute $DwmSetWindowAttribute;
static _SetWindowThemeAttribute $SetWindowThemeAttribute;
static _IsThemeActive $IsThemeActive;
static _OpenThemeData $OpenThemeData;
static _CloseThemeData $CloseThemeData;
static _DrawThemeBackground $DrawThemeBackground;
typedef enum Theme {
ThemeUnknown = -1,
ThemeClassic,
ThemeBasic,
ThemeAeroLight,
ThemeAeroDark
} Theme;
static HBITMAP g_bannerWordmark;
static HBITMAP g_bannerWordmarkGlow;
static HTHEME g_aeroTheme;
static Theme g_theme = ThemeUnknown;
static WNDPROC g_dialogOrigWndProc;
static WNDPROC g_bannerOrigWndProc;
static WNDPROC g_bottomOrigWndProc;
static Theme GetTheme() {
BOOL enabled;
if (!$DwmIsCompositionEnabled || !$IsThemeActive || !SUCCEEDED($DwmIsCompositionEnabled(&enabled))) {
return ThemeClassic;
}
if (enabled) {
DWORD light = 1;
if (AtLeastWin10_1809()) {
GetRegistryDword(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", L"AppsUseLightTheme", 0, &light);
}
return light ? ThemeAeroLight : ThemeAeroDark;
}
return $IsThemeActive() ? ThemeBasic : ThemeClassic;
}
static void ConfigureWindow() {
HWND bannerWindow = GetDlgItem(g_hwndParent, 1046);
HWND bannerDivider = GetDlgItem(g_hwndParent, 1047);
HWND bottomDivider = GetDlgItem(g_hwndParent, 6900);
if (!bannerWindow || !bannerDivider || !bottomDivider) {
return;
}
Theme theme = GetTheme();
if (g_theme != theme) {
g_theme = theme;
MARGINS margins = {0};
if (theme >= ThemeAeroLight) {
// Set glass area
RECT rect;
GetWindowRect(bannerWindow, &rect);
margins.cyTopHeight = rect.bottom - rect.top;
}
if ($DwmExtendFrameIntoClientArea) {
$DwmExtendFrameIntoClientArea(g_hwndParent, &margins);
}
ShowWindow(bannerDivider, theme >= ThemeBasic ? SW_HIDE : SW_SHOW);
ShowWindow(bottomDivider, theme >= ThemeBasic ? SW_HIDE : SW_SHOW);
if (g_theme >= ThemeBasic) {
DWORD wordmark = g_theme == ThemeAeroDark ? IDI_BANNER_WORDMARK_DARK : IDI_BANNER_WORDMARK_LIGHT;
g_bannerWordmark = LoadPNGResource(NULL, MAKEINTRESOURCE(wordmark), L"PNG");
if (g_theme >= ThemeAeroLight && AtMostWin7()) {
g_bannerWordmarkGlow = LoadPNGResource(NULL, MAKEINTRESOURCE(IDI_BANNER_WORDMARK_GLOW), L"PNG");
}
} else {
DeleteObject(g_bannerWordmark);
DeleteObject(g_bannerWordmarkGlow);
g_bannerWordmark = NULL;
g_bannerWordmarkGlow = NULL;
}
// Set dark mode state
if (AtLeastWin10_1809() && $DwmSetWindowAttribute) {
DWORD attr = AtLeastWin10_2004() ? DWMWA_USE_IMMERSIVE_DARK_MODE : DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;
DWORD value = g_theme == ThemeAeroDark;
$DwmSetWindowAttribute(g_hwndParent, attr, &value, sizeof(value));
}
}
}
static LRESULT CALLBACK BannerWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (g_theme < ThemeBasic) {
return CallWindowProc(g_bannerOrigWndProc, hwnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rect;
GetClientRect(hwnd, &rect);
// Draw base color for glass area
FillRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
// Draw Aero Basic titlebar
if (g_theme == ThemeBasic && g_aeroTheme && $DrawThemeBackground) {
int state = GetActiveWindow() == g_hwndParent ? AW_S_TITLEBAR_ACTIVE : AW_S_TITLEBAR_INACTIVE;
$DrawThemeBackground(g_aeroTheme, hdc, AW_TITLEBAR, state, &rect, NULL);
}
float scale = (float)GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f;
BLENDFUNCTION blendFunc;
blendFunc.BlendOp = AC_SRC_OVER;
blendFunc.BlendFlags = 0;
blendFunc.SourceConstantAlpha = 0xFF;
blendFunc.AlphaFormat = AC_SRC_ALPHA;
// Draw wordmark with alpha blending
if (g_bannerWordmarkGlow) {
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_bannerWordmarkGlow);
BITMAP bitmap;
GetObject(g_bannerWordmarkGlow, sizeof(bitmap), &bitmap);
LONG width = bitmap.bmWidth * scale;
LONG height = bitmap.bmHeight * scale;
LONG x = (rect.right - rect.left - width) / 2;
LONG y = (rect.bottom - rect.top - height) / 2;
SetStretchBltMode(hdc, HALFTONE);
AlphaBlend(hdc,
x, y, width, height, hdcMem,
0, 0, bitmap.bmWidth, bitmap.bmHeight, blendFunc);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
}
if (g_bannerWordmark) {
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_bannerWordmark);
BITMAP bitmap;
GetObject(g_bannerWordmark, sizeof(bitmap), &bitmap);
LONG width = bitmap.bmWidth * scale;
LONG height = bitmap.bmHeight * scale;
LONG x = (rect.right - rect.left - width) / 2;
LONG y = ((rect.bottom - rect.top - height) / 2) - (1 * scale);
SetStretchBltMode(hdc, HALFTONE);
AlphaBlend(hdc,
x, y, width, height, hdcMem,
0, 0, bitmap.bmWidth, bitmap.bmHeight, blendFunc);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
}
EndPaint(hwnd, &ps);
return 0;
}
case WM_ERASEBKGND:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
case WM_NCHITTEST:
// Pass through to parent
return HTTRANSPARENT;
}
if (!g_bannerOrigWndProc) {
return 0;
}
return CallWindowProc(g_bannerOrigWndProc, hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK BottomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_PAINT: {
// Draw command area background (grey with divider line)
if (g_theme < ThemeBasic || !g_aeroTheme || !$DrawThemeBackground) {
break;
}
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rect;
GetClientRect(hwnd, &rect);
$DrawThemeBackground(g_aeroTheme, hdc, AW_COMMANDAREA, 0, &rect, NULL);
EndPaint(hwnd, &ps);
return 0;
}
}
if (!g_bottomOrigWndProc) {
return 0;
}
return CallWindowProc(g_bottomOrigWndProc, hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (g_theme >= ThemeAeroLight && $DwmDefWindowProc) {
LRESULT lRet = 0;
if ($DwmDefWindowProc(hwnd, uMsg, wParam, lParam, &lRet)) {
return lRet;
}
}
switch (uMsg) {
case WM_THEMECHANGED:
case WM_DWMCOMPOSITIONCHANGED:
ConfigureWindow();
break;
case WM_ACTIVATE:
case WM_NCACTIVATE:
// Redraw banner on activation
if (g_theme == ThemeBasic) {
InvalidateRect(GetDlgItem(hwnd, 1046), NULL, FALSE);
}
break;
case WM_NCHITTEST: {
if (g_theme < ThemeBasic) {
break;
}
// Allow drag in the header area
HWND bannerWindow = GetDlgItem(hwnd, 1046);
if (!bannerWindow) {
break;
}
POINT hit = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
ScreenToClient(hwnd, &hit);
RECT rect;
GetWindowRect(bannerWindow, &rect);
rect.right -= rect.left;
rect.bottom -= rect.top;
rect.left = 0;
rect.top = 0;
if (PtInRect(&rect, hit)) {
return HTCAPTION;
}
break;
}
}
if (!g_dialogOrigWndProc) {
return 0;
}
return CallWindowProc(g_dialogOrigWndProc, hwnd, uMsg, wParam, lParam);
}
static UINT_PTR NSISPluginCallback(enum NSPIM event) {
// Does nothing, but keeping a callback registered prevents NSIS from unloading the plugin
return 0;
}
PLUGIN_METHOD(DialogInit) {
PLUGIN_INIT();
if (g_dialogOrigWndProc) {
return;
}
extra->RegisterPluginCallback(g_hInstance, NSISPluginCallback);
// Get symbols
HMODULE dwmapi = LoadLibrary(L"dwmapi.dll");
if (dwmapi) {
$DwmExtendFrameIntoClientArea = (_DwmExtendFrameIntoClientArea)GetProcAddress(dwmapi, "DwmExtendFrameIntoClientArea");
$DwmIsCompositionEnabled = (_DwmIsCompositionEnabled)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
$DwmDefWindowProc = (_DwmDefWindowProc)GetProcAddress(dwmapi, "DwmDefWindowProc");
$DwmSetWindowAttribute = (_DwmSetWindowAttribute)GetProcAddress(dwmapi, "DwmSetWindowAttribute");
}
HMODULE uxtheme = LoadLibrary(L"uxtheme.dll");
if (uxtheme) {
$SetWindowThemeAttribute = (_SetWindowThemeAttribute)GetProcAddress(uxtheme, "SetWindowThemeAttribute");
$IsThemeActive = (_IsThemeActive)GetProcAddress(uxtheme, "IsThemeActive");
$OpenThemeData = (_OpenThemeData)GetProcAddress(uxtheme, "OpenThemeData");
$CloseThemeData = (_CloseThemeData)GetProcAddress(uxtheme, "CloseThemeData");
$DrawThemeBackground = (_DrawThemeBackground)GetProcAddress(uxtheme, "DrawThemeBackground");
}
// Get AeroWizard theme
if ($OpenThemeData) {
g_aeroTheme = $OpenThemeData(g_hwndParent, L"AeroWizard");
}
// Hide title caption/icon
if ($SetWindowThemeAttribute) {
WTA_OPTIONS options;
options.dwFlags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
options.dwMask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
$SetWindowThemeAttribute(g_hwndParent, WTA_NONCLIENT, &options, sizeof(options));
}
// Enable Acrylic blur
if (AtLeastWin11_21H1() && $DwmSetWindowAttribute) {
// I stole this undocumented 1029 attr from Microsoft Store's StoreInstaller.exe
BOOL modern = AtLeastWin11_22H2();
DWORD attr = modern ? DWMWA_SYSTEMBACKDROP_TYPE : 1029;
DWORD value = modern ? DWMSBT_MAINWINDOW : 1;
$DwmSetWindowAttribute(g_hwndParent, attr, &value, sizeof(value));
// Hide caption background
value = DWMWA_COLOR_NONE;
$DwmSetWindowAttribute(g_hwndParent, DWMWA_CAPTION_COLOR, &value, sizeof(value));
}
// Set up extended client frame
ConfigureWindow();
// Set up window procedures
HWND bannerWindow = GetDlgItem(g_hwndParent, 1046);
HWND bottomWindow = GetDlgItem(g_hwndParent, 6901);
g_dialogOrigWndProc = (WNDPROC)SetWindowLongPtr(g_hwndParent, GWLP_WNDPROC, (LONG_PTR)MainWndProc);
g_bannerOrigWndProc = (WNDPROC)SetWindowLongPtr(bannerWindow, GWLP_WNDPROC, (LONG_PTR)BannerWndProc);
g_bottomOrigWndProc = (WNDPROC)SetWindowLongPtr(bottomWindow, GWLP_WNDPROC, (LONG_PTR)BottomWndProc);
}

602
nsisplugin/Exec.c Normal file
View File

@ -0,0 +1,602 @@
/*
Copyright (C) 2002 Robert Rainwater <rrainwater@yahoo.com>
Copyright (C) 2002-2023 Nullsoft and Contributors
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <windows.h>
#include <commctrl.h>
#include <winnt.h>
#include <nsis/pluginapi.h> // nsis plugin
#include "main.h"
#if defined(_MSC_VER) && !defined(GetVersion)
#if _MSC_VER >= 1500
FORCEINLINE DWORD NoDepr_GetVersion() { __pragma(warning(push))__pragma(warning(disable:4996)) DWORD r = GetVersion(); __pragma(warning(pop)) return r; }
#define GetVersion NoDepr_GetVersion
#endif //~ _MSC_VER >= 1500
#endif //~ _MSC_VER
#define TAB_REPLACE _T(" ")
#define TAB_REPLACE_SIZE (sizeof(TAB_REPLACE) - sizeof(_T("")))
#define TAB_REPLACE_CCH (TAB_REPLACE_SIZE / sizeof(_T("")))
enum { MODE_IGNOREOUTPUT = 0, MODE_LINES = 1, MODE_STACK = 2 };
#define LOOPTIMEOUT 100
static HWND g_hwndList;
static void ExecScript(BOOL log);
static TCHAR *my_strstr(TCHAR *a, TCHAR *b);
static unsigned int my_atoi(TCHAR *s);
static int WINAPI AsExeWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow);
PLUGIN_METHOD(Exec) {
PLUGIN_INIT();
ExecScript(MODE_IGNOREOUTPUT);
}
PLUGIN_METHOD(ExecToLog) {
PLUGIN_INIT();
ExecScript(extra->exec_flags->status_update & 1 ? MODE_LINES : MODE_IGNOREOUTPUT);
}
PLUGIN_METHOD(ExecToStack) {
PLUGIN_INIT();
ExecScript(MODE_STACK);
}
static BOOL IsLeadSurrogateUTF16(unsigned short c) { return c >= 0xd800 && c <= 0xdbff; }
static BOOL IsTrailSurrogateUTF16(unsigned short c) { return c >= 0xdc00 && c <= 0xdfff; }
static PWSTR MyCharNext(PCWSTR p)
{
// Note: This is wrong for surrogate pair combining characters but CharNextW does
// not support surrogate pairs correctly so we have to manually handle the pairs.
if (!p[0]) return (PWSTR) p;
if (IsLeadSurrogateUTF16(p[0]) && IsTrailSurrogateUTF16(p[1])) return (PWSTR) p + 2; // Current is a surrogate pair, we incorrectly assume that it is not followed by combining characters.
if (IsLeadSurrogateUTF16(p[1]) && IsTrailSurrogateUTF16(p[2])) return (PWSTR) p + 1; // Next is a surrogate pair, we incorrectly assume that it is not a combining character for the current character.
return (CharNextW)(p);
}
#define CharNextW MyCharNext
static void TruncateStringUTF16LE(LPWSTR Buffer, SIZE_T Length, LPCWSTR Overflow, SIZE_T lenOver) {
if (Length) {
LPWSTR p = &Buffer[Length - 1];
UINT stripBaseCharIfCuttingCombining = TRUE;
// CharNextW is buggy on XP&2003 but we don't care enough to call GetStringTypeW (http://archives.miloush.net/michkap/archive/2005/01/30/363420.html)
if (stripBaseCharIfCuttingCombining && lenOver) {
WCHAR buf[] = { *p, Overflow[0], lenOver > 1 ? Overflow[1] : L' ', L'\0' };
for (;;) {
BOOL comb = CharNextW(buf) > buf + 1;
if (!comb || p < Buffer) break;
*((WORD*)((BYTE*)&buf[1])) = *((WORD*)((BYTE*)&buf[0]));
buf[0] = *p;
*p-- = L'\0';
}
}
if (IsLeadSurrogateUTF16(*p)) {
*p = L'\0'; // Avoid incomplete pair
}
}
}
static void TruncateStringMB(UINT Codepage, LPSTR Buffer, SIZE_T Length, unsigned short OverflowCh) {
if (Length) {
CHAR *p = &Buffer[Length - 1], buf[] = { *p, ' ', ' ', '\0' };
if (CharNextExA(Codepage, buf, 0) > buf + 1) { // Remove incomplete DBCS character?
*p = '\0';
}
}
}
static BOOL IsWOW64() {
#ifdef _WIN64
return FALSE;
#else
typedef BOOL (WINAPI*ISWOW64PROCESS)(HANDLE, BOOL*);
ISWOW64PROCESS pfIsWow64Process;
typedef BOOL (WINAPI*ISWOW64PROCESS2)(HANDLE, USHORT*, USHORT*);
ISWOW64PROCESS2 pfIsWow64Process2;
HANDLE hProcess = GetCurrentProcess();
HMODULE hK32 = GetModuleHandleA("KERNEL32");
UINT_PTR retval;
USHORT appmach, image_file_machine_unknown = 0;
CHAR funcnam[16]
#if defined(_MSC_VER) && (_MSC_VER-0 <= 1400)
= "IsWow64Process2"; // MOVSD * 4
#else
; lstrcpyA(funcnam, "IsWow64Process2");
#endif
pfIsWow64Process2 = (ISWOW64PROCESS2) GetProcAddress(hK32, funcnam);
if (pfIsWow64Process2 && pfIsWow64Process2(hProcess, &appmach, NULL)) {
retval = image_file_machine_unknown != appmach;
}
else {
BOOL wow64;
pfIsWow64Process = (ISWOW64PROCESS) GetProcAddress(hK32, (funcnam[14] = '\0', funcnam));
retval = (UINT_PTR) pfIsWow64Process;
if (pfIsWow64Process && (retval = pfIsWow64Process(hProcess, &wow64))) {
retval = wow64;
}
}
return (BOOL) (UINT) retval;
#endif
}
// Tim Kosse's LogMessage
#ifdef UNICODE
static void LogMessage(const TCHAR *pStr, BOOL bOEM) {
#else
static void LogMessage(TCHAR *pStr, BOOL bOEM) {
#endif
LVITEM item;
int nItemCount;
if (!g_hwndList) return;
//if (!*pStr) return;
#ifndef UNICODE
if (bOEM == TRUE) OemToCharBuff(pStr, pStr, lstrlen(pStr));
#endif
nItemCount=(int) SendMessage(g_hwndList, LVM_GETITEMCOUNT, 0, 0);
item.mask=LVIF_TEXT;
item.pszText=(TCHAR *)pStr;
item.cchTextMax=0;
item.iItem=nItemCount, item.iSubItem=0;
ListView_InsertItem(g_hwndList, &item);
ListView_EnsureVisible(g_hwndList, item.iItem, 0);
}
void ExecScript(int mode) {
TCHAR szRet[128];
TCHAR meDLLPath[MAX_PATH];
TCHAR *g_exec, *executor;
TCHAR *pExec;
int ignoreData = mode == MODE_IGNOREOUTPUT;
int logMode = mode == MODE_LINES, stackMode = mode == MODE_STACK;
unsigned int to, tabExpandLength = logMode ? TAB_REPLACE_CCH : 0, codepage;
BOOL bOEM, forceNarrowInput = FALSE;
*szRet = _T('\0');
if (!IsWOW64()) {
TCHAR* p;
int nComSpecSize;
nComSpecSize = GetModuleFileName(g_hInstance, meDLLPath, MAX_PATH) + 2; // 2 chars for quotes
g_exec = (TCHAR *)GlobalAlloc(GPTR, sizeof(TCHAR) * (g_stringsize+nComSpecSize+2)); // 1 for space, 1 for null
p = meDLLPath + nComSpecSize - 2; // point p at null char of meDLLPath
*g_exec = _T('"');
executor = g_exec + 1;
// Look for the last '\' in path.
do
{
if (*p == _T('\\'))
break;
p = CharPrev(meDLLPath, p);
}
while (p > meDLLPath);
if (p == meDLLPath)
{
// bad path
pushstring(_T("error"));
GlobalFree(g_exec);
return;
}
*p = 0;
GetTempFileName(meDLLPath, _T("ns"), 0, executor); // executor = new temp file name in module path.
*p = _T('\\');
if (CopyFile(meDLLPath, executor, FALSE)) // copy current DLL to temp file in module path.
{
HANDLE hFile, hMapping;
LPBYTE pMapView;
PIMAGE_NT_HEADERS pNTHeaders;
hFile = CreateFile(executor, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, 0);
hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
pMapView = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);
if (pMapView)
{
pNTHeaders = (PIMAGE_NT_HEADERS)(pMapView + ((PIMAGE_DOS_HEADER)pMapView)->e_lfanew);
// Turning the copied DLL into a stripped down executable.
pNTHeaders->FileHeader.Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE;
// Windows character-mode user interface (CUI) subsystem.
pNTHeaders->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
// g_hInst is assumed to be the very base of the DLL in memory.
// WinMain will have the address of the WinMain function in memory.
// Getting the difference gets you the relative location of the
// WinMain function.
pNTHeaders->OptionalHeader.AddressOfEntryPoint = (DWORD) ((DWORD_PTR)AsExeWinMain - (DWORD_PTR)g_hInstance);
UnmapViewOfFile(pMapView);
}
CloseHandle(hMapping);
CloseHandle(hFile);
}
lstrcat(g_exec, _T("\""));
// add space
pExec = g_exec + lstrlen(g_exec);
*pExec = _T(' ');
pExec++;
} else {
executor = NULL;
g_exec = (TCHAR *)GlobalAlloc(GPTR, sizeof(TCHAR) * (g_stringsize+1)); // 1 for NULL
pExec = g_exec;
}
to = 0; // default is no timeout
bOEM = FALSE; // default is no OEM->ANSI conversion
g_hwndList = NULL;
// g_hwndParent = the caller, usually NSIS installer.
if (g_hwndParent) // The window class name for dialog boxes is "#32770"
g_hwndList = FindWindowEx(FindWindowEx(g_hwndParent, NULL, _T("#32770"), NULL), NULL, _T("SysListView32"), NULL);
// g_exec is the complete command to run: It has the copy of this DLL turned
// into an executable right now.
params:
// Get the command I need to run from the NSIS stack.
popstring(pExec);
if (my_strstr(pExec, _T("/TIMEOUT=")) == pExec) {
TCHAR *szTimeout = pExec + 9;
to = my_atoi(szTimeout);
*pExec = 0;
goto params;
}
if (!lstrcmpi(pExec, _T("/OEM"))) {
bOEM = forceNarrowInput = TRUE;
*pExec = 0;
goto params;
}
if (!lstrcmpi(pExec, _T("/MBCS"))) {
forceNarrowInput = TRUE;
*pExec = 0;
goto params;
}
if (!pExec[0])
{
pushstring(_T("error"));
if (pExec-2 >= g_exec)
*(pExec-2) = _T('\0'); // skip space and quote
if (executor) DeleteFile(executor);
GlobalFree(g_exec);
return;
}
// Got all the params off the stack.
{
STARTUPINFO si = { sizeof(si), };
SECURITY_ATTRIBUTES sa = { sizeof(sa), };
SECURITY_DESCRIPTOR sd = { 0, };
PROCESS_INFORMATION pi;
const BOOL isNT = sizeof(void*) > 4 || (GetVersion() < 0x80000000);
HANDLE newstdout = 0, read_stdout = 0;
HANDLE newstdin = 0, read_stdin = 0;
int utfSource = sizeof(TCHAR) > 1 && !forceNarrowInput ? -1 : FALSE, utfOutput = sizeof(TCHAR) > 1;
DWORD cbRead, dwLastOutput;
DWORD dwExit = 0, waitResult = WAIT_TIMEOUT;
static BYTE bufSrc[1024];
BYTE *pSrc;
SIZE_T cbSrcTot = sizeof(bufSrc), cbSrc = 0, cbSrcFree;
TCHAR *bufOutput = 0, *pNewAlloc, *pD;
SIZE_T cchAlloc, cbAlloc, cchFree;
#ifndef _MSC_VER // Avoid GCC "may be used uninitialized in this function" warnings
pD = NULL;
cchAlloc = 0;
#endif
pi.hProcess = pi.hThread = NULL;
codepage = bOEM ? CP_OEMCP : CP_ACP;
if (!ignoreData) {
cbAlloc = stackMode ? (g_stringsize * sizeof(TCHAR)) : sizeof(bufSrc) * 4, cchAlloc = cbAlloc / sizeof(TCHAR);
pD = bufOutput = GlobalAlloc(GPTR, cbAlloc + sizeof(TCHAR)); // Include "hidden" space for a \0
if (!bufOutput) {
lstrcpy(szRet, _T("error"));
goto done;
}
*bufOutput = _T('\0');
}
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if (isNT) {
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
sa.lpSecurityDescriptor = &sd;
}
if (!CreatePipe(&read_stdout, &newstdout, &sa, 0)) {
lstrcpy(szRet, _T("error"));
goto done;
}
if (!CreatePipe(&read_stdin, &newstdin, &sa, 0)) {
lstrcpy(szRet, _T("error"));
goto done;
}
GetStartupInfo(&si); // Why?
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdInput = newstdin;
si.hStdOutput = newstdout;
si.hStdError = newstdout;
if (!CreateProcess(NULL, g_exec, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
lstrcpy(szRet, _T("error"));
goto done;
}
// Now I'm talking with an executable copy of myself.
dwLastOutput = GetTickCount();
for (;;) {
TCHAR bufCh[2];
waitForProcess:
waitResult = WaitForSingleObject(pi.hProcess, 0);
GetExitCodeProcess(pi.hProcess, &dwExit);
readMore:
PeekNamedPipe(read_stdout, 0, 0, 0, &cbRead, NULL);
if (!cbRead) {
if (waitResult == WAIT_OBJECT_0) {
break; // No data in the pipe and process ended, we are done
}
if (to && GetTickCount() > dwLastOutput+to) {
TerminateProcess(pi.hProcess, -1);
lstrcpy(szRet, _T("timeout"));
}
else {
Sleep(LOOPTIMEOUT);
}
continue;
}
dwLastOutput = GetTickCount();
ReadFile(read_stdout, bufSrc + cbSrc, (DWORD) (cbSrcFree = cbSrcTot - cbSrc), &cbRead, NULL);
cbSrcFree -= cbRead, cbSrc = cbSrcTot - cbSrcFree;
pSrc = bufSrc;
if (utfSource < 0 && cbSrc) { // Simple UTF-16LE detection
#ifdef UNICODE
utfSource = IsTextUnicode(pSrc, (UINT) (cbSrc & ~1), NULL) != FALSE;
#else
utfSource = (cbSrc >= 3 && pSrc[0] && !pSrc[1]) || (cbSrc > 4 && pSrc[2] && !pSrc[3]); // Lame latin-only test
utfSource |= (cbSrc > 3 && pSrc[0] == 0xFF && pSrc[1] == 0xFE && (pSrc[2] | pSrc[3])); // Lame BOM test
#endif
}
if (ignoreData) {
cbSrc = 0; // Overwrite the whole buffer every read
continue;
}
if (!cbRead) {
continue; // No new data, read more before trying to parse
}
parseLines:
cchFree = cchAlloc - (pD - bufOutput);
for (;;) {
DWORD cbSrcChar = 1, cchDstChar, i;
*pD = _T('\0'); // Terminate output buffer because we can unexpectedly run out of data
if (!cbSrc) {
goto readMore;
}
if (utfSource) { // UTF-16LE --> ?:
if (cbSrc < 2) {
goto readMore;
}
if (utfOutput) { // UTF-16LE --> UTF-16LE:
bufCh[0] = ((TCHAR*)pSrc)[0], cbSrcChar = sizeof(WCHAR), cchDstChar = 1; // We only care about certain ASCII characters so we don't bother dealing with surrogate pairs.
}
else { // UTF-16LE --> DBCS
// TODO: This is tricky because we need the complete base character (or surrogate pair) and all the trailing combining characters for a grapheme in the buffer before we can call WideCharToMultiByte.
utfOutput = FALSE; // For now we just treat it as DBCS
continue;
}
}
else { // DBCS --> ?:
if (utfOutput) { // DBCS --> UTF-16LE:
BOOL isMb = IsDBCSLeadByteEx(codepage, ((CHAR*)pSrc)[0]);
if (isMb && cbSrc < ++cbSrcChar) {
goto readMore;
}
cchDstChar = MultiByteToWideChar(codepage, 0, (CHAR*)pSrc, cbSrcChar, (WCHAR*) bufCh, 2);
}
else { // DBCS --> DBCS:
bufCh[0] = ((CHAR*)pSrc)[0], cchDstChar = 1; // Note: OEM codepage will be converted by LogMessage
}
}
if (bufCh[0] == _T('\t') && tabExpandLength) { // Expand tab to spaces?
if (cchFree < tabExpandLength) {
goto resizeOutputBuffer;
}
lstrcpy(pD, TAB_REPLACE);
pD += tabExpandLength, cchFree -= tabExpandLength;
}
else if (bufCh[0] == _T('\r') && logMode) {
// Eating it
}
else if (bufCh[0] == _T('\n') && logMode) {
LogMessage(bufOutput, bOEM); // Output has already been \0 terminated
*(pD = bufOutput) = _T('\0'), cchFree = cchAlloc;
}
else {
if (cchFree < cchDstChar) {
SIZE_T cchOrgOffset;
resizeOutputBuffer:
if (stackMode) {
ignoreData = TRUE; // Buffer was already maximum for the NSIS stack, we cannot handle more data
if (utfOutput)
TruncateStringUTF16LE((LPWSTR) bufOutput, pD - bufOutput, (LPCWSTR) bufCh, cchDstChar);
else
TruncateStringMB(codepage, (LPSTR) bufOutput, pD - bufOutput, bufCh[0]);
goto waitForProcess;
}
cchAlloc += 1024, cbAlloc = cchAlloc / sizeof(TCHAR);
pNewAlloc = GlobalReAlloc(bufOutput, cbAlloc + sizeof(TCHAR),GPTR|GMEM_MOVEABLE); // Include "hidden" space for a \0
if (!pNewAlloc) {
lstrcpy(szRet, _T("error"));
ignoreData = TRUE;
goto waitForProcess;
}
cchOrgOffset = pD - bufOutput;
*(pD = (bufOutput = pNewAlloc) + cchOrgOffset) = _T('\0');
goto parseLines;
}
for (i = 0; i < cchDstChar; ++i) {
*pD++ = bufCh[i], --cchFree;
}
}
pSrc += cbSrcChar, cbSrc -= cbSrcChar;
}
}
done:
if (stackMode) pushstring(bufOutput);
if (logMode && *bufOutput) LogMessage(bufOutput,bOEM); // Write remaining output
if (dwExit == STATUS_ILLEGAL_INSTRUCTION)
lstrcpy(szRet, _T("error"));
if (!szRet[0]) wsprintf(szRet,_T("%d"),dwExit);
pushstring(szRet);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(newstdin);
CloseHandle(read_stdin);
if (pExec-2 >= g_exec)
*(pExec-2) = _T('\0'); // skip space and quote
if (executor)
DeleteFile(executor);
GlobalFree(g_exec);
if (bufOutput)
GlobalFree(bufOutput);
}
}
static TCHAR *my_strstr(TCHAR *a, TCHAR *b)
{
int l = lstrlen(b);
while (lstrlen(a) >= l)
{
TCHAR c = a[l];
a[l] = 0;
if (!lstrcmpi(a, b))
{
a[l] = c;
return a;
}
a[l] = c;
a = CharNext(a);
}
return NULL;
}
static unsigned int my_atoi(TCHAR *s) {
unsigned int v=0;
if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X'))) {
s+=2;
for (;;) {
int c=*s++;
if (c >= _T('0') && c <= _T('9')) c-=_T('0');
else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10;
else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10;
else break;
v<<=4;
v+=c;
}
}
else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0')) {
s++;
for (;;) {
int c=*s++;
if (c >= _T('0') && c <= _T('7')) c-=_T('0');
else break;
v<<=3;
v+=c;
}
}
else {
for (;;) {
int c=*s++ - _T('0');
if (c < 0 || c > 9) break;
v*=10;
v+=c;
}
}
return (int)v;
}
int WINAPI AsExeWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
DWORD Ret;
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
TCHAR command_line[1024]; //BUGBUG
TCHAR seekchar=_T(' ');
TCHAR *cmdline;
si.cb = sizeof(si);
// Make child process use this app's standard files. Not needed because the handles
// we created when executing this process were inheritable.
//si.dwFlags = STARTF_USESTDHANDLES;
//si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
//si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
//si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
lstrcpyn(command_line, GetCommandLine(), 1024);
cmdline = command_line;
if (*cmdline == _T('\"')) seekchar = *cmdline++;
while (*cmdline && *cmdline != seekchar) cmdline=CharNext(cmdline);
cmdline=CharNext(cmdline);
// skip any spaces before the arguments
while (*cmdline && *cmdline == _T(' ')) cmdline++;
Ret = CreateProcess (NULL, cmdline,
NULL, NULL,
TRUE, 0,
NULL, NULL,
&si, &pi
);
if (Ret)
{
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &Ret);
CloseHandle (pi.hProcess);
CloseHandle (pi.hThread);
ExitProcess(Ret);
}
else
{
ExitProcess(STATUS_ILLEGAL_INSTRUCTION);
}
return 0; // dummy
}

122
nsisplugin/IsActivated.c Normal file
View File

@ -0,0 +1,122 @@
#include <windows.h>
#include <nsis/pluginapi.h>
#include "main.h"
#include "WMI.h"
#include "VersionInfo.h"
#include "licdll.h"
#include <slpublic.h>
typedef HRESULT (WINAPI *_SLOpen)(HSLC *);
typedef HRESULT (WINAPI *_SLGetLicensingStatusInformation)(HSLC, const SLID *, DWORD, DWORD, UINT *, SL_LICENSING_STATUS **);
typedef HRESULT (WINAPI *_SLClose)(HSLC);
static _SLOpen $SLOpen;
static _SLClose $SLClose;
static _SLGetLicensingStatusInformation $SLGetLicensingStatusInformation;
static BOOL g_loadedLicenseStatus = FALSE;
static BOOL g_isActivated = TRUE;
PLUGIN_METHOD(IsActivated) {
PLUGIN_INIT();
// Get the Operating System Version information as well as the CPU architecture.
// We'll need this so that we activate the correct COM object on 64-bit versions
// of Windows XP and Windows Server 2003.
OSVERSIONINFOEX* versionInfo = GetVersionInfo();
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
// Activation is irrelevant prior to XP
if (g_loadedLicenseStatus || !AtLeastWinXP2002()) {
pushint(g_isActivated);
return;
}
g_loadedLicenseStatus = TRUE;
if (AtLeastWinVista()) {
// Vista+: Ask the Software Licensing Service
if (!$SLOpen) {
HMODULE slc = LoadLibrary(L"slc.dll");
$SLOpen = (_SLOpen)GetProcAddress(slc, "SLOpen");
$SLClose = (_SLClose)GetProcAddress(slc, "SLClose");
$SLGetLicensingStatusInformation = (_SLGetLicensingStatusInformation)GetProcAddress(slc, "SLGetLicensingStatusInformation");
}
if (!$SLOpen || !$SLClose || !$SLGetLicensingStatusInformation) {
TRACE(L"Failed to load slc.dll");
pushint(1);
return;
}
HSLC slc;
SL_LICENSING_STATUS *status;
UINT count;
HRESULT hr = $SLOpen(&slc);
if (!SUCCEEDED(hr)) {
goto end_slc;
}
hr = $SLGetLicensingStatusInformation(slc, &WINDOWS_SLID, 0, 0, &count, &status);
if (!SUCCEEDED(hr) || count == 0) {
goto end_slc;
}
// Iterate through all statuses until we find one in Licensed status.
g_isActivated = FALSE;
for (int i = 0; i < count; i++) {
if (status[i].eStatus == SL_LICENSING_STATUS_LICENSED) {
g_isActivated = TRUE;
break;
}
}
end_slc:
if (status) {
LocalFree(status);
}
if (slc) {
$SLClose(slc);
}
} else {
// XP: Use private API
ICOMLicenseAgent *agent;
HRESULT hr;
// On XP and Server 2003 x64, we need to pass a different argument to CoCreateInstance.
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
hr = CoCreateInstance(&CLSID_COMLicenseAgent, NULL, CLSCTX_INPROC_SERVER | CLSCTX_ACTIVATE_64_BIT_SERVER, &IID_ICOMLicenseAgent, (void **)&agent);
} else {
hr = CoCreateInstance(&CLSID_COMLicenseAgent, NULL, CLSCTX_INPROC_SERVER, &IID_ICOMLicenseAgent, (void **)&agent);
}
if (!SUCCEEDED(hr)) {
TRACE(L"COMLicenseAgent load failed: %x", hr);
goto end_xp;
}
ULONG result;
hr = ICOMLicenseAgent_Initialize(agent, 0xC475, 3, NULL, &result);
if (!SUCCEEDED(hr) || result != 0) {
TRACE(L"COMLicenseAgent init failed: %x", hr);
goto end_xp;
}
ULONG wpaLeft, evalLeft;
hr = ICOMLicenseAgent_GetExpirationInfo(agent, &wpaLeft, &evalLeft);
if (!SUCCEEDED(hr)) {
TRACE(L"COMLicenseAgent GetExpirationInfo failed: %x", hr);
goto end_xp;
}
g_isActivated = wpaLeft == MAXLONG;
end_xp:
if (agent) {
ICOMLicenseAgent_Release(agent);
}
}
pushint(g_isActivated);
}

9
nsisplugin/IsAdmin.c Normal file
View File

@ -0,0 +1,9 @@
#include <windows.h>
#include <nsis/pluginapi.h>
#include "User.h"
PLUGIN_METHOD(IsAdmin) {
PLUGIN_INIT();
pushint(IsUserAdmin());
}

67
nsisplugin/UpdateRoots.c Normal file
View File

@ -0,0 +1,67 @@
#include <windows.h>
#include <nsis/pluginapi.h>
#include <wincrypt.h>
#include "HResult.h"
PLUGIN_METHOD(UpdateRoots) {
PLUGIN_INIT();
HRESULT hr = E_FAIL;
WCHAR stateStr[1024], store[1024], path[1024];
popstring(stateStr);
popstring(store);
popstring(path);
if (!stateStr || !store || !path) {
pushint(E_INVALIDARG);
return;
}
BOOL add;
if (lstrcmpi(stateStr, L"/update") == 0) {
add = TRUE;
} else if (lstrcmpi(stateStr, L"/delete") == 0) {
add = FALSE;
} else {
pushint(E_INVALIDARG);
return;
}
HCERTSTORE srcStore = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, CERT_STORE_READONLY_FLAG, path);
if (!srcStore) {
TRACE(L"CertOpenStore for %ls failed: %08x", path, hr);
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
HCERTSTORE dstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, store);
if (!dstStore) {
hr = HRESULT_FROM_WIN32(GetLastError());
TRACE(L"CertOpenStore for %ls failed: %08x", store, hr);
goto end;
}
PCCERT_CONTEXT cert = NULL;
while ((cert = CertEnumCertificatesInStore(srcStore, cert)) != NULL) {
BOOL result = add
? CertAddCertificateContextToStore(dstStore, cert, CERT_STORE_ADD_REPLACE_EXISTING, NULL)
: CertDeleteCertificateFromStore(CertDuplicateCertificateContext(cert));
if (!result) {
TRACE(L"cert %ls in %ls failed: %d\n", add ? L"add" : L"delete", store, GetLastError());
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
}
hr = S_OK;
end:
if (srcStore) {
CertCloseStore(srcStore, 0);
}
if (dstStore) {
CertCloseStore(dstStore, 0);
}
pushint(hr);
}

99
setup/ActiveXPage.nsh Normal file
View File

@ -0,0 +1,99 @@
Var Dialog
Var Dialog.Y
Function ActiveXPage
; Skip in runonce
${If} ${IsRunOnce}
${OrIf} ${IsPostInstall}
Abort
${EndIf}
; Skip if not required
${If} ${AtLeastWin7}
; TODO: Fix ordering of setup.nsi so we can do this
; ${OrIfNot} ${SectionIsSelected} ${LEGACYUPDATE}
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "How do you want to use Windows Update?" ""
nsDialogs::Create 1018
Pop $Dialog
${AeroWizardDialogControl} $Dialog
StrCpy $Dialog.Y 0
${NSD_CreateLabel} 0 $Dialog.Y -1u 24u "Legacy Update configures Windows Update to use the Legacy Update proxy server, resolving connection issues to the official Microsoft Windows Update service. You can choose between two options to access Windows Update."
Pop $0
${AeroWizardDialogControl} $0
IntOp $Dialog.Y $Dialog.Y + 60
${NSD_CreateIcon} 3u $Dialog.Y 4u 4u ""
Pop $0
${AeroWizardDialogControl} $0
${NSD_SetIconFromInstaller} $0 103
${NSD_CreateRadioButton} 30u $Dialog.Y -30u 10u "Use the Legacy Update website"
Pop $0
${AeroWizardDialogControl} $0
${NSD_OnClick} $0 ActiveXPageSelectionChanged
SendMessage $0 ${BM_SETCHECK} ${BST_CHECKED} 0
${NSD_SetFocus} $0
${If} ${AtLeastWinVista}
StrCpy $0 "The Legacy Update website is a replacement for the original Windows Update website. If you select this, you can still use the Windows Update Control Panel."
${Else}
StrCpy $0 "The Legacy Update website is a replacement for the original Windows Update website, allowing you to download optional updates and drivers."
${EndIf}
IntOp $Dialog.Y $Dialog.Y + 17
${NSD_CreateLabel} 41u $Dialog.Y -41u 24u "$0"
Pop $0
${AeroWizardDialogControl} $0
IntOp $Dialog.Y $Dialog.Y + 50
${NSD_CreateIcon} 3u $Dialog.Y 4u 4u ""
Pop $0
${AeroWizardDialogControl} $0
${If} ${AtLeastWinVista}
${NSD_SetIcon} $0 "$WINDIR\System32\wucltux.dll" $1
StrCpy $1 "Use the Windows Update Control Panel"
StrCpy $2 "Legacy Update is compatible with the built-in Windows Update Control Panel. Make sure to check for updates $\"managed by your system administrator$\" to use the Legacy Update proxy server."
${Else}
${NSD_SetIcon} $0 "res://$WINDIR\System32\wupdmgr.exe/#Icon/APPICON" $1
StrCpy $1 "Use Automatic Updates"
StrCpy $2 "Use the built-in Automatic Updates feature to download and install updates. You will only be able to download critical updates."
${EndIf}
${NSD_CreateRadioButton} 30u $Dialog.Y -30u 10u "$1"
Pop $0
${AeroWizardDialogControl} $0
${NSD_OnClick} $0 ActiveXPageSelectionChanged
IntOp $Dialog.Y $Dialog.Y + 17
${NSD_CreateLabel} 41u $Dialog.Y -41u 24u "$2"
Pop $0
${AeroWizardDialogControl} $0
nsDialogs::Show
Call AeroWizardOnShow
FunctionEnd
Function ActiveXPageSelectionChanged
Pop $0
${NSD_GetState} $0 $0
; TODO: Fix ordering of setup.nsi so we can do this
${If} $0 == ${BST_CHECKED}
; !insertmacro UnselectSection ${ACTIVEX}
${Else}
; !insertmacro SelectSection ${ACTIVEX}
${EndIf}
FunctionEnd

170
setup/DownloadVista78.nsh Normal file
View File

@ -0,0 +1,170 @@
Function NeedsPackage
Pop $0
ClearErrors
FindFirst $R0 $R1 "$WINDIR\servicing\Packages\$0~31bf3856ad364e35~*"
FindClose $R0
${If} ${Errors}
Push 1
${Else}
Push 0
${EndIf}
FunctionEnd
!macro SPHandler kbid pkg title
Function Needs${kbid}
Push ${pkg}
Call NeedsPackage
FunctionEnd
Function Download${kbid}
Call Needs${kbid}
Pop $0
${If} $0 == 1
Call GetArch
Pop $0
ReadINIStr $0 $PLUGINSDIR\Patches.ini "${kbid}" $0
ReadINIStr $1 $PLUGINSDIR\Patches.ini "${kbid}" Prefix
!insertmacro Download "${title}" "$1$0" "${kbid}.exe" 1
${EndIf}
FunctionEnd
Function Install${kbid}
${If} ${NeedsPatch} ${kbid}
Call Download${kbid}
!insertmacro InstallSP "${title}" "${kbid}.exe"
${EndIf}
FunctionEnd
!macroend
!macro MSUHandler kbid title
Function Needs${kbid}
Push Package_for_${kbid}
Call NeedsPackage
FunctionEnd
Function Download${kbid}
${If} ${NeedsPatch} ${kbid}
Call GetArch
Pop $0
ReadINIStr $1 $PLUGINSDIR\Patches.ini "${kbid}" $0
ReadINIStr $2 $PLUGINSDIR\Patches.ini "${kbid}" Prefix
!insertmacro DownloadMSU "${kbid}" "${title}" "$2$1"
${EndIf}
FunctionEnd
Function Install${kbid}
${If} ${NeedsPatch} ${kbid}
Call Download${kbid}
!insertmacro InstallMSU "${kbid}" "${title}"
${EndIf}
FunctionEnd
!macroend
; Service Packs
!insertmacro SPHandler "VistaSP1" "VistaSP1-KB936330" "Windows Vista $(SP) 1"
!insertmacro SPHandler "VistaSP2" "VistaSP2-KB948465" "Windows Vista $(SP) 2"
!insertmacro SPHandler "Win7SP1" "Windows7SP1-KB976933" "Windows 7 $(SP) 1"
; Windows Vista post-SP2 update combination that fixes WU indefinitely checking for updates
!insertmacro MSUHandler "KB3205638" "$(SecUpd) for Windows Vista"
!insertmacro MSUHandler "KB4012583" "$(SecUpd) for Windows Vista"
!insertmacro MSUHandler "KB4015195" "$(SecUpd) for Windows Vista"
!insertmacro MSUHandler "KB4015380" "$(SecUpd) for Windows Vista"
; Internet Explorer 9 for Windows Vista
!insertmacro MSUHandler "KB971512" "$(Update) for Windows Vista"
!insertmacro MSUHandler "KB2117917" "$(PUS) for Windows Vista"
!insertmacro NeedsFileVersionHandler "IE9" "mshtml.dll" "9.0.8112.16421"
!insertmacro PatchHandler "IE9" "$(IE) 9 for Windows Vista" ${PATCH_FLAGS_OTHER} "/passive /norestart /update-no /closeprograms"
; Windows Vista Servicing Stack Update
!insertmacro MSUHandler "KB4493730" "2019-04 $(SSU) for Windows $(SRV) 2008"
; Windows 7 Servicing Stack Update
!insertmacro MSUHandler "KB3138612" "2016-03 $(SSU) for Windows 7"
!insertmacro MSUHandler "KB4474419" "$(SHA2) for Windows 7"
!insertmacro MSUHandler "KB4490628" "2019-03 $(SSU) for Windows 7"
; Windows Home Server 2011 Update Rollup 4
!insertmacro MSUHandler "KB2757011" "$(SectionWHS2011U4)"
; Windows 8 Servicing Stack
!insertmacro MSUHandler "KB4598297" "2021-01 $(SSU) for Windows $(SRV) 2012"
; Windows 8.1 Servicing Stack
!insertmacro MSUHandler "KB3021910" "2015-04 $(SSU) for Windows 8.1"
; Windows 8.1 Update 1
!insertmacro MSUHandler "KB2919355" "Windows 8.1 $(Update) 1"
!insertmacro MSUHandler "KB2932046" "Windows 8.1 $(Update) 1"
!insertmacro MSUHandler "KB2959977" "Windows 8.1 $(Update) 1"
!insertmacro MSUHandler "KB2937592" "Windows 8.1 $(Update) 1"
!insertmacro MSUHandler "KB2934018" "Windows 8.1 $(Update) 1"
; Windows 8.1 Update 3
; TODO
; !insertmacro MSUHandler "KB2934018" "Windows 8.1 $(Update) 3"
Function NeedsVistaPostSP2
${If} ${NeedsPatch} KB3205638
${OrIf} ${NeedsPatch} KB4012583
${OrIf} ${NeedsPatch} KB4015195
${OrIf} ${NeedsPatch} KB4015380
${OrIf} ${NeedsPatch} KB4493730
Push 1
${Else}
Push 0
${EndIf}
FunctionEnd
Function NeedsWin7PostSP1
${If} ${NeedsPatch} KB3138612
${OrIf} ${NeedsPatch} KB4474419
${OrIf} ${NeedsPatch} KB4490628
Push 1
${Else}
Push 0
${EndIf}
FunctionEnd
Function NeedsWin81Update1
${If} ${NeedsPatch} KB2919355
${OrIf} ${NeedsPatch} KB2932046
${OrIf} ${NeedsPatch} KB2937592
${OrIf} ${NeedsPatch} KB2934018
Push 1
${Else}
Push 0
${EndIf}
FunctionEnd
; TODO
; Function NeedsWin81Update3
; Call GetArch
; Pop $0
; ${If} $0 == "arm"
; ${AndIf} ${NeedsPatch} KB2934018
; Push 1
; ${Else}
; Push 0
; ${EndIf}
; FunctionEnd
; Weird prerequisite to Update 1 that fixes the main KB2919355 update failing to install
Function DownloadClearCompressionFlag
${If} ${NeedsPatch} KB2919355
Call GetArch
Pop $0
ReadINIStr $0 $PLUGINSDIR\Patches.ini ClearCompressionFlag $0
ReadINIStr $1 $PLUGINSDIR\Patches.ini ClearCompressionFlag Prefix
!insertmacro Download "Windows 8.1 $(Update) 1 $(PrepTool)" "$1$0" "ClearCompressionFlag.exe" 1
${EndIf}
FunctionEnd
Function InstallClearCompressionFlag
${If} ${NeedsPatch} KB2919355
Call DownloadClearCompressionFlag
!insertmacro Install "Windows 8.1 $(Update) 1 $(PrepTool)" "ClearCompressionFlag.exe" ""
${EndIf}
FunctionEnd

32
setup/Makefile Normal file
View File

@ -0,0 +1,32 @@
DEBUG ?= 1
SIGN ?= 0
CI ?= 0
MAKENSIS = makensis
NSISFLAGS = -DDEBUG=$(DEBUG) -DSIGN=$(SIGN) -DCI=$(CI)
all:
+$(MAKE) -C ../nsisplugin
+$(MAKE) setup
+$(MAKE) activex
setup:
$(MAKENSIS) $(NSISFLAGS) setup.nsi
activex:
ifeq ($(SIGN),1)
cp LegacyUpdate-*.exe codebase/setup.exe
cd codebase && makecab.exe /f lucontrl.ddf
../build/sign.sh codebase/lucontrl.cab
rm codebase/setup.exe codebase/setup.rpt
endif
clean:
+$(MAKE) -C ../nsisplugin clean
rm -f LegacyUpdate-*.exe codebase/{lucontrl.cab,setup.exe,setup.rpt}
test:
+$(MAKE)
sudo.exe LegacyUpdate-*.exe
.PHONY: all nsisplugin setup activex clean

201
setup/Strings.nsh Normal file
View File

@ -0,0 +1,201 @@
!insertmacro MUI_LANGUAGE "English"
; Dialog
MiscButtonText "Back" "Next" "Cancel" "Close"
; Log
LangString ^ExecShell ${LANG_ENGLISH} "Execute: "
LangString ^Completed ${LANG_ENGLISH} "Done"
LangString Downloading ${LANG_ENGLISH} "Downloading "
LangString Extracting ${LANG_ENGLISH} "Extracting "
LangString Installing ${LANG_ENGLISH} "Installing "
LangString ExitCode ${LANG_ENGLISH} "Exit code: "
LangString RestartRequired ${LANG_ENGLISH} "Success - restart required"
LangString AlreadyInstalled ${LANG_ENGLISH} "Installation skipped - already installed"
LangString NotApplicable ${LANG_ENGLISH} "Installation skipped - not applicable"
; Download
LangString DownloadStatusSingle ${LANG_ENGLISH} "{TIMEREMAINING} left - {RECVSIZE} of {FILESIZE} ({SPEED})"
LangString DownloadStatusMulti ${LANG_ENGLISH} "{TIMEREMAINING} left - {TOTALRECVSIZE} of {TOTALFILESIZE} ({SPEED})"
; Startup errors
LangString MsgBoxUsage ${LANG_ENGLISH} \
"Usage: setup.exe [/S] [/v] [/passive] [/norestart]$\r$\n\
$\r$\n\
/S$\tExecute Legacy Update setup silently.$\r$\n\
/v$\tDisplay verbose details during installation.$\r$\n\
/passive$\tInstall without user interaction.$\r$\n\
/norestart$\tDisable automatic restart during installation.$\r$\n\
$\r$\n\
If no flags are passed, Legacy Update will launch its full user interface.$\r$\n\
For more information on these flags, visit legacyupdate.net."
LangString MsgBoxElevationRequired ${LANG_ENGLISH} \
"Log on as an administrator to install Legacy Update."
LangString MsgBoxOldWinVersion ${LANG_ENGLISH} \
"Legacy Update requires Windows 2000 or later.$\r$\n\
$\r$\n\
You might be interested in Windows Update Restored instead.$\r$\n\
Would you like to go to ${WUR_WEBSITE} now?"
LangString MsgBoxBetaOS ${LANG_ENGLISH} \
"The current version of Windows is a beta build. Legacy Update may not work correctly on this version of Windows.$\r$\n\
$\r$\n\
Continue anyway?"
LangString MsgBoxCompatMode ${LANG_ENGLISH} \
"A compatibility mode has been set on this program. Legacy Update will not work correctly in compatibility mode.$\r$\n\
$\r$\n\
Disable it in the Properties dialog of this file and try again."
LangString MsgBoxPluginFailed ${LANG_ENGLISH} \
"Setup failed to initialize.$\r$\n\
$\r$\n\
The file may be corrupt. Try downloading Legacy Update again."
; Install errors
FileErrorText \
'Unable to write to "$0".$\r$\n\
$\r$\n\
If Internet Explorer is open, close it and click Retry.' \
'Unable to write to "$0".$\r$\n\
$\r$\n\
If Internet Explorer is open, close it and click Retry.'
LangString MsgBoxDownloadAbort ${LANG_ENGLISH} \
"Cancelling will terminate Legacy Update setup."
LangString MsgBoxDownloadFailed ${LANG_ENGLISH} \
"$2 failed to download.$\r$\n\
$\r$\n\
$0 ($1)"
LangString MsgBoxInstallFailed ${LANG_ENGLISH} \
"$2 failed to install.$\r$\n\
$\r$\n\
$1 ($0)"
LangString MsgBoxPatchNotFound ${LANG_ENGLISH} \
"$0 failed to install.$\r$\n\
$\r$\n\
The installed Windows language and/or architecture is not supported."
LangString MsgBoxMUFailed ${LANG_ENGLISH} \
"Failed to enable Microsoft Update.$\r$\n\
$\r$\n\
$1 ($0)"
; Warnings
LangString MsgBoxWES09NotSSE2 ${LANG_ENGLISH} \
"Your processor does not support the Streaming SIMD Extensions 2 (SSE2) instruction set, which is required to install Windows Embedded 2009 updates released after May 2018.$\r$\n\
Processors that initially implemented SSE2 instructions include the Intel Pentium 4, Pentium M, and AMD Athlon 64.$\r$\n\
$\r$\n\
To protect your Windows installation from becoming corrupted by incompatible updates, this option will be disabled."
LangString MsgBoxActivateXP2002NotSP3 ${LANG_ENGLISH} \
"Windows XP must be updated to Service Pack 3 to activate over the internet. The Service Pack 3 update action will be enabled."
LangString MsgBoxActivateXP2003NotSP2 ${LANG_ENGLISH} \
"Windows XP Professional x64 Edition or Windows Server 2003 must be updated to Service Pack 2 to activate over the internet. The Service Pack 2 update action will be enabled."
LangString MsgBoxVistaSPInstall ${LANG_ENGLISH} \
"Your computer will restart several times to install Windows Vista Service Pack 2. Your screen may appear blank for an extended period of time. Do not turn off your computer during this process."
LangString MsgBoxWUA2000Datacenter ${LANG_ENGLISH} \
"Windows Update Agent is not supported on Windows 2000 Datacenter Server. The Legacy Update action will be disabled."
; Statuses
LangString StatusRestarting ${LANG_ENGLISH} "Restarting..."
LangString StatusRestartingWUAU ${LANG_ENGLISH} "Restarting Windows Update service..."
LangString StatusCheckingSSL ${LANG_ENGLISH} "Checking SSL connectivity..."
LangString StatusCbsInstalling ${LANG_ENGLISH} "Configuring updates..."
; Sections
LangString Setup ${LANG_ENGLISH} "Setup"
LangString IE ${LANG_ENGLISH} "Internet Explorer"
LangString PRO ${LANG_ENGLISH} "Professional"
LangString P64 ${LANG_ENGLISH} "Professional x64 Edition"
LangString EMB ${LANG_ENGLISH} "Embedded"
LangString SRV ${LANG_ENGLISH} "Server"
LangString SP ${LANG_ENGLISH} "Service Pack"
LangString SSU ${LANG_ENGLISH} "Servicing Stack Update"
LangString WUA ${LANG_ENGLISH} "Windows Update Agent"
LangString SecUpd ${LANG_ENGLISH} "Security Update"
LangString Update ${LANG_ENGLISH} "Update"
LangString Rollup ${LANG_ENGLISH} "Update Rollup"
LangString PrepTool ${LANG_ENGLISH} "Preparation Tool"
LangString PUS ${LANG_ENGLISH} "Platform Update Supplement"
LangString SHA2 ${LANG_ENGLISH} "SHA-2 Code Signing Support Update"
LangString CTL ${LANG_ENGLISH} "Certificate Trust List"
LangString SectionWES09 ${LANG_ENGLISH} "Enable Windows Embedded 2009 updates"
LangString SectionWHS2011U4 ${LANG_ENGLISH} "Windows Home Server 2011 $(Rollup) 4"
LangString SectionW2KUR1 ${LANG_ENGLISH} "Update Rollup 1 for Windows 2000 $(SP) 4"
LangString SectionSSU ${LANG_ENGLISH} "Windows Servicing Stack update"
LangString SectionWUA ${LANG_ENGLISH} "Windows Update Agent update"
LangString SectionRootCerts ${LANG_ENGLISH} "Root certificates store update"
LangString SectionEnableMU ${LANG_ENGLISH} "Enable Microsoft Update"
LangString SectionActivate ${LANG_ENGLISH} "Activate Windows"
LangString SectionReboots ${LANG_ENGLISH} \
"Your computer will restart automatically to complete installation."
LangString SectionSupEULA ${LANG_ENGLISH} \
"By installing, you are agreeing to the Supplemental End User License Agreement for this update."
LangString SectionMSLT ${LANG_ENGLISH} \
"By installing, you are agreeing to the Microsoft Software License Terms for this update."
LangString SectionW2KSP4Desc ${LANG_ENGLISH} \
"Updates Windows 2000 to Service Pack 4 with Update Rollup 1, as required to install the Windows Update Agent.$\r$\n$(SectionReboots) $(SectionSupEULA)"
LangString SectionIE6SP1Desc ${LANG_ENGLISH} \
"Updates Internet Explorer to 6.0 SP1, as required for Legacy Update.$\r$\n$(SectionReboots) $(SectionSupEULA)"
LangString SectionXPSP3Desc ${LANG_ENGLISH} \
"Updates Windows XP to Service Pack 3. Required if you would like to activate Windows online. $(SectionReboots) $(SectionSupEULA)"
LangString SectionXPESP3Desc ${LANG_ENGLISH} \
"Updates Windows XP Embedded to Service Pack 3. Required if you would like to activate Windows online. $(SectionReboots) $(SectionSupEULA)"
LangString SectionWES09Desc ${LANG_ENGLISH} \
"Configures Windows to appear as Windows Embedded POSReady 2009 to Windows Update, enabling access to Windows XP security updates released between 2014 and 2019. Please note that Microsoft officially advises against doing this."
LangString Section2003SP2Desc ${LANG_ENGLISH} \
"Updates Windows XP Professional x64 Edition or Windows Server 2003 to Service Pack 2. Required if you would like to activate Windows online. $(SectionReboots) $(SectionSupEULA)"
LangString SectionVistaSP2Desc ${LANG_ENGLISH} \
"Updates Windows Vista or Windows Server 2008 to Service Pack 2, as required to install the Windows Update Agent. $(SectionReboots) $(SectionMSLT)"
LangString SectionVistaSSUDesc ${LANG_ENGLISH} \
"Updates Windows Vista or Windows Server 2008 with additional updates required to resolve issues with the Windows Update Agent.$\r$\n$(SectionReboots)"
LangString SectionVistaIE9Desc ${LANG_ENGLISH} \
"Updates Internet Explorer to 9.0.$\r$\n$(SectionReboots) $(SectionMSLT)"
LangString SectionWin7SP1Desc ${LANG_ENGLISH} \
"Updates Windows 7 or Windows Server 2008 R2 to Service Pack 1, as required to install the Windows Update Agent. $(SectionReboots) $(SectionMSLT)"
LangString SectionWin7SSUDesc ${LANG_ENGLISH} \
"Updates Windows 7 or Windows Server 2008 R2 with additional updates required to resolve issues with the Windows Update Agent.$\r$\n$(SectionReboots)"
LangString SectionWin8SSUDesc ${LANG_ENGLISH} \
"Updates Windows 8 or Windows Server 2012 with additional updates required to resolve issues with the Windows Update Agent.$\r$\n$(SectionReboots)"
LangString SectionWin81U1Desc ${LANG_ENGLISH} \
"Updates Windows 8.1 to Update 1, as required to resolve issues with the Windows Update Agent. Also required to upgrade to Windows 10.$\r$\n$(SectionReboots)"
LangString SectionWin81SSUDesc ${LANG_ENGLISH} \
"Updates Windows 8.1 or Windows Server 2012 R2 with additional updates required to resolve issues with the Windows Update Agent.$\r$\n$(SectionReboots)"
LangString SectionWHS2011U4Desc ${LANG_ENGLISH} \
"Updates Windows Home Server 2011 to Update Rollup 4 to resolve issues with the Windows Update Agent. Also fixes data corruption problems.$\r$\n$(SectionReboots)"
LangString SectionWUADesc ${LANG_ENGLISH} \
"Updates the Windows Update Agent to the latest version, as required for Legacy Update."
LangString SectionRootCertsDesc ${LANG_ENGLISH} \
"Updates the root certificate store to the latest from Microsoft, and enables additional modern security features. Root certificates are used to verify the security of encrypted (https) connections. This fixes connection issues with some websites."
LangString SectionWin7MUDesc ${LANG_ENGLISH} \
"Configures Windows Update to receive updates for Microsoft Office and other Microsoft software."
LangString SectionActivateDesc ${LANG_ENGLISH} \
"Your copy of Windows is not activated. If you update the root certificates store, Windows Product Activation can be completed over the internet. Legacy Update can start the activation wizard after installation so you can activate your copy of Windows."
LangString SectionActiveX2KXPDesc ${LANG_ENGLISH} \
"Installs the Legacy Update ActiveX control, enabling access to the full Windows Update interface via the legacyupdate.net website."
LangString SectionActiveXVista78Desc ${LANG_ENGLISH} \
"Installs the Legacy Update ActiveX control, enabling access to the classic Windows Update interface via the legacyupdate.net website. Not required if you want to use the built-in Windows Update Control Panel."
LangString SectionActiveXWin10Desc ${LANG_ENGLISH} \
"Installs the Legacy Update ActiveX control, enabling access to the classic Windows Update interface via the legacyupdate.net website."
; LangString SectionLegacyUpdateDesc ${LANG_ENGLISH} \
; "Installs Legacy Update, enabling access to Windows Update."
; LangString SectionWUServerDesc ${LANG_ENGLISH} \
; "Configures Windows Update to use the Legacy Update proxy server, resolving connection issues to the official Microsoft Windows Update service."
LangString SectionAllowOSUpgrade ${LANG_ENGLISH} "Allow OS Upgrade"
LangString SectionAllowOSUpgradeDesc ${LANG_ENGLISH} \
"Configures Windows Update to deliver the latest feature update. It can help upgrading from Windows 7 to 10 or from Windows 10 to Windows 11."

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -115,8 +115,8 @@ Var /GLOBAL UninstallInstalled
!include Strings.nsh
; Uncomment lines below to enable code signing when compiling under Windows
; !uninstfinalize 'sign.cmd "certPath" certPassword "Legacy Update - Vichingo455 Mod" "%1"' = 0
; !finalize 'sign.cmd "certPath" certPassword "Legacy Update - Vichingo455 Mod" "%1"' = 0
; !uninstfinalize 'sign.cmd certFile certPassword "Legacy Update - Vichingo455 Mod" "%1"' = 0
; !finalize 'sign.cmd certFile certPassword "Legacy Update - Vichingo455 Mod" "%1"' = 0
!macro RestartWUAUService
${DetailPrint} "$(StatusRestartingWUAU)"

43
shared/Exec.c Normal file
View File

@ -0,0 +1,43 @@
#include "stdafx.h"
#include "Exec.h"
HRESULT Exec(LPWSTR verb, LPWSTR file, LPWSTR params, LPWSTR workingDir, WORD show, BOOL wait, LPDWORD exitCode) {
SHELLEXECUTEINFO execInfo = {0};
execInfo.cbSize = sizeof(execInfo);
execInfo.lpVerb = verb;
execInfo.lpFile = file;
execInfo.lpParameters = params;
execInfo.lpDirectory = workingDir;
execInfo.nShow = show;
return ExecEx(&execInfo, wait, exitCode);
}
HRESULT ExecEx(LPSHELLEXECUTEINFO execInfo, BOOL wait, LPDWORD exitCode) {
if (wait) {
execInfo->fMask |= SEE_MASK_NOCLOSEPROCESS;
}
if (!ShellExecuteEx(execInfo)) {
return HRESULT_FROM_WIN32(GetLastError());
}
HRESULT hr = S_OK;
if (wait) {
if (execInfo->hProcess == NULL) {
TRACE(L"ShellExecuteEx() didn't return a handle: %u", GetLastError());
hr = E_FAIL;
}
WaitForSingleObject(execInfo->hProcess, INFINITE);
if (exitCode != NULL && GetExitCodeProcess(execInfo->hProcess, exitCode) == 0) {
hr = HRESULT_FROM_WIN32(GetLastError());
TRACE(L"GetExitCodeProcess() failed: %p\n", hr);
}
CloseHandle(execInfo->hProcess);
}
return hr;
}

7
shared/Exec.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <windows.h>
#include <shellapi.h>
EXTERN_C HRESULT Exec(LPWSTR verb, LPWSTR file, LPWSTR params, LPWSTR workingDir, WORD show, BOOL wait, LPDWORD exitCode);
EXTERN_C HRESULT ExecEx(LPSHELLEXECUTEINFO execInfo, BOOL wait, LPDWORD exitCode);

36
shared/GetPidForName.c Normal file
View File

@ -0,0 +1,36 @@
#include "stdafx.h"
#include <psapi.h>
#include "GetPidForName.h"
#pragma comment(lib, "psapi.lib")
DWORD GetPidForName(const LPTSTR process) {
// Yes, eat all of our SHRTs!
DWORD pids[SHRT_MAX];
DWORD bytesReturned;
if (!EnumProcesses(pids, sizeof(pids), &bytesReturned)) {
return 0;
}
DWORD count = bytesReturned / sizeof(DWORD);
for (DWORD i = 0; i < count; ++i) {
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, pids[i]);
if (handle) {
WCHAR path[MAX_PATH];
if (GetModuleBaseName(handle, NULL, path, ARRAYSIZE(path))) {
LPWSTR basename = wcsrchr(path, L'\\');
if (basename) {
basename += 1;
CharLowerBuffW(basename, (DWORD)wcslen(basename));
if (_wcsicmp(process, basename) == 0) {
CloseHandle(handle);
return pids[i];
}
}
}
CloseHandle(handle);
}
}
return 0;
}

5
shared/GetPidForName.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <windows.h>
EXTERN_C DWORD GetPidForName(LPTSTR process);

31
shared/LegacyUpdate.c Normal file
View File

@ -0,0 +1,31 @@
#include "stdafx.h"
#include <windows.h>
#include "Registry.h"
static LPWSTR _installPath;
EXTERN_C HRESULT GetInstallPath(LPWSTR *path) {
*path = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
HRESULT hr = S_OK;
if (!_installPath) {
DWORD size = 0;
hr = GetRegistryString(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\LegacyUpdate", L"InstallLocation", KEY_WOW64_64KEY, &_installPath, &size);
if (SUCCEEDED(hr)) {
lstrcpy(*path, _installPath);
return S_OK;
}
// Do our best to guess where it should be
LPWSTR programFiles;
hr = GetRegistryString(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion", L"ProgramFilesDir", KEY_WOW64_64KEY, &programFiles, &size);
if (SUCCEEDED(hr)) {
_installPath = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
wsprintf(_installPath, L"%ls\\Legacy Update", programFiles);
LocalFree(programFiles);
}
}
lstrcpy(*path, _installPath);
return hr;
}

5
shared/LegacyUpdate.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <windows.h>
EXTERN_C HRESULT GetInstallPath(LPWSTR *path);

256
shared/LoadImage.c Normal file
View File

@ -0,0 +1,256 @@
#include <windows.h>
#include <wincodec.h>
#include <gdiplus.h>
// Adapted from https://faithlife.codes/blog/2008/09/displaying_a_splash_screen_with_c_part_i/
// 1. Get resource as an IStream
// 2. Use Windows Imaging Component to load the PNG
// 3. Convert the WIC bitmap to an HBITMAP
// Why does loading a PNG need to be so difficult?
typedef HRESULT (WINAPI *_WICConvertBitmapSource)(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst);
static _WICConvertBitmapSource $WICConvertBitmapSource;
static HGLOBAL GetRawResource(HINSTANCE hInstance, LPWSTR name, LPWSTR type) {
HRSRC resource = FindResource(hInstance, name, type);
if (!resource) {
TRACE(L"FindResource failed: %d", GetLastError());
return NULL;
}
DWORD resourceSize = SizeofResource(hInstance, resource);
HGLOBAL imageHandle = LoadResource(hInstance, resource);
if (!imageHandle) {
TRACE(L"LoadResource failed: %d", GetLastError());
return NULL;
}
LPVOID sourceResourceData = LockResource(imageHandle);
if (!sourceResourceData) {
TRACE(L"LockResource failed: %d", GetLastError());
return NULL;
}
HGLOBAL resourceDataHandle = GlobalAlloc(GMEM_MOVEABLE, resourceSize);
if (!resourceDataHandle) {
TRACE(L"GlobalAlloc failed: %d", GetLastError());
return NULL;
}
LPVOID resourceData = GlobalLock(resourceDataHandle);
if (!resourceData) {
TRACE(L"GlobalLock failed: %d", GetLastError());
GlobalFree(resourceDataHandle);
return NULL;
}
CopyMemory(resourceData, sourceResourceData, resourceSize);
GlobalUnlock(resourceDataHandle);
return resourceDataHandle;
}
static IStream *GetResourceStream(HINSTANCE hInstance, LPWSTR name, LPWSTR type) {
IStream *stream;
HGLOBAL resource = GetRawResource(hInstance, name, type);
if (!resource) {
TRACE(L"GetResource failed: %d", GetLastError());
return NULL;
}
if (SUCCEEDED(CreateStreamOnHGlobal(resource, TRUE, &stream))) {
return stream;
}
GlobalFree(resource);
return NULL;
}
static IWICBitmapSource *GetWICBitmap(IStream *imageStream) {
IWICBitmapSource *bitmap;
IWICBitmapDecoder *decoder;
UINT frameCount;
IWICBitmapFrameDecode *frame;
if (!SUCCEEDED(CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER, &IID_IWICBitmapDecoder, (LPVOID *)&decoder))) {
return NULL;
}
if (!SUCCEEDED(IWICBitmapDecoder_Initialize(decoder, imageStream, WICDecodeMetadataCacheOnLoad))) {
goto end;
}
if (!SUCCEEDED(IWICBitmapDecoder_GetFrameCount(decoder, &frameCount)) || frameCount != 1) {
goto end;
}
if (!SUCCEEDED(IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) {
goto end;
}
$WICConvertBitmapSource(&GUID_WICPixelFormat32bppPBGRA, (IWICBitmapSource *)frame, &bitmap);
IWICBitmapFrameDecode_Release(frame);
end:
IWICBitmapDecoder_Release(decoder);
return bitmap;
}
static HBITMAP GetHBitmapForWICBitmap(IWICBitmapSource *bitmap) {
HBITMAP hBitmap;
UINT width, height;
if (!SUCCEEDED(IWICBitmapSource_GetSize(bitmap, &width, &height)) || width == 0 || height == 0) {
return NULL;
}
BITMAPINFO bminfo;
ZeroMemory(&bminfo, sizeof(bminfo));
bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bminfo.bmiHeader.biWidth = width;
bminfo.bmiHeader.biHeight = -(LONG)height;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
void *imageBits;
HDC screenDC = GetDC(NULL);
hBitmap = CreateDIBSection(screenDC, &bminfo, DIB_RGB_COLORS, &imageBits, NULL, 0);
ReleaseDC(NULL, screenDC);
if (!hBitmap) {
return NULL;
}
UINT stride = width * 4;
UINT imageSize = stride * height;
if (!SUCCEEDED(IWICBitmapSource_CopyPixels(bitmap, NULL, stride, imageSize, (BYTE*)imageBits))) {
DeleteObject(hBitmap);
return NULL;
}
return hBitmap;
}
HBITMAP LoadPNGResource(HINSTANCE hInstance, LPWSTR resourceName, LPWSTR resourceType) {
if (!$WICConvertBitmapSource) {
$WICConvertBitmapSource = (_WICConvertBitmapSource)GetProcAddress(LoadLibrary(L"windowscodecs.dll"), "WICConvertBitmapSource");
if (!$WICConvertBitmapSource) {
return NULL;
}
}
IStream *imageStream = GetResourceStream(hInstance, resourceName, resourceType);
if (!imageStream) {
TRACE(L"GetResourceStream failed: %d", GetLastError());
return NULL;
}
IWICBitmapSource *bitmap = GetWICBitmap(imageStream);
if (!bitmap) {
TRACE(L"GetWICBitmap failed: %d", GetLastError());
IStream_Release(imageStream);
return NULL;
}
HBITMAP result = GetHBitmapForWICBitmap(bitmap);
IWICBitmapSource_Release(bitmap);
IStream_Release(imageStream);
return result;
}
BOOL ScaleAndWriteToBMP(HBITMAP hBitmap, DWORD width, DWORD height, LPWSTR outputPath) {
BOOL result = FALSE;
if (!hBitmap) {
TRACE(L"Null bitmap");
return FALSE;
}
HDC hdc = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP scaledBitmap = CreateCompatibleBitmap(hdc, width, height);
if (!scaledBitmap) {
TRACE(L"CreateCompatibleBitmap failed: %d", GetLastError());
goto end;
}
BITMAP bmp;
if (!GetObject(hBitmap, sizeof(BITMAP), &bmp)) {
TRACE(L"GetObject failed: %d", GetLastError());
goto end;
}
HBITMAP hOld = (HBITMAP)SelectObject(hdcMem, hBitmap);
HDC hdcMemScaled = CreateCompatibleDC(hdc);
HBITMAP hOldScaled = (HBITMAP)SelectObject(hdcMemScaled, scaledBitmap);
SetStretchBltMode(hdcMemScaled, HALFTONE);
if (!StretchBlt(hdcMemScaled,
0, 0, width, height, hdcMem,
0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY)) {
TRACE(L"StretchBlt failed: %d", GetLastError());
goto end;
}
BITMAPINFOHEADER bmih = {0};
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = width;
bmih.biHeight = height;
bmih.biPlanes = 1;
bmih.biBitCount = bmp.bmBitsPixel;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = ((width * bmp.bmBitsPixel + 31) / 32) * 4 * height;
BITMAPFILEHEADER bmfh = {0};
bmfh.bfType = 0x4D42;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmfh.bfSize = bmfh.bfOffBits + bmih.biSizeImage;
HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE, bmih.biSizeImage);
if (!handle) {
TRACE(L"GlobalAlloc failed: %d", GetLastError());
goto end;
}
BYTE *bitmapData = (BYTE *)GlobalLock(handle);
if (!bitmapData) {
TRACE(L"GlobalLock failed: %d", GetLastError());
goto end;
}
if (!GetDIBits(hdcMemScaled, scaledBitmap, 0, height, bitmapData, (BITMAPINFO *)&bmih, DIB_RGB_COLORS)) {
TRACE(L"GetDIBits failed: %d", GetLastError());
goto end;
}
HANDLE file = CreateFile(outputPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
TRACE(L"CreateFile failed: %d", GetLastError());
goto end;
}
DWORD written;
if (!WriteFile(file, &bmfh, sizeof(BITMAPFILEHEADER), &written, NULL) ||
!WriteFile(file, &bmih, sizeof(BITMAPINFOHEADER), &written, NULL) ||
!WriteFile(file, bitmapData, bmih.biSizeImage, &written, NULL)) {
TRACE(L"WriteFile failed: %d", GetLastError());
goto end;
}
result = TRUE;
end:
if (file && file != INVALID_HANDLE_VALUE) {
CloseHandle(file);
}
if (scaledBitmap) {
DeleteObject(scaledBitmap);
}
if (handle) {
GlobalUnlock(handle);
GlobalFree(handle);
}
ReleaseDC(NULL, hdc);
DeleteDC(hdcMem);
DeleteDC(hdcMemScaled);
return result;
}

4
shared/LoadImage.h Normal file
View File

@ -0,0 +1,4 @@
#include <windows.h>
HBITMAP LoadPNGResource(HINSTANCE hInstance, LPWSTR resourceName, LPWSTR resourceType);
BOOL ScaleAndWriteToBMP(HBITMAP hBitmap, DWORD width, DWORD height, LPWSTR outputPath);

93
shared/Registry.c Normal file
View File

@ -0,0 +1,93 @@
#include "stdafx.h"
#include "Registry.h"
#include "VersionInfo.h"
#include <malloc.h>
static ALWAYS_INLINE REGSAM GetWow64Flag(REGSAM options) {
#ifdef _WIN64
return options;
#else
if (AtLeastWinXP2002()) {
return options;
}
// Filter out WOW64 keys, which are not supported on Windows 2000
return options & ~(KEY_WOW64_64KEY | KEY_WOW64_32KEY);
#endif
}
HRESULT GetRegistryString(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPWSTR *data, LPDWORD size) {
HKEY subkey;
HRESULT hr = HRESULT_FROM_WIN32(RegOpenKeyEx(key, subkeyPath, 0, GetWow64Flag(KEY_READ | options), &subkey));
if (!SUCCEEDED(hr)) {
goto end;
}
if (data) {
DWORD length = 512 * sizeof(WCHAR);
LPWSTR buffer = (LPWSTR)LocalAlloc(LPTR, length);
if (!buffer) {
hr = E_OUTOFMEMORY;
goto end;
}
LSTATUS status;
do {
status = RegQueryValueEx(subkey, valueName, NULL, NULL, (BYTE *)buffer, &length);
if (status == ERROR_MORE_DATA) {
length += 256 * sizeof(WCHAR);
LPWSTR newBuffer = (LPWSTR)LocalReAlloc(buffer, length, LMEM_MOVEABLE);
if (!newBuffer) {
LocalFree(buffer);
hr = E_OUTOFMEMORY;
goto end;
}
buffer = newBuffer;
} else if (status != ERROR_SUCCESS) {
hr = HRESULT_FROM_WIN32(status);
LocalFree(buffer);
goto end;
}
} while (status == ERROR_MORE_DATA);
*data = buffer;
if (size) {
*size = length / sizeof(WCHAR);
}
}
end:
if (subkey) {
RegCloseKey(subkey);
}
if (!SUCCEEDED(hr)) {
if (data) {
*data = NULL;
}
if (size) {
*size = 0;
}
}
return hr;
}
HRESULT GetRegistryDword(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPDWORD data) {
HKEY subkey;
HRESULT hr = HRESULT_FROM_WIN32(RegOpenKeyEx(key, subkeyPath, 0, GetWow64Flag(KEY_READ | options), &subkey));
if (!SUCCEEDED(hr)) {
goto end;
}
if (data) {
DWORD length = sizeof(DWORD);
hr = HRESULT_FROM_WIN32(RegQueryValueEx(subkey, valueName, NULL, NULL, (LPBYTE)data, &length));
}
end:
if (subkey) {
RegCloseKey(subkey);
}
return hr;
}

6
shared/Registry.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <windows.h>
EXTERN_C HRESULT GetRegistryString(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPWSTR *data, LPDWORD size);
EXTERN_C HRESULT GetRegistryDword(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPDWORD data);

45
shared/Startup.h Normal file
View File

@ -0,0 +1,45 @@
#pragma once
#include <windows.h>
typedef void (WINAPI *_SetDefaultDllDirectories)(DWORD DirectoryFlags);
typedef BOOL (WINAPI *_SetDllDirectoryW)(LPWSTR);
static inline void HardenDllSearchPaths() {
// Try our best to secure DLL search paths to just system32
WCHAR path[MAX_PATH];
// Reset %windir% and %SystemRoot%
GetWindowsDirectory(path, ARRAYSIZE(path));
SetEnvironmentVariable(L"WINDIR", path);
SetEnvironmentVariable(L"SystemRoot", path);
// Reset %PATH% to just system32
ZeroMemory(path, sizeof(path));
GetSystemDirectory(path, ARRAYSIZE(path));
SetEnvironmentVariable(L"PATH", path);
wcscat(path, L"\\kernel32.dll");
HMODULE kernel32 = GetModuleHandle(path);
if (!kernel32) {
return;
}
// Windows Vista SP2+/7 SP1+ with KB2533623
_SetDefaultDllDirectories $SetDefaultDllDirectories = (_SetDefaultDllDirectories)GetProcAddress(kernel32, "SetDefaultDllDirectories");
if ($SetDefaultDllDirectories) {
$SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
return;
}
// Windows XP SP1+
_SetDllDirectoryW $SetDllDirectoryW = (_SetDllDirectoryW)GetProcAddress(kernel32, "SetDllDirectoryW");
if ($SetDllDirectoryW) {
$SetDllDirectoryW(L"");
return;
}
}
static inline void Startup() {
HardenDllSearchPaths();
}

16
shared/Trace.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#if defined(ATLTRACE)
#define TRACE ATLTRACE
#elif defined(_DEBUG)
// Yeah, sue me lol
#define TRACE(...) { \
LPWSTR __traceMsg = (LPWSTR)LocalAlloc(LPTR, 4096 * sizeof(WCHAR)); \
wsprintf(__traceMsg, L"%hs(%d): %hs: ", __FILE__, __LINE__, __FUNCTION__); \
wsprintf(__traceMsg + wcslen(__traceMsg), __VA_ARGS__); \
MessageBox(NULL, __traceMsg, L"Debug", MB_OK); \
LocalFree(__traceMsg); \
}
#else
#define TRACE(...)
#endif

20
shared/User.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <windows.h>
static inline BOOL IsUserAdmin() {
SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
PSID adminsSid;
BOOL result = FALSE;
if (!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminsSid)) {
return FALSE;
}
if (!CheckTokenMembership(NULL, adminsSid, &result)) {
result = FALSE;
}
FreeSid(adminsSid);
return result;
}

6
shared/Version.h Normal file
View File

@ -0,0 +1,6 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 11
#define VERSION_PATCH 0
#define VERSION_BUILD 0
#define VERSION_STRING "1.11"

44
shared/VersionInfo.c Normal file
View File

@ -0,0 +1,44 @@
#include "stdafx.h"
#include "VersionInfo.h"
static BOOL _loadedOwnVersion = FALSE;
static LPWSTR _version;
HRESULT GetOwnVersion(LPWSTR *version) {
if (!_loadedOwnVersion) {
_loadedOwnVersion = TRUE;
LPWSTR filename;
GetOwnFileName(&filename);
DWORD verHandle;
DWORD verInfoSize = GetFileVersionInfoSize(filename, &verHandle);
if (verInfoSize == 0) {
LocalFree(filename);
return HRESULT_FROM_WIN32(GetLastError());
}
LPVOID verInfo = LocalAlloc(LPTR, verInfoSize);
if (!GetFileVersionInfo(filename, verHandle, verInfoSize, verInfo)) {
LocalFree(filename);
LocalFree(verInfo);
return HRESULT_FROM_WIN32(GetLastError());
}
LocalFree(filename);
LPWSTR value;
UINT size;
if (!VerQueryValue(verInfo, L"\\StringFileInfo\\040904B0\\ProductVersion", (LPVOID *)&value, &size)) {
LocalFree(verInfo);
return HRESULT_FROM_WIN32(GetLastError());
}
_version = (LPWSTR)LocalAlloc(LPTR, (wcslen(value) + 1) * sizeof(WCHAR));
wcscpy(_version, value);
LocalFree(verInfo);
}
*version = _version;
return _version == NULL ? E_FAIL : S_OK;
}

79
shared/WMI.c Normal file
View File

@ -0,0 +1,79 @@
#include "stdafx.h"
#include "WMI.h"
#include <wbemcli.h>
#pragma comment(lib, "wbemuuid.lib")
#ifdef __cplusplus
#define our_CLSID_WbemLocator CLSID_WbemLocator
#define our_IID_IWbemLocator IID_IWbemLocator
#define IWbemLocator_ConnectServer(obj, ...) obj->ConnectServer(__VA_ARGS__)
#define IWbemServices_ExecQuery(obj, ...) obj->ExecQuery(__VA_ARGS__)
#define IEnumWbemClassObject_Next(obj, ...) obj->Next(__VA_ARGS__)
#define IWbemClassObject_Get(obj, ...) obj->Get(__VA_ARGS__)
#define IWbemClassObject_Release(obj) obj->Release()
#define IEnumWbemClassObject_Release(obj) obj->Release()
#define IWbemServices_Release(obj) obj->Release()
#define IWbemLocator_Release(obj) obj->Release()
#else
#define our_CLSID_WbemLocator &CLSID_WbemLocator
#define our_IID_IWbemLocator &IID_IWbemLocator
#endif
HRESULT QueryWMIProperty(LPWSTR query, LPWSTR property, LPVARIANT value) {
IWbemLocator *locator = NULL;
IWbemServices *services = NULL;
IEnumWbemClassObject *enumerator = NULL;
IWbemClassObject *object = NULL;
HRESULT hr = CoCreateInstance(our_CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, our_IID_IWbemLocator, (void **)&locator);
if (!SUCCEEDED(hr)) {
goto end;
}
BSTR server = SysAllocString(L"ROOT\\CIMV2");
hr = IWbemLocator_ConnectServer(locator, server, NULL, NULL, NULL, 0, NULL, NULL, &services);
SysFreeString(server);
if (!SUCCEEDED(hr)) {
goto end;
}
hr = CoSetProxyBlanket((IUnknown *)services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (!SUCCEEDED(hr)) {
goto end;
}
BSTR wql = SysAllocString(L"WQL");
BSTR queryBstr = SysAllocString(query);
hr = IWbemServices_ExecQuery(services, wql, queryBstr, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &enumerator);
SysFreeString(wql);
SysFreeString(queryBstr);
if (!SUCCEEDED(hr)) {
goto end;
}
ULONG uReturn = 0;
hr = IEnumWbemClassObject_Next(enumerator, WBEM_INFINITE, 1, &object, &uReturn);
if (!SUCCEEDED(hr)) {
goto end;
}
BSTR propBstr = SysAllocString(property);
hr = IWbemClassObject_Get(object, propBstr, 0, value, NULL, NULL);
SysFreeString(propBstr);
end:
if (object) {
IWbemClassObject_Release(object);
}
if (enumerator) {
IEnumWbemClassObject_Release(enumerator);
}
if (services) {
IWbemServices_Release(services);
}
if (locator) {
IWbemLocator_Release(locator);
}
return hr;
}

44
shared/WULog.h Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include "stdafx.h"
#include <windows.h>
#include <shlobj.h>
#include "Exec.h"
#include "HResult.h"
#include "VersionInfo.h"
static inline HRESULT ViewWindowsUpdateLog(int nCmdShow) {
WCHAR windir[MAX_PATH];
HRESULT hr = SHGetFolderPath(0, CSIDL_WINDOWS, NULL, 0, windir);
if (!SUCCEEDED(hr)) {
TRACE(L"SHGetFolderPath() failed: %ls\n", GetMessageForHresult(hr));
return hr;
}
LPWSTR workDir = windir;
if (AtLeastWin10()) {
// Windows 10 moves WU/USO logs to ETW. The ETW logs can be converted back to a plain-text .log
// using a cmdlet.
WCHAR powershell[MAX_PATH];
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", powershell, ARRAYSIZE(powershell));
DWORD code;
HRESULT hr = Exec(NULL, powershell, L"-Command Get-WindowsUpdateLog", windir, nCmdShow, TRUE, &code);
if (!SUCCEEDED(hr) || code != 0) {
return hr;
}
// On success, the log is written to Desktop\WindowsUpdate.log.
WCHAR desktop[MAX_PATH];
hr = SHGetFolderPath(0, CSIDL_DESKTOP, NULL, 0, desktop);
if (!SUCCEEDED(hr)) {
TRACE(L"SHGetFolderPath() failed: %ls\n", GetMessageForHresult(hr));
return hr;
}
workDir = desktop;
}
return Exec(L"open", L"WindowsUpdate.log", NULL, workDir, nCmdShow, FALSE, NULL);
}

45
shared/Wow64.c Normal file
View File

@ -0,0 +1,45 @@
#include "stdafx.h"
#include "Wow64.h"
typedef BOOL (WINAPI *_Wow64DisableWow64FsRedirection)(PVOID *OldValue);
typedef BOOL (WINAPI *_Wow64RevertWow64FsRedirection)(PVOID OldValue);
static BOOL _loadedWow64;
static _Wow64DisableWow64FsRedirection $Wow64DisableWow64FsRedirection;
static _Wow64RevertWow64FsRedirection $Wow64RevertWow64FsRedirection;
#if _WIN64
// Not needed
#define DisableWow64FsRedirection(OldValue) TRUE
#define RevertWow64FsRedirection(OldValue) TRUE
#else
static void LoadWow64Symbols() {
if (!_loadedWow64) {
_loadedWow64 = TRUE;
HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
$Wow64DisableWow64FsRedirection = (_Wow64DisableWow64FsRedirection)GetProcAddress(kernel32, "Wow64DisableWow64FsRedirection");
$Wow64RevertWow64FsRedirection = (_Wow64RevertWow64FsRedirection)GetProcAddress(kernel32, "Wow64RevertWow64FsRedirection");
}
}
BOOL DisableWow64FsRedirection(PVOID *OldValue) {
LoadWow64Symbols();
if ($Wow64DisableWow64FsRedirection) {
return $Wow64DisableWow64FsRedirection(OldValue);
} else {
return TRUE;
}
}
BOOL RevertWow64FsRedirection(PVOID OldValue) {
LoadWow64Symbols();
if ($Wow64RevertWow64FsRedirection) {
return $Wow64RevertWow64FsRedirection(OldValue);
} else {
return TRUE;
}
}
#endif

6
shared/Wow64.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <windows.h>
BOOL DisableWow64FsRedirection(PVOID *OldValue);
BOOL RevertWow64FsRedirection(PVOID OldValue);