2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// CustomAction.cpp : Defines the entry point for the custom action.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "pch.h" 
  
						 
					
						
							
								
									
										
										
										
											2024-04-11 12:06:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <stdlib.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-04-06 16:30:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <strutil.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  <shellapi.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-04-11 11:51:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <tlhelp32.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <winternl.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-04-11 18:54:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <netfw.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <shlwapi.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-12 17:42:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "./Common.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-11 18:54:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# pragma comment(lib, "Shlwapi.lib") 
  
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  CustomActionHello (  
						 
					
						
							
								
									
										
										
										
											2024-04-11 11:51:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    __in  MSIHANDLE  hInstall ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " CustomActionHello " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Initialized. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // TODO: Add your custom action code here.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " ================= Example CustomAction Hello " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  RemoveInstallFolder (  
						 
					
						
							
								
									
										
										
										
											2024-04-11 11:51:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    __in  MSIHANDLE  hInstall ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  nResult  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-06 16:30:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    LPWSTR  installFolder  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwz  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwzData  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " RemoveInstallFolder " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-06 16:30:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    hr  =  WcaGetProperty ( L " CustomActionData " ,  & pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to get CustomActionData " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pwz  =  pwzData ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaReadStringFromCaData ( & pwz ,  & installFolder ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to read database key from custom action data: %ls " ,  pwz ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SHFILEOPSTRUCTW  fileOp ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-11 11:51:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ZeroMemory ( & fileOp ,  sizeof ( SHFILEOPSTRUCT ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fileOp . wFunc  =  FO_DELETE ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-06 16:30:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fileOp . pFrom  =  installFolder ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    fileOp . fFlags  =  FOF_NOCONFIRMATION  |  FOF_SILENT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 00:47:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    nResult  =  SHFileOperationW ( & fileOp ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    if  ( nResult  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-06 16:30:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " The directory  \" %ls \"  has been deleted. " ,  installFolder ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-06 16:30:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " The directory  \" %ls \"  has not been deleted, error code: 0X%02X. Please refer to https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa for the error codes. " ,  installFolder ,  nResult ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
									
										
										
										
											2024-04-22 10:37:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ReleaseStr ( pwzData ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-06 16:30:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-03 14:27:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-04-11 11:51:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// **NtQueryInformationProcess** may be altered or unavailable in future versions of Windows.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Applications should use the alternate functions listed in this topic.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// But I do not find the alternate functions.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://github.com/heim-rs/heim/issues/105#issuecomment-683647573
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  NTSTATUS ( NTAPI  * pfnNtQueryInformationProcess ) ( HANDLE ,  PROCESSINFOCLASS ,  PVOID ,  ULONG ,  PULONG ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  TerminateProcessIfNotContainsParam ( pfnNtQueryInformationProcess  NtQueryInformationProcess ,  HANDLE  process ,  LPCWSTR  excludeParam )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  processClosed  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    PROCESS_BASIC_INFORMATION  processInfo ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    NTSTATUS  status  =  NtQueryInformationProcess ( process ,  ProcessBasicInformation ,  & processInfo ,  sizeof ( processInfo ) ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( status  = =  0  & &  processInfo . PebBaseAddress  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        PEB  peb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        SIZE_T  dwBytesRead ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ReadProcessMemory ( process ,  processInfo . PebBaseAddress ,  & peb ,  sizeof ( peb ) ,  & dwBytesRead ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            RTL_USER_PROCESS_PARAMETERS  pebUpp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ReadProcessMemory ( process , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  peb . ProcessParameters , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  & pebUpp , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  sizeof ( RTL_USER_PROCESS_PARAMETERS ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  & dwBytesRead ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( pebUpp . CommandLine . Length  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    WCHAR  * commandLine  =  ( WCHAR  * ) malloc ( pebUpp . CommandLine . Length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  ( commandLine  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  ( ReadProcessMemory ( process ,  pebUpp . CommandLine . Buffer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              commandLine ,  pebUpp . CommandLine . Length ,  & dwBytesRead ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            if  ( wcsstr ( commandLine ,  excludeParam )  = =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                WcaLog ( LOGMSG_STANDARD ,  " Terminate process : %ls " ,  commandLine ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                TerminateProcess ( process ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                processClosed  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        free ( commandLine ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  processClosed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Terminate processes that do not have parameter [excludeParam]
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note. This function relies on "NtQueryInformationProcess",
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//       which may not be found.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//       Then all processes of [processName] will be terminated.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  TerminateProcessesByNameW ( LPCWSTR  processName ,  LPCWSTR  excludeParam )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HMODULE  hntdll  =  GetModuleHandleW ( L " ntdll.dll " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( hntdll  = =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to load ntdll. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pfnNtQueryInformationProcess  NtQueryInformationProcess  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( hntdll  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        NtQueryInformationProcess  =  ( pfnNtQueryInformationProcess ) GetProcAddress ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            hntdll ,  " NtQueryInformationProcess " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( NtQueryInformationProcess  = =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to get address of NtQueryInformationProcess. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  processClosed  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Create a snapshot of the current system processes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HANDLE  snapshot  =  CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( snapshot  ! =  INVALID_HANDLE_VALUE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        PROCESSENTRY32W  processEntry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        processEntry . dwSize  =  sizeof ( PROCESSENTRY32W ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( Process32FirstW ( snapshot ,  & processEntry ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            do 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( lstrcmpW ( processName ,  processEntry . szExeFile )  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    HANDLE  process  =  OpenProcess ( PROCESS_TERMINATE  |  PROCESS_QUERY_INFORMATION  |  PROCESS_VM_READ ,  FALSE ,  processEntry . th32ProcessID ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  ( process  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  ( NtQueryInformationProcess  = =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            WcaLog ( LOGMSG_STANDARD ,  " Terminate process : %ls, while NtQueryInformationProcess is NULL " ,  processName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            TerminateProcess ( process ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            processClosed  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            processClosed  =  TerminateProcessIfNotContainsParam ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                NtQueryInformationProcess , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                process , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                excludeParam ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        CloseHandle ( process ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 00:47:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            }  while  ( Process32NextW ( snapshot ,  & processEntry ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-11 11:51:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        CloseHandle ( snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( hntdll  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        CloseHandle ( hntdll ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  processClosed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  TerminateProcesses (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    __in  MSIHANDLE  hInstall ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  nResult  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szProcess [ 256 ]  =  { 0 } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchProcess  =  sizeof ( szProcess )  /  sizeof ( szProcess [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " TerminateProcesses " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " TerminateProcesses " ,  szProcess ,  & cchProcess ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try terminate processes : %ls " ,  szProcess ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    TerminateProcessesByNameW ( szProcess ,  L " --install " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-04-11 18:54:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// No use for now, it can be refer as an example of ShellExecuteW.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  AddFirewallRuleCmdline ( LPWSTR  exeName ,  LPWSTR  exeFile ,  LPCWSTR  dir )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HINSTANCE  hi  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  cmdline [ 1024 ]  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  rulename [ 500 ]  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StringCchPrintfW ( rulename ,  sizeof ( rulename )  /  sizeof ( rulename [ 0 ] ) ,  L " %ls Service " ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( hr  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to make rulename: %ls " ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StringCchPrintfW ( cmdline ,  sizeof ( cmdline )  /  sizeof ( cmdline [ 0 ] ) ,  L " advfirewall firewall add rule name= \" %ls \"  dir=%ls action=allow program= \" %ls \"  enable=yes " ,  rulename ,  dir ,  exeFile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( hr  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to make cmdline: %ls " ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hi  =  ShellExecuteW ( NULL ,  L " open " ,  L " netsh " ,  cmdline ,  NULL ,  SW_HIDE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( int ) hi  < =  32 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to change firewall rule : %d, last error: %d " ,  ( int ) hi ,  GetLastError ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Firewall rule  \" %ls \"  (%ls) is added " ,  rulename ,  dir ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// No use for now, it can be refer as an example of ShellExecuteW.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  RemoveFirewallRuleCmdline ( LPWSTR  exeName )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HINSTANCE  hi  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  cmdline [ 1024 ]  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  rulename [ 500 ]  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StringCchPrintfW ( rulename ,  sizeof ( rulename )  /  sizeof ( rulename [ 0 ] ) ,  L " %ls Service " ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( hr  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to make rulename: %ls " ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StringCchPrintfW ( cmdline ,  sizeof ( cmdline )  /  sizeof ( cmdline [ 0 ] ) ,  L " advfirewall firewall delete rule name= \" %ls \" " ,  rulename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( hr  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to make cmdline: %ls " ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hi  =  ShellExecuteW ( NULL ,  L " open " ,  L " netsh " ,  cmdline ,  NULL ,  SW_HIDE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( int ) hi  < =  32 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to change firewall rule  \" %ls \"  : %d, last error: %d " ,  rulename ,  ( int ) hi ,  GetLastError ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Firewall rule  \" %ls \"  is removed " ,  rulename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  AddFirewallRules (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    __in  MSIHANDLE  hInstall ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  nResult  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  exeFile  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  exeName  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  exeNameNoExt [ 500 ]  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwz  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwzData  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  szNameLen  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-14 21:03:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " AddFirewallRules " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-11 18:54:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaGetProperty ( L " CustomActionData " ,  & pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to get CustomActionData " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pwz  =  pwzData ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaReadStringFromCaData ( & pwz ,  & exeFile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to read database key from custom action data: %ls " ,  pwz ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try add firewall exceptions for file : %ls " ,  exeFile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    exeName  =  PathFindFileNameW ( exeFile  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  StringCchPrintfW ( exeNameNoExt ,  500 ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to copy exe name: %ls " ,  exeName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    szNameLen  =  wcslen ( exeNameNoExt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( szNameLen  > =  4  & &  wcscmp ( exeNameNoExt  +  szNameLen  -  4 ,  L " .exe " )  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        exeNameNoExt [ szNameLen  -  4 ]  =  L ' \0 ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //if (exeFile[0] == L'1') {
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    AddFirewallRuleCmdline(exeNameNoExt, exeFile, L"in");
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    AddFirewallRuleCmdline(exeNameNoExt, exeFile, L"out");
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //}
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //else {
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    RemoveFirewallRuleCmdline(exeNameNoExt);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //}
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    AddFirewallRule ( exeFile [ 0 ]  = =  L ' 1 ' ,  exeNameNoExt ,  exeFile  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( pwzData )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ReleaseStr ( pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-04-12 17:42:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  SetPropertyIsServiceRunning ( __in  MSIHANDLE  hInstall )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szAppName [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchAppName  =  sizeof ( szAppName )  /  sizeof ( szAppName [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szPropertyName [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchPropertyName  =  sizeof ( szPropertyName )  /  sizeof ( szPropertyName [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  isRunning  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " SetPropertyIsServiceRunning " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " AppName " ,  szAppName ,  & cchAppName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try query service of :  \" %ls \" " ,  szAppName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " PropertyName " ,  szPropertyName ,  & cchPropertyName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try set is service running, property name :  \" %ls \" " ,  szPropertyName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isRunning  =  IsServiceRunningW ( szAppName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiSetPropertyW ( hInstall ,  szPropertyName ,  isRunning  ?  L " 'N' "  :  L " 'Y' " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  CreateStartService ( __in  MSIHANDLE  hInstall )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  svcParams  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwz  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwzData  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  svcName  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  svcBinary  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szSvcDisplayName [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchSvcDisplayName  =  sizeof ( szSvcDisplayName )  /  sizeof ( szSvcDisplayName [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " CreateStartService " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaGetProperty ( L " CustomActionData " ,  & pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to get CustomActionData " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pwz  =  pwzData ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaReadStringFromCaData ( & pwz ,  & svcParams ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to read database key from custom action data: %ls " ,  pwz ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try create start service : %ls " ,  svcParams ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    svcName  =  svcParams ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    svcBinary  =  wcschr ( svcParams ,  L ' ; ' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( svcBinary  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to find binary : %ls " ,  svcParams ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        goto  LExit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    svcBinary [ 0 ]  =  L ' \0 ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    svcBinary  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  StringCchPrintfW ( szSvcDisplayName ,  cchSvcDisplayName ,  L " %ls Service " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to compose a resource identifier string " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( MyCreateServiceW ( svcName ,  szSvcDisplayName ,  svcBinary ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Service  \" %ls \"  is created. " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( MyStartServiceW ( svcName ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WcaLog ( LOGMSG_STANDARD ,  " Service  \" %ls \"  is started. " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WcaLog ( LOGMSG_STANDARD ,  " Failed to start service:  \" %ls \" " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to create service:  \" %ls \" " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( pwzData )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ReleaseStr ( pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  TryStopDeleteService ( __in  MSIHANDLE  hInstall )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  nResult  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  svcName  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwz  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwzData  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szExeFile [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchExeFile  =  sizeof ( szExeFile )  /  sizeof ( szExeFile [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " TryStopDeleteService " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaGetProperty ( L " CustomActionData " ,  & pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to get CustomActionData " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pwz  =  pwzData ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaReadStringFromCaData ( & pwz ,  & svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to read database key from custom action data: %ls " ,  pwz ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try stop and delete service : %ls " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( MyStopServiceW ( svcName ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( int  i  =  0 ;  i  <  10 ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( IsServiceRunningW ( svcName ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                Sleep ( 100 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Service  \" %ls \"  is stopped " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to stop service:  \" %ls \" " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( MyDeleteServiceW ( svcName ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Service  \" %ls \"  is deleted " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to delete service:  \" %ls \" " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // It's really strange that we need sleep here.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // But the upgrading may be stucked at "copying new files" because the file is in using.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Steps to reproduce: Install -> stop service in tray --> start service -> upgrade
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Sleep(300);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Or we can terminate the process
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  StringCchPrintfW ( szExeFile ,  cchExeFile ,  L " %ls.exe " ,  svcName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to compose a resource identifier string " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    TerminateProcessesByNameW ( szExeFile ,  L " --not-in-use " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( pwzData )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ReleaseStr ( pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  TryDeleteStartupShortcut ( __in  MSIHANDLE  hInstall )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szShortcut [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchShortcut  =  sizeof ( szShortcut )  /  sizeof ( szShortcut [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szStartupDir [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchStartupDir  =  sizeof ( szStartupDir )  /  sizeof ( szStartupDir [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  pwszTemp [ 1024 ]  =  L " " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " DeleteStartupShortcut " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " StartupFolder " ,  szStartupDir ,  & cchStartupDir ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " ShortcutName " ,  szShortcut ,  & cchShortcut ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try delete startup shortcut of :  \" %ls \" " ,  szShortcut ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  StringCchPrintfW ( pwszTemp ,  1024 ,  L " %ls%ls.lnk " ,  szStartupDir ,  szShortcut ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to compose a resource identifier string " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 00:47:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( DeleteFileW ( pwszTemp ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-12 17:42:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to delete startup shortcut of :  \" %ls \" " ,  pwszTemp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Startup shortcut is deleted :  \" %ls \" " ,  pwszTemp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  SetPropertyFromConfig ( __in  MSIHANDLE  hInstall )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szConfigFile [ 1024 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchConfigFile  =  sizeof ( szConfigFile )  /  sizeof ( szConfigFile [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szConfigKey [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchConfigKey  =  sizeof ( szConfigKey )  /  sizeof ( szConfigKey [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    wchar_t  szPropertyName [ 500 ]  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cchPropertyName  =  sizeof ( szPropertyName )  /  sizeof ( szPropertyName [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : wstring  configValue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " SetPropertyFromConfig " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " ConfigFile " ,  szConfigFile ,  & cchConfigFile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try read config file of :  \" %ls \" " ,  szConfigFile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " ConfigKey " ,  szConfigKey ,  & cchConfigKey ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try read configuration, config key :  \" %ls \" " ,  szConfigKey ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiGetPropertyW ( hInstall ,  L " PropertyName " ,  szPropertyName ,  & cchPropertyName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Try read configuration, property name :  \" %ls \" " ,  szPropertyName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    configValue  =  ReadConfig ( szConfigFile ,  szConfigKey ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MsiSetPropertyW ( hInstall ,  szPropertyName ,  configValue . c_str ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-04-14 21:03:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  AddRegSoftwareSASGeneration ( __in  MSIHANDLE  hInstall )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     LSTATUS  result  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     HKEY  hKey ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     LPCWSTR  subKey  =  L " Software \\ Microsoft \\ Windows \\ CurrentVersion \\ Policies \\ System " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     LPCWSTR  valueName  =  L " SoftwareSASGeneration " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     DWORD  valueType  =  REG_DWORD ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     DWORD  valueData  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     DWORD  valueDataSize  =  sizeof ( DWORD ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HINSTANCE  hi  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " AddRegSoftwareSASGeneration " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hi  =  ShellExecuteW ( NULL ,  L " open " ,  L " reg " ,  L "  add HKEY_LOCAL_MACHINE \\ Software \\ Microsoft \\ Windows \\ CurrentVersion \\ Policies \\ System /f /v SoftwareSASGeneration /t REG_DWORD /d 1 " ,  NULL ,  SW_HIDE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( int ) hi  < =  32 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to add registry name  \" %ls \" , %d, %d " ,  valueName ,  ( int ) hi ,  GetLastError ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Registry name  \" %ls \"  is added " ,  valueName ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Why RegSetValueExW always return 998?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    result  =  RegCreateKeyExW ( HKEY_LOCAL_MACHINE ,  subKey ,  0 ,  NULL ,  REG_OPTION_NON_VOLATILE ,  KEY_WRITE ,  NULL ,  & hKey ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( result  ! =  ERROR_SUCCESS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to create or open registry key: %d " ,  result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        goto  LExit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    result  =  RegSetValueExW ( hKey ,  valueName ,  0 ,  valueType ,  reinterpret_cast < const  BYTE * > ( valueData ) ,  valueDataSize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( result  ! =  ERROR_SUCCESS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to set registry value: %d " ,  result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        RegCloseKey ( hKey ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        goto  LExit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Registry value has been successfully set. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    RegCloseKey ( hKey ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-04-19 11:31:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								UINT  __stdcall  RemoveAmyuniIdd (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    __in  MSIHANDLE  hInstall ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HRESULT  hr  =  S_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  er  =  ERROR_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-23 17:00:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    int  nResult  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  installFolder  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwz  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPWSTR  pwzData  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  workDir [ 1024 ]  =  L " " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  fileAttributes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HINSTANCE  hi  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SYSTEM_INFO  si ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LPCWSTR  exe  =  L " deviceinstaller64.exe " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WCHAR  exePath [ 1024 ]  =  L " " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-22 10:37:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    BOOL  rebootRequired  =  FALSE ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 11:31:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaInitialize ( hInstall ,  " RemoveAmyuniIdd " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to initialize " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-22 10:37:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    UninstallDriver ( L " usbmmidd " ,  rebootRequired ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 11:31:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-23 17:00:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // Only for x86 app on x64
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    GetNativeSystemInfo ( & si ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( si . wProcessorArchitecture  ! =  PROCESSOR_ARCHITECTURE_AMD64 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        goto  LExit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaGetProperty ( L " CustomActionData " ,  & pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to get CustomActionData " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pwz  =  pwzData ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  WcaReadStringFromCaData ( & pwz ,  & installFolder ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " failed to read database key from custom action data: %ls " ,  pwz ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  StringCchPrintfW ( workDir ,  1024 ,  L " %lsusbmmidd_v2 " ,  installFolder ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to compose a resource identifier string " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fileAttributes  =  GetFileAttributesW ( workDir ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( fileAttributes  = =  INVALID_FILE_ATTRIBUTES )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Amyuni idd dir  \" %ls \"  is not found, %d " ,  workDir ,  fileAttributes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        goto  LExit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hr  =  StringCchPrintfW ( exePath ,  1024 ,  L " %ls \\ %ls " ,  workDir ,  exe ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ExitOnFailure ( hr ,  " Failed to compose a resource identifier string " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fileAttributes  =  GetFileAttributesW ( exePath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( fileAttributes  = =  INVALID_FILE_ATTRIBUTES )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        goto  LExit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WcaLog ( LOGMSG_STANDARD ,  " Remove amyuni idd %ls in %ls " ,  exe ,  workDir ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    hi  =  ShellExecuteW ( NULL ,  L " open " ,  exe ,  L " remove usbmmidd " ,  workDir ,  SW_HIDE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( int ) hi  < =  32 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Failed to remove amyuni idd : %d, last error: %d " ,  ( int ) hi ,  GetLastError ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        WcaLog ( LOGMSG_STANDARD ,  " Amyuni idd is removed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 11:31:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								LExit :  
						 
					
						
							
								
									
										
										
										
											2024-04-23 17:00:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( pwzData )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ReleaseStr ( pwzData ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 11:31:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    er  =  SUCCEEDED ( hr )  ?  ERROR_SUCCESS  :  ERROR_INSTALL_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  WcaFinalize ( er ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}