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 #include "sal/config.h" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include <cstddef> 27cdf0e10cSrcweir #include <new> 28cdf0e10cSrcweir #include <string.h> // <cstring> not supported by old MSC versions 29cdf0e10cSrcweir 30cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN 31cdf0e10cSrcweir #if defined _MSC_VER 32cdf0e10cSrcweir #pragma warning(push, 1) 33cdf0e10cSrcweir #endif 34cdf0e10cSrcweir #include <windows.h> 35cdf0e10cSrcweir #include <msiquery.h> 36cdf0e10cSrcweir #include <shellapi.h> 37cdf0e10cSrcweir #if defined _MSC_VER 38cdf0e10cSrcweir #pragma warning(pop) 39cdf0e10cSrcweir #endif 40cdf0e10cSrcweir 41cdf0e10cSrcweir #include "boost/scoped_array.hpp" 42cdf0e10cSrcweir 43cdf0e10cSrcweir #define LCL_LENGTH0(s) (sizeof (s) / sizeof *(s)) 44cdf0e10cSrcweir #define LCL_STRING0(s) (s), LCL_LENGTH0(s) 45cdf0e10cSrcweir 46cdf0e10cSrcweir namespace { 47cdf0e10cSrcweir 48cdf0e10cSrcweir enum Status { STATUS_NO, STATUS_YES, STATUS_ERROR }; 49cdf0e10cSrcweir 50cdf0e10cSrcweir Status fileExists(wchar_t const * path) { 51cdf0e10cSrcweir return GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES 52cdf0e10cSrcweir ? GetLastError() == ERROR_FILE_NOT_FOUND ? STATUS_NO : STATUS_ERROR 53cdf0e10cSrcweir : STATUS_YES; 54cdf0e10cSrcweir } 55cdf0e10cSrcweir 56cdf0e10cSrcweir wchar_t * getProperty( 57cdf0e10cSrcweir MSIHANDLE install, wchar_t const * name, wchar_t const * suffix, 58cdf0e10cSrcweir std::size_t suffixLength, wchar_t ** end = NULL) 59cdf0e10cSrcweir { 60cdf0e10cSrcweir DWORD n = 0; 61cdf0e10cSrcweir UINT err = MsiGetPropertyW(install, name, L"", &n); 62cdf0e10cSrcweir if (err != ERROR_SUCCESS && err != ERROR_MORE_DATA) { 63cdf0e10cSrcweir return NULL; 64cdf0e10cSrcweir } 65cdf0e10cSrcweir DWORD n2 = n + suffixLength; //TODO: overflow 66cdf0e10cSrcweir wchar_t * data = new(std::nothrow) wchar_t[n2]; 67cdf0e10cSrcweir if (data == NULL) { 68cdf0e10cSrcweir return NULL; 69cdf0e10cSrcweir } 70cdf0e10cSrcweir if (MsiGetPropertyW(install, name, data, &n2) != ERROR_SUCCESS || n2 != n) { 71cdf0e10cSrcweir delete[] data; 72cdf0e10cSrcweir return NULL; 73cdf0e10cSrcweir } 74cdf0e10cSrcweir memcpy(data + n, suffix, suffixLength * sizeof (wchar_t)); //TODO: overflow 75cdf0e10cSrcweir if (end != NULL) { 76cdf0e10cSrcweir *end = data + n + suffixLength; 77cdf0e10cSrcweir } 78cdf0e10cSrcweir return data; 79cdf0e10cSrcweir } 80cdf0e10cSrcweir 81cdf0e10cSrcweir } 82cdf0e10cSrcweir 83cdf0e10cSrcweir extern "C" UINT __stdcall copyEditionData(MSIHANDLE install) { 84cdf0e10cSrcweir boost::scoped_array<wchar_t> from( 85cdf0e10cSrcweir getProperty(install, L"SourceDir", LCL_STRING0(L"edition\0"))); 86cdf0e10cSrcweir if (!from) { 87cdf0e10cSrcweir return ERROR_INSTALL_FAILURE; 88cdf0e10cSrcweir } 89cdf0e10cSrcweir Status stat = fileExists(from.get()); 90cdf0e10cSrcweir if (stat == STATUS_ERROR) { 91cdf0e10cSrcweir return ERROR_INSTALL_FAILURE; 92cdf0e10cSrcweir } 93cdf0e10cSrcweir if (stat == STATUS_NO) { 94cdf0e10cSrcweir return ERROR_SUCCESS; 95cdf0e10cSrcweir } 96cdf0e10cSrcweir wchar_t * end; 97cdf0e10cSrcweir boost::scoped_array<wchar_t> to( 98cdf0e10cSrcweir getProperty( 99cdf0e10cSrcweir install, L"INSTALLLOCATION", 100cdf0e10cSrcweir LCL_STRING0(L"program\\edition\0"), &end)); 101cdf0e10cSrcweir if (!to) { 102cdf0e10cSrcweir return ERROR_INSTALL_FAILURE; 103cdf0e10cSrcweir } 104cdf0e10cSrcweir stat = fileExists(to.get()); 105cdf0e10cSrcweir if (stat == STATUS_ERROR) { 106cdf0e10cSrcweir return ERROR_INSTALL_FAILURE; 107cdf0e10cSrcweir } 108cdf0e10cSrcweir if (stat == STATUS_YES) { 109cdf0e10cSrcweir SHFILEOPSTRUCTW opDelete = { 110cdf0e10cSrcweir NULL, FO_DELETE, to.get(), NULL, FOF_NOCONFIRMATION | FOF_SILENT, 111cdf0e10cSrcweir FALSE, NULL, NULL }; //TODO: non-NULL hwnd 112cdf0e10cSrcweir if (SHFileOperationW(&opDelete) != 0) { 113cdf0e10cSrcweir return ERROR_INSTALL_FAILURE; 114cdf0e10cSrcweir } 115cdf0e10cSrcweir } 116cdf0e10cSrcweir *(end - LCL_LENGTH0(L"\\edition\0")) = L'\0'; 117cdf0e10cSrcweir *(end - LCL_LENGTH0(L"\\edition\0") + 1) = L'\0'; 118cdf0e10cSrcweir SHFILEOPSTRUCTW opCopy = { 119cdf0e10cSrcweir NULL, FO_COPY, from.get(), to.get(), 120cdf0e10cSrcweir FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_SILENT, FALSE, NULL, 121cdf0e10cSrcweir NULL }; //TODO: non-NULL hwnd 122cdf0e10cSrcweir if (SHFileOperationW(&opCopy) != 0) { 123cdf0e10cSrcweir return ERROR_INSTALL_FAILURE; 124cdf0e10cSrcweir } 125cdf0e10cSrcweir return ERROR_SUCCESS; 126cdf0e10cSrcweir } 127