mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
installer: SxS: WIP
This commit is contained in:
parent
329b14d838
commit
de9112f6e6
@ -21,10 +21,13 @@
|
|||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shellapi.h>
|
||||||
#include <msiquery.h>
|
#include <msiquery.h>
|
||||||
#include <wcautil.h>
|
#include <wcautil.h>
|
||||||
#include <strutil.h>
|
#include <strutil.h>
|
||||||
|
|
||||||
|
static HINSTANCE DllInstance;
|
||||||
|
|
||||||
UINT __stdcall InstanceID(MSIHANDLE MsiHandle)
|
UINT __stdcall InstanceID(MSIHANDLE MsiHandle)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@ -112,12 +115,218 @@ LExit:
|
|||||||
return WcaFinalize(err);
|
return WcaFinalize(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT __stdcall DeferredAction(MSIHANDLE MsiHandle)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
WCHAR MessageBuf[64];
|
||||||
|
wsprintfW(MessageBuf, L"PID=%ld", GetCurrentProcessId());
|
||||||
|
MessageBoxW(0, MessageBuf, L"" __FUNCTION__ " Break", MB_OK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
UINT err = ERROR_SUCCESS;
|
||||||
|
PWSTR CommandLine = 0;
|
||||||
|
PWSTR *Argv;
|
||||||
|
int Argc;
|
||||||
|
CHAR ProcName[64];
|
||||||
|
FARPROC Proc;
|
||||||
|
|
||||||
|
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||||
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
|
hr = WcaGetProperty(L"CustomActionData", &CommandLine);
|
||||||
|
ExitOnFailure(hr, "Failed to get CommandLine");
|
||||||
|
|
||||||
|
WcaLog(LOGMSG_STANDARD, "Initialized: \"%S\"", CommandLine);
|
||||||
|
|
||||||
|
Argv = CommandLineToArgvW(CommandLine, &Argc);
|
||||||
|
ExitOnNullWithLastError(Argv, hr, "Failed to CommandLineToArgvW");
|
||||||
|
|
||||||
|
if (0 < Argc)
|
||||||
|
{
|
||||||
|
if (0 == WideCharToMultiByte(CP_UTF8, 0, Argv[0], -1, ProcName, sizeof ProcName, 0, 0))
|
||||||
|
ExitWithLastError(hr, "Failed to WideCharToMultiByte");
|
||||||
|
|
||||||
|
Proc = GetProcAddress(DllInstance, ProcName);
|
||||||
|
ExitOnNullWithLastError(Proc, hr, "Failed to GetProcAddress");
|
||||||
|
|
||||||
|
err = ((HRESULT (*)(int, PWSTR *))Proc)(Argc, Argv);
|
||||||
|
ExitOnWin32Error(err, hr, "Failed to %S", ProcName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
ExitOnFailure(hr, "Failed to get arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
LExit:
|
||||||
|
LocalFree(Argv);
|
||||||
|
ReleaseStr(CommandLine);
|
||||||
|
|
||||||
|
err = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||||
|
return WcaFinalize(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD CreateSymlink(PWSTR Symlink, PWSTR Target);
|
||||||
|
static DWORD RemoveFile(PWSTR FileName);
|
||||||
|
|
||||||
|
DWORD InstallSymlinks(int Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
/* usage: InstallSymlinks SourceDir TargetDir Name... */
|
||||||
|
|
||||||
|
DWORD Result;
|
||||||
|
PWSTR SourceDir, TargetDir;
|
||||||
|
WCHAR SourcePath[MAX_PATH], TargetPath[MAX_PATH];
|
||||||
|
int SourceDirLen, TargetDirLen, Len;
|
||||||
|
|
||||||
|
if (4 > Argc)
|
||||||
|
{
|
||||||
|
Result = ERROR_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceDir = Argv[1];
|
||||||
|
TargetDir = Argv[2];
|
||||||
|
SourceDirLen = lstrlenW(SourceDir);
|
||||||
|
TargetDirLen = lstrlenW(TargetDir);
|
||||||
|
|
||||||
|
for (int Argi = 3; Argc > Argi; Argi++)
|
||||||
|
{
|
||||||
|
Len = lstrlenW(Argv[Argi]);
|
||||||
|
if (MAX_PATH < SourceDirLen + Len + 1 || MAX_PATH < TargetDirLen + Len + 1)
|
||||||
|
{
|
||||||
|
Result = ERROR_FILENAME_EXCED_RANGE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(SourcePath, SourceDir, SourceDirLen * sizeof(WCHAR));
|
||||||
|
memcpy(SourcePath + SourceDirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||||
|
SourcePath[SourceDirLen + Len] = L'\0';
|
||||||
|
|
||||||
|
memcpy(TargetPath, TargetDir, TargetDirLen * sizeof(WCHAR));
|
||||||
|
memcpy(TargetPath + TargetDirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||||
|
TargetPath[TargetDirLen + Len] = L'\0';
|
||||||
|
|
||||||
|
Result = CreateSymlink(SourcePath, TargetPath);
|
||||||
|
#if 0
|
||||||
|
WCHAR MessageBuf[1024];
|
||||||
|
wsprintfW(MessageBuf, L"CreateSymlink(\"%s\", \"%s\") = %lu", SourcePath, TargetPath, Result);
|
||||||
|
MessageBoxW(0, MessageBuf, L"TRACE", MB_OK);
|
||||||
|
#endif
|
||||||
|
if (ERROR_SUCCESS != Result)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD RemoveFiles(int Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
/* usage: RemoveFiles Dir Name... */
|
||||||
|
|
||||||
|
DWORD Result;
|
||||||
|
PWSTR Dir;
|
||||||
|
WCHAR Path[MAX_PATH];
|
||||||
|
int DirLen, Len;
|
||||||
|
|
||||||
|
if (3 > Argc)
|
||||||
|
{
|
||||||
|
Result = ERROR_INVALID_PARAMETER;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dir = Argv[1];
|
||||||
|
DirLen = lstrlenW(Dir);
|
||||||
|
|
||||||
|
for (int Argi = 2; Argc > Argi; Argi++)
|
||||||
|
{
|
||||||
|
Len = lstrlenW(Argv[Argi]);
|
||||||
|
if (MAX_PATH < DirLen + Len + 1)
|
||||||
|
{
|
||||||
|
Result = ERROR_FILENAME_EXCED_RANGE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(Path, Dir, DirLen * sizeof(WCHAR));
|
||||||
|
memcpy(Path + DirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||||
|
Path[DirLen + Len] = L'\0';
|
||||||
|
|
||||||
|
Result = RemoveFile(Path);
|
||||||
|
#if 0
|
||||||
|
WCHAR MessageBuf[1024];
|
||||||
|
wsprintfW(MessageBuf, L"RemoveFile(\"%s\") = %lu", Path, Result);
|
||||||
|
MessageBoxW(0, MessageBuf, L"TRACE", MB_OK);
|
||||||
|
#endif
|
||||||
|
if (ERROR_SUCCESS != Result)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD CreateSymlink(PWSTR Symlink, PWSTR Target)
|
||||||
|
{
|
||||||
|
DWORD Result;
|
||||||
|
DWORD FileAttributes, Flags;
|
||||||
|
|
||||||
|
FileAttributes = GetFileAttributesW(Target);
|
||||||
|
if (INVALID_FILE_ATTRIBUTES == FileAttributes)
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
Flags = 0 != (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
|
||||||
|
|
||||||
|
RemoveFile(Symlink);
|
||||||
|
|
||||||
|
if (!CreateSymbolicLinkW(Symlink, Target, Flags))
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD RemoveFile(PWSTR FileName)
|
||||||
|
{
|
||||||
|
DWORD Result;
|
||||||
|
|
||||||
|
if (!RemoveDirectoryW(FileName))
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
if (ERROR_DIRECTORY != Result)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (!DeleteFileW(FileName))
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||||
{
|
{
|
||||||
switch(Reason)
|
switch(Reason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
DllInstance = Instance;
|
||||||
WcaGlobalInitialize(Instance);
|
WcaGlobalInitialize(Instance);
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
EXPORTS
|
EXPORTS
|
||||||
InstanceID
|
InstanceID
|
||||||
ServiceRunning
|
ServiceRunning
|
||||||
|
DeferredAction
|
||||||
|
InstallSymlinks
|
||||||
|
RemoveFiles
|
||||||
|
@ -1071,5 +1071,89 @@
|
|||||||
</Custom>
|
</Custom>
|
||||||
</InstallUISequence>
|
</InstallUISequence>
|
||||||
|
|
||||||
|
<!-- InstallSymlinks installs SxS symlinks -->
|
||||||
|
<SetProperty
|
||||||
|
Id="Deferred.InstallSymlinks"
|
||||||
|
Value='InstallSymlinks "[INSTALLDIR]\" "[SXSDIR]\" bin'
|
||||||
|
Before="Deferred.InstallSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Deferred.InstallSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="deferred"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="check" />
|
||||||
|
<SetProperty
|
||||||
|
Id="Rollback.InstallSymlinks"
|
||||||
|
Value='RemoveFiles "[INSTALLDIR]\" bin'
|
||||||
|
Before="Rollback.InstallSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Rollback.InstallSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="rollback"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="ignore" />
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<!--
|
||||||
|
deferred: `InstallSymlinks` on install or repair
|
||||||
|
rollback: `RemoveSymlinks` on install only
|
||||||
|
-->
|
||||||
|
<Custom Action="Rollback.InstallSymlinks" After="InstallFiles">
|
||||||
|
NOT Installed
|
||||||
|
</Custom>
|
||||||
|
<Custom Action="Deferred.InstallSymlinks" After="Rollback.InstallSymlinks">
|
||||||
|
((NOT Installed) OR REINSTALL)
|
||||||
|
</Custom>
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
|
<!-- RemoveSymlinks removes SxS symlinks -->
|
||||||
|
<SetProperty
|
||||||
|
Id="Deferred.RemoveSymlinks"
|
||||||
|
Value='RemoveFiles "[INSTALLDIR]\" bin'
|
||||||
|
Before="Deferred.RemoveSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Deferred.RemoveSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="deferred"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="ignore" />
|
||||||
|
<SetProperty
|
||||||
|
Id="Rollback.RemoveSymlinks"
|
||||||
|
Value='InstallSymlinks "[INSTALLDIR]\" "[SXSDIR]\" bin'
|
||||||
|
Before="Rollback.RemoveSymlinks"
|
||||||
|
Sequence="execute" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Rollback.RemoveSymlinks"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="DeferredAction"
|
||||||
|
Execute="rollback"
|
||||||
|
Impersonate="no"
|
||||||
|
Return="check" />
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<!--
|
||||||
|
deferred: `RemoveSymlinks` on uninstall
|
||||||
|
rollback: `InstallSymlinks` on uninstall
|
||||||
|
-->
|
||||||
|
<Custom Action="Rollback.RemoveSymlinks" Before="RemoveFiles">
|
||||||
|
REMOVE
|
||||||
|
</Custom>
|
||||||
|
<Custom Action="Deferred.RemoveSymlinks" After="Rollback.RemoveSymlinks">
|
||||||
|
REMOVE
|
||||||
|
</Custom>
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Specify WIXFAILWHENDEFERRED=1 on the msiexec cmdline for rollback testing.
|
||||||
|
See http://tinyurl.com/yxkaywek
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<Property Id="WIXFAILWHENDEFERRED" Value="0" Secure="yes" />
|
||||||
|
<CustomActionRef Id="WixFailWhenDeferred" />
|
||||||
|
-->
|
||||||
</Product>
|
</Product>
|
||||||
</Wix>
|
</Wix>
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
<Compile Include="Product.wxs" />
|
<Compile Include="Product.wxs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<WixExtension Include="WixUtilExtension">
|
||||||
|
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
|
||||||
|
<Name>WixUtilExtension</Name>
|
||||||
|
</WixExtension>
|
||||||
<WixExtension Include="WixUIExtension">
|
<WixExtension Include="WixUIExtension">
|
||||||
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
||||||
<Name>WixUIExtension</Name>
|
<Name>WixUIExtension</Name>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user