mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	installer: SxS: WIP
This commit is contained in:
		| @@ -21,10 +21,13 @@ | ||||
|  | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
| #include <windows.h> | ||||
| #include <shellapi.h> | ||||
| #include <msiquery.h> | ||||
| #include <wcautil.h> | ||||
| #include <strutil.h> | ||||
|  | ||||
| static HINSTANCE DllInstance; | ||||
|  | ||||
| UINT __stdcall InstanceID(MSIHANDLE MsiHandle) | ||||
| { | ||||
| #if 0 | ||||
| @@ -112,12 +115,218 @@ LExit: | ||||
|     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" | ||||
| BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved) | ||||
| { | ||||
|     switch(Reason) | ||||
|     { | ||||
|     case DLL_PROCESS_ATTACH: | ||||
|         DllInstance = Instance; | ||||
|         WcaGlobalInitialize(Instance); | ||||
|         break; | ||||
|     case DLL_PROCESS_DETACH: | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| EXPORTS | ||||
|     InstanceID | ||||
|     ServiceRunning | ||||
|     DeferredAction | ||||
|     InstallSymlinks | ||||
|     RemoveFiles | ||||
|   | ||||
| @@ -42,7 +42,7 @@ | ||||
|                 Name="PROCESSOR_ARCHITECTURE" | ||||
|                 Type="raw" /> | ||||
|         </Property> | ||||
|          | ||||
|  | ||||
|         <!-- Setup INSTALLDIR and SXSDIR from the registry or defaults. --> | ||||
|         <Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property> | ||||
|         <Property Id="P.LauncherRegistryKey">Software\$(var.MyProductName)\Services</Property> | ||||
| @@ -68,7 +68,7 @@ | ||||
|         <SetProperty Id="SXSDIR" Value="[INSTALLDIR]SxS\sxs.[InstanceID]\" After="SetINSTALLDIR"> | ||||
|             NOT SXSDIR | ||||
|         </SetProperty> | ||||
|          | ||||
|  | ||||
|         <!-- Setup directory structure. --> | ||||
|         <Directory Id="TARGETDIR" Name="SourceDir"> | ||||
|             <Directory Id="ProgramFilesFolder"> | ||||
| @@ -1020,7 +1020,7 @@ | ||||
|                 Value="WelcomeDlg" | ||||
|                 Order="10">NOT Installed</Publish> | ||||
|         </UI> | ||||
|          | ||||
|  | ||||
|         <!-- Custom Actions --> | ||||
|         <Binary Id="CustomActions" SourceFile="..\build\$(var.Configuration)\CustomActions.dll" /> | ||||
|  | ||||
| @@ -1071,5 +1071,89 @@ | ||||
|             </Custom> | ||||
|         </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> | ||||
| </Wix> | ||||
|   | ||||
| @@ -35,6 +35,10 @@ | ||||
|     <Compile Include="Product.wxs" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <WixExtension Include="WixUtilExtension"> | ||||
|       <HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath> | ||||
|       <Name>WixUtilExtension</Name> | ||||
|     </WixExtension> | ||||
|     <WixExtension Include="WixUIExtension"> | ||||
|       <HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath> | ||||
|       <Name>WixUIExtension</Name> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user