1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #define _WIN32_WINDOWS 0x0410
25 #ifdef _MSC_VER
26 #pragma warning(push, 1) /* disable warnings within system headers */
27 #endif
28 #define WIN32_LEAN_AND_MEAN
29 #include <windows.h>
30 #include <msiquery.h>
31 #ifdef _MSC_VER
32 #pragma warning(pop)
33 #endif
34 
35 #include <malloc.h>
36 
37 #ifdef UNICODE
38 #define _UNICODE
39 #define _tstring	wstring
40 #else
41 #define _tstring	string
42 #endif
43 #include <tchar.h>
44 #include <string>
45 
46 #include <io.h>
47 
GetMsiProperty(MSIHANDLE handle,const std::_tstring & sProperty)48 static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty )
49 {
50 	std::_tstring	result;
51 	TCHAR	szDummy[1] = TEXT("");
52 	DWORD	nChars = 0;
53 
54 	if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA )
55 	{
56         DWORD nBytes = ++nChars * sizeof(TCHAR);
57         LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
58         ZeroMemory( buffer, nBytes );
59         MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
60         result = buffer;
61 	}
62 
63 	return	result;
64 }
65 
66 
ExecuteCommand(LPCTSTR lpCommand,BOOL bSync)67 static BOOL ExecuteCommand( LPCTSTR lpCommand, BOOL bSync )
68 {
69 	BOOL				fSuccess = FALSE;
70 	STARTUPINFO			si;
71 	PROCESS_INFORMATION	pi;
72 
73 	ZeroMemory( &si, sizeof(si) );
74 	si.cb = sizeof(si);
75 
76 	fSuccess = CreateProcess(
77 		NULL,
78 		(LPTSTR)lpCommand,
79 		NULL,
80 		NULL,
81 		FALSE,
82 		0,
83 		NULL,
84 		NULL,
85 		&si,
86 		&pi
87 		);
88 
89 	if ( fSuccess )
90 	{
91 		if ( bSync )
92 			WaitForSingleObject( pi.hProcess, INFINITE );
93 
94 		CloseHandle( pi.hProcess );
95 		CloseHandle( pi.hThread );
96 	}
97 
98 	return fSuccess;
99 }
100 
ExecutePostUninstallScript(MSIHANDLE handle)101 extern "C" UINT __stdcall ExecutePostUninstallScript( MSIHANDLE handle )
102 {
103 	TCHAR	szValue[8192];
104 	DWORD	nValueSize = sizeof(szValue);
105 	HKEY	hKey;
106 	std::_tstring	sInstDir;
107 
108 	std::_tstring	sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") );
109 
110 	// MessageBox( NULL, sProductKey.c_str(), "Titel", MB_OK );
111 
112 	if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER,  sProductKey.c_str(), &hKey ) )
113 	{
114 		if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
115 		{
116 			sInstDir = szValue;
117 		}
118 		RegCloseKey( hKey );
119 	}
120 	else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,  sProductKey.c_str(), &hKey ) )
121 	{
122 		if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) )
123 		{
124 			sInstDir = szValue;
125 		}
126 		RegCloseKey( hKey );
127 	}
128 	else
129 		return ERROR_SUCCESS;
130 
131 	std::_tstring	sInfFile = sInstDir + TEXT("program\\postuninstall.inf");
132 	std::_tstring	sCommand = _T("RUNDLL32.EXE ");
133 
134 	// MessageBox( NULL, sInfFile.c_str(), "Titel", MB_OK );
135 
136 	if ( (LONG)GetVersion() < 0 )
137 		sCommand += _T("setupx.dll");
138 	else
139 		sCommand += _T("setupapi.dll");
140 
141 	sCommand += _T(",InstallHinfSection PostUninstall 132 ");
142 	sCommand += sInfFile;
143 
144 	if ( 0 == _taccess( sInfFile.c_str(), 2 ) )
145 		ExecuteCommand( sCommand.c_str(), TRUE );
146 
147 	DeleteFile( sInfFile.c_str() );
148 
149 	return ERROR_SUCCESS;
150 }
151 
152