1*32b1fd08SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*32b1fd08SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*32b1fd08SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*32b1fd08SAndrew Rist  * distributed with this work for additional information
6*32b1fd08SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*32b1fd08SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*32b1fd08SAndrew Rist  * "License"); you may not use this file except in compliance
9*32b1fd08SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*32b1fd08SAndrew Rist  *
11*32b1fd08SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*32b1fd08SAndrew Rist  *
13*32b1fd08SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*32b1fd08SAndrew Rist  * software distributed under the License is distributed on an
15*32b1fd08SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*32b1fd08SAndrew Rist  * KIND, either express or implied.  See the License for the
17*32b1fd08SAndrew Rist  * specific language governing permissions and limitations
18*32b1fd08SAndrew Rist  * under the License.
19*32b1fd08SAndrew Rist  *
20*32b1fd08SAndrew Rist  *************************************************************/
21*32b1fd08SAndrew Rist 
22*32b1fd08SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #undef UNICODE
25cdf0e10cSrcweir #undef _UNICODE
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #define _WIN32_WINDOWS 0x0410
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #ifdef _MSC_VER
30cdf0e10cSrcweir #pragma warning(push, 1) /* disable warnings within system headers */
31cdf0e10cSrcweir #endif
32cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN
33cdf0e10cSrcweir #include <windows.h>
34cdf0e10cSrcweir #include <msiquery.h>
35cdf0e10cSrcweir #ifdef _MSC_VER
36cdf0e10cSrcweir #pragma warning(pop)
37cdf0e10cSrcweir #endif
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <malloc.h>
40cdf0e10cSrcweir #include <assert.h>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include <tchar.h>
43cdf0e10cSrcweir #include <string>
44cdf0e10cSrcweir #include <systools/win32/uwinapi.h>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #include <../tools/seterror.hxx>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir using namespace std;
49cdf0e10cSrcweir 
50cdf0e10cSrcweir namespace
51cdf0e10cSrcweir {
GetMsiProperty(MSIHANDLE handle,const string & sProperty)52cdf0e10cSrcweir     string GetMsiProperty(MSIHANDLE handle, const string& sProperty)
53cdf0e10cSrcweir     {
54cdf0e10cSrcweir         string  result;
55cdf0e10cSrcweir         TCHAR   szDummy[1] = TEXT("");
56cdf0e10cSrcweir         DWORD   nChars = 0;
57cdf0e10cSrcweir 
58cdf0e10cSrcweir         if (MsiGetProperty(handle, sProperty.c_str(), szDummy, &nChars) == ERROR_MORE_DATA)
59cdf0e10cSrcweir         {
60cdf0e10cSrcweir             DWORD nBytes = ++nChars * sizeof(TCHAR);
61cdf0e10cSrcweir             LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
62cdf0e10cSrcweir             ZeroMemory( buffer, nBytes );
63cdf0e10cSrcweir             MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
64cdf0e10cSrcweir             result = buffer;
65cdf0e10cSrcweir         }
66cdf0e10cSrcweir         return result;
67cdf0e10cSrcweir     }
68cdf0e10cSrcweir 
IsSetMsiProperty(MSIHANDLE handle,const string & sProperty)69cdf0e10cSrcweir     inline bool IsSetMsiProperty(MSIHANDLE handle, const string& sProperty)
70cdf0e10cSrcweir     {
71cdf0e10cSrcweir         return (GetMsiProperty(handle, sProperty).length() > 0);
72cdf0e10cSrcweir     }
73cdf0e10cSrcweir 
UnsetMsiProperty(MSIHANDLE handle,const string & sProperty)74cdf0e10cSrcweir     inline void UnsetMsiProperty(MSIHANDLE handle, const string& sProperty)
75cdf0e10cSrcweir     {
76cdf0e10cSrcweir         MsiSetProperty(handle, sProperty.c_str(), NULL);
77cdf0e10cSrcweir     }
78cdf0e10cSrcweir 
SetMsiProperty(MSIHANDLE handle,const string & sProperty,const string &)79cdf0e10cSrcweir     inline void SetMsiProperty(MSIHANDLE handle, const string& sProperty, const string&)
80cdf0e10cSrcweir     {
81cdf0e10cSrcweir         MsiSetProperty(handle, sProperty.c_str(), TEXT("1"));
82cdf0e10cSrcweir     }
83cdf0e10cSrcweir 
stripFinalBackslash(std::string * path)84cdf0e10cSrcweir     void stripFinalBackslash(std::string * path) {
85cdf0e10cSrcweir         std::string::size_type i = path->size();
86cdf0e10cSrcweir         if (i > 1) {
87cdf0e10cSrcweir             --i;
88cdf0e10cSrcweir             if ((*path)[i] == '\\') {
89cdf0e10cSrcweir                 path->erase(i);
90cdf0e10cSrcweir             }
91cdf0e10cSrcweir         }
92cdf0e10cSrcweir     }
93cdf0e10cSrcweir } // namespace
94cdf0e10cSrcweir 
CreateLayerLinks(MSIHANDLE handle)95cdf0e10cSrcweir extern "C" UINT __stdcall CreateLayerLinks(MSIHANDLE handle)
96cdf0e10cSrcweir {
97cdf0e10cSrcweir     string sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
98cdf0e10cSrcweir 
99cdf0e10cSrcweir     string sOfficeInstallPath = sInstallPath;
100cdf0e10cSrcweir     string sBasisInstallPath = sInstallPath + TEXT("Basis\\");
101cdf0e10cSrcweir     string sUreInstallPath = sInstallPath + TEXT("URE\\");
102cdf0e10cSrcweir 
103cdf0e10cSrcweir     string sBasisLinkPath = sInstallPath + TEXT("basis-link");
104cdf0e10cSrcweir     string sUreLinkPath = sInstallPath + TEXT("Basis\\ure-link");
105cdf0e10cSrcweir 
106cdf0e10cSrcweir     if ( IsSetMsiProperty(handle, TEXT("ADMININSTALL")) )
107cdf0e10cSrcweir     {
108cdf0e10cSrcweir         sBasisInstallPath = TEXT("Basis");
109cdf0e10cSrcweir         sUreInstallPath = TEXT("..\\URE");
110cdf0e10cSrcweir     }
111cdf0e10cSrcweir 
112cdf0e10cSrcweir     stripFinalBackslash(&sBasisInstallPath);
113cdf0e10cSrcweir     stripFinalBackslash(&sUreInstallPath);
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     // string myText1 = TEXT("Creating Basis-Link: ") + sBasisLinkPath;
116cdf0e10cSrcweir     // string myText2 = TEXT("Creating Ure-Link: ") + sUreLinkPath;
117cdf0e10cSrcweir     // MessageBox(NULL, myText1.c_str(), "DEBUG", MB_OK);
118cdf0e10cSrcweir     // MessageBox(NULL, myText2.c_str(), "DEBUG", MB_OK);
119cdf0e10cSrcweir 
120cdf0e10cSrcweir     // creating basis-link in brand layer
121cdf0e10cSrcweir 
122cdf0e10cSrcweir     HANDLE h1file = CreateFile(
123cdf0e10cSrcweir         sBasisLinkPath.c_str(),
124cdf0e10cSrcweir         GENERIC_WRITE,
125cdf0e10cSrcweir         0,
126cdf0e10cSrcweir         NULL,
127cdf0e10cSrcweir         CREATE_NEW,
128cdf0e10cSrcweir         FILE_ATTRIBUTE_NORMAL,
129cdf0e10cSrcweir         NULL);
130cdf0e10cSrcweir 
131cdf0e10cSrcweir     if (IsValidHandle(h1file))
132cdf0e10cSrcweir     {
133cdf0e10cSrcweir         DWORD dummy;
134cdf0e10cSrcweir 
135cdf0e10cSrcweir         // Converting string into UTF-8 encoding and writing into file "basis-link"
136cdf0e10cSrcweir 
137cdf0e10cSrcweir         int nCharsRequired = MultiByteToWideChar( CP_ACP, 0, sBasisInstallPath.c_str(), -1, NULL, 0 );
138cdf0e10cSrcweir         if ( nCharsRequired )
139cdf0e10cSrcweir         {
140cdf0e10cSrcweir             LPWSTR	lpPathW = new WCHAR[nCharsRequired];
141cdf0e10cSrcweir             if ( MultiByteToWideChar( CP_ACP, 0, sBasisInstallPath.c_str(), -1, lpPathW, nCharsRequired ) )
142cdf0e10cSrcweir             {
143cdf0e10cSrcweir                 nCharsRequired = WideCharToMultiByte( CP_UTF8, 0, lpPathW, -1, NULL, 0, NULL, NULL );
144cdf0e10cSrcweir                 if ( nCharsRequired )
145cdf0e10cSrcweir                 {
146cdf0e10cSrcweir                     LPSTR	lpPathUTF8 = new CHAR[nCharsRequired];
147cdf0e10cSrcweir                     WideCharToMultiByte( CP_UTF8, 0, lpPathW, -1, lpPathUTF8, nCharsRequired, NULL, NULL );
148cdf0e10cSrcweir 
149cdf0e10cSrcweir                     // WriteFile( h1file, sBasisInstallPath.c_str(), sBasisInstallPath.size() ,&dummy, 0 );
150cdf0e10cSrcweir                     WriteFile( h1file, lpPathUTF8, strlen(lpPathUTF8) ,&dummy, 0 );
151cdf0e10cSrcweir 
152cdf0e10cSrcweir                     delete lpPathUTF8;
153cdf0e10cSrcweir                 }
154cdf0e10cSrcweir             }
155cdf0e10cSrcweir 
156cdf0e10cSrcweir             delete lpPathW;
157cdf0e10cSrcweir         }
158cdf0e10cSrcweir 
159cdf0e10cSrcweir         CloseHandle(h1file);
160cdf0e10cSrcweir     }
161cdf0e10cSrcweir 
162cdf0e10cSrcweir     // creating ure-link in basis layer
163cdf0e10cSrcweir 
164cdf0e10cSrcweir     HANDLE h2file = CreateFile(
165cdf0e10cSrcweir         sUreLinkPath.c_str(),
166cdf0e10cSrcweir         GENERIC_WRITE,
167cdf0e10cSrcweir         0,
168cdf0e10cSrcweir         NULL,
169cdf0e10cSrcweir         CREATE_NEW,
170cdf0e10cSrcweir         FILE_ATTRIBUTE_NORMAL,
171cdf0e10cSrcweir         NULL);
172cdf0e10cSrcweir 
173cdf0e10cSrcweir     if (IsValidHandle(h2file))
174cdf0e10cSrcweir     {
175cdf0e10cSrcweir         DWORD dummy;
176cdf0e10cSrcweir 
177cdf0e10cSrcweir         // Converting string into UTF-8 encoding and writing into file "basis-link"
178cdf0e10cSrcweir 
179cdf0e10cSrcweir         int nCharsRequired = MultiByteToWideChar( CP_ACP, 0, sUreInstallPath.c_str(), -1, NULL, 0 );
180cdf0e10cSrcweir         if ( nCharsRequired )
181cdf0e10cSrcweir         {
182cdf0e10cSrcweir             LPWSTR	lpPathW = new WCHAR[nCharsRequired];
183cdf0e10cSrcweir             if ( MultiByteToWideChar( CP_ACP, 0, sUreInstallPath.c_str(), -1, lpPathW, nCharsRequired ) )
184cdf0e10cSrcweir             {
185cdf0e10cSrcweir                 nCharsRequired = WideCharToMultiByte( CP_UTF8, 0, lpPathW, -1, NULL, 0, NULL, NULL );
186cdf0e10cSrcweir                 if ( nCharsRequired )
187cdf0e10cSrcweir                 {
188cdf0e10cSrcweir                     LPSTR	lpPathUTF8 = new CHAR[nCharsRequired];
189cdf0e10cSrcweir                     WideCharToMultiByte( CP_UTF8, 0, lpPathW, -1, lpPathUTF8, nCharsRequired, NULL, NULL );
190cdf0e10cSrcweir 
191cdf0e10cSrcweir                     // WriteFile( h2file, sUreInstallPath.c_str(), sUreInstallPath.size() ,&dummy, 0 );
192cdf0e10cSrcweir                     WriteFile( h2file, lpPathUTF8, strlen(lpPathUTF8) ,&dummy, 0 );
193cdf0e10cSrcweir 
194cdf0e10cSrcweir                     delete lpPathUTF8;
195cdf0e10cSrcweir                 }
196cdf0e10cSrcweir             }
197cdf0e10cSrcweir 
198cdf0e10cSrcweir             delete lpPathW;
199cdf0e10cSrcweir         }
200cdf0e10cSrcweir 
201cdf0e10cSrcweir         CloseHandle(h2file);
202cdf0e10cSrcweir     }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     return ERROR_SUCCESS;
205cdf0e10cSrcweir }
206cdf0e10cSrcweir 
RemoveLayerLinks(MSIHANDLE handle)207cdf0e10cSrcweir extern "C" UINT __stdcall RemoveLayerLinks(MSIHANDLE handle)
208cdf0e10cSrcweir {
209cdf0e10cSrcweir     string sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
210cdf0e10cSrcweir 
211cdf0e10cSrcweir     string sOfficeInstallPath = sInstallPath;
212cdf0e10cSrcweir     string sBasisInstallPath = sInstallPath + TEXT("Basis\\");
213cdf0e10cSrcweir     string sUreInstallPath = sInstallPath + TEXT("URE\\");
214cdf0e10cSrcweir 
215cdf0e10cSrcweir     string sBasisLinkPath = sOfficeInstallPath + TEXT("basis-link");
216cdf0e10cSrcweir     string sUreLinkPath = sBasisInstallPath + TEXT("ure-link");
217cdf0e10cSrcweir     string sUreDirName = sUreInstallPath + TEXT("bin");
218cdf0e10cSrcweir 
219cdf0e10cSrcweir     // string myText2 = TEXT("Deleting Ure-Link: ") + sUreLinkPath;
220cdf0e10cSrcweir     // MessageBox(NULL, myText2.c_str(), "DEBUG", MB_OK);
221cdf0e10cSrcweir 
222cdf0e10cSrcweir     // Deleting link to basis layer
223cdf0e10cSrcweir     // string myText1 = TEXT("Deleting Basis-Link: ") + sBasisLinkPath;
224cdf0e10cSrcweir     // MessageBox(NULL, myText1.c_str(), "DEBUG", MB_OK);
225cdf0e10cSrcweir     DeleteFile(sBasisLinkPath.c_str());
226cdf0e10cSrcweir 
227cdf0e10cSrcweir     // Check, if URE is still installed
228cdf0e10cSrcweir     bool ureDirExists = true;
229cdf0e10cSrcweir     WIN32_FIND_DATA aFindData;
230cdf0e10cSrcweir     HANDLE hFindContent = FindFirstFile( sUreDirName.c_str(), &aFindData );
231cdf0e10cSrcweir     if ( hFindContent == INVALID_HANDLE_VALUE ) { ureDirExists = false; }
232cdf0e10cSrcweir     FindClose( hFindContent );
233cdf0e10cSrcweir 
234cdf0e10cSrcweir     // if ( ureDirExists )
235cdf0e10cSrcweir     // {
236cdf0e10cSrcweir     //     string myText3 = TEXT("URE directory still exists: ") + sUreDirName;
237cdf0e10cSrcweir     //     MessageBox(NULL, myText3.c_str(), "DEBUG", MB_OK);
238cdf0e10cSrcweir     //     string myText4 = TEXT("URE link NOT removed: ") + sUreLinkPath;
239cdf0e10cSrcweir     //     MessageBox(NULL, myText4.c_str(), "DEBUG", MB_OK);
240cdf0e10cSrcweir     // }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir     // Deleting link to URE layer, if URE dir no longer exists
243cdf0e10cSrcweir     if ( ! ureDirExists )
244cdf0e10cSrcweir     {
245cdf0e10cSrcweir     //     string myText5 = TEXT("URE directory does not exist: ") + sUreDirName;
246cdf0e10cSrcweir     //     MessageBox(NULL, myText5.c_str(), "DEBUG", MB_OK);
247cdf0e10cSrcweir     	DeleteFile(sUreLinkPath.c_str());
248cdf0e10cSrcweir     //     string myText6 = TEXT("URE link removed: ") + sUreLinkPath;
249cdf0e10cSrcweir     //     MessageBox(NULL, myText6.c_str(), "DEBUG", MB_OK);
250cdf0e10cSrcweir     }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir     return ERROR_SUCCESS;
253cdf0e10cSrcweir }
254