mirror of
https://github.com/reactos/reactos.git
synced 2025-05-07 10:46:58 +00:00
Christoph Brill <egore@gmx.de>
- Sync msiexec to Wine-20080105. See issue #2948 for more details. svn path=/trunk/; revision=31701
This commit is contained in:
parent
ba8ac4fd2f
commit
11cd25ed6f
7 changed files with 322 additions and 48 deletions
|
@ -16,9 +16,11 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <msi.h>
|
#include <msi.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
|
@ -32,6 +34,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msiexec);
|
||||||
typedef HRESULT (WINAPI *DLLREGISTERSERVER)(void);
|
typedef HRESULT (WINAPI *DLLREGISTERSERVER)(void);
|
||||||
typedef HRESULT (WINAPI *DLLUNREGISTERSERVER)(void);
|
typedef HRESULT (WINAPI *DLLUNREGISTERSERVER)(void);
|
||||||
|
|
||||||
|
DWORD DoService(void);
|
||||||
|
|
||||||
struct string_list
|
struct string_list
|
||||||
{
|
{
|
||||||
struct string_list *next;
|
struct string_list *next;
|
||||||
|
@ -205,7 +209,7 @@ static DWORD msi_atou(LPCWSTR str)
|
||||||
ret += (*str - '0');
|
ret += (*str - '0');
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LPWSTR msi_strdup(LPCWSTR str)
|
static LPWSTR msi_strdup(LPCWSTR str)
|
||||||
|
@ -224,32 +228,52 @@ static BOOL msi_strequal(LPCWSTR str1, LPCSTR str2)
|
||||||
|
|
||||||
len = MultiByteToWideChar( CP_ACP, 0, str2, -1, NULL, 0);
|
len = MultiByteToWideChar( CP_ACP, 0, str2, -1, NULL, 0);
|
||||||
if( !len )
|
if( !len )
|
||||||
return TRUE;
|
return FALSE;
|
||||||
if( lstrlenW(str1) != (len-1) )
|
if( lstrlenW(str1) != (len-1) )
|
||||||
return TRUE;
|
return FALSE;
|
||||||
strW = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
|
strW = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
|
||||||
MultiByteToWideChar( CP_ACP, 0, str2, -1, strW, len);
|
MultiByteToWideChar( CP_ACP, 0, str2, -1, strW, len);
|
||||||
ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, len, strW, len);
|
ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, len, strW, len);
|
||||||
HeapFree(GetProcessHeap(), 0, strW);
|
HeapFree(GetProcessHeap(), 0, strW);
|
||||||
return (ret != CSTR_EQUAL);
|
return (ret == CSTR_EQUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prefix is hyphen or dash, and str1 is the same as str2, ignoring case */
|
||||||
|
static BOOL msi_option_equal(LPCWSTR str1, LPCSTR str2)
|
||||||
|
{
|
||||||
|
if (str1[0] != '/' && str1[0] != '-')
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* skip over the hyphen or slash */
|
||||||
|
return msi_strequal(str1 + 1, str2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* str2 is at the beginning of str1, ignoring case */
|
/* str2 is at the beginning of str1, ignoring case */
|
||||||
static BOOL msi_strprefix(LPCWSTR str1, LPCSTR str2)
|
static BOOL msi_strprefix(LPCWSTR str1, LPCSTR str2)
|
||||||
{
|
{
|
||||||
int len, ret;
|
DWORD len, ret;
|
||||||
LPWSTR strW;
|
LPWSTR strW;
|
||||||
|
|
||||||
len = MultiByteToWideChar( CP_ACP, 0, str2, -1, NULL, 0);
|
len = MultiByteToWideChar( CP_ACP, 0, str2, -1, NULL, 0);
|
||||||
if( !len )
|
if( !len )
|
||||||
return TRUE;
|
return FALSE;
|
||||||
if( lstrlenW(str1) < (len-1) )
|
if( lstrlenW(str1) < (len-1) )
|
||||||
return TRUE;
|
return FALSE;
|
||||||
strW = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
|
strW = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
|
||||||
MultiByteToWideChar( CP_ACP, 0, str2, -1, strW, len);
|
MultiByteToWideChar( CP_ACP, 0, str2, -1, strW, len);
|
||||||
ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, len-1, strW, len-1);
|
ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, len-1, strW, len-1);
|
||||||
HeapFree(GetProcessHeap(), 0, strW);
|
HeapFree(GetProcessHeap(), 0, strW);
|
||||||
return (ret != CSTR_EQUAL);
|
return (ret == CSTR_EQUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prefix is hyphen or dash, and str2 is at the beginning of str1, ignoring case */
|
||||||
|
static BOOL msi_option_prefix(LPCWSTR str1, LPCSTR str2)
|
||||||
|
{
|
||||||
|
if (str1[0] != '/' && str1[0] != '-')
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* skip over the hyphen or slash */
|
||||||
|
return msi_strprefix(str1 + 1, str2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID *LoadProc(LPCWSTR DllName, LPCSTR ProcName, HMODULE* DllHandle)
|
static VOID *LoadProc(LPCWSTR DllName, LPCSTR ProcName, HMODULE* DllHandle)
|
||||||
|
@ -314,6 +338,43 @@ static DWORD DoDllUnregisterServer(LPCWSTR DllName)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD DoRegServer(void)
|
||||||
|
{
|
||||||
|
SC_HANDLE scm, service;
|
||||||
|
CHAR path[MAX_PATH+12];
|
||||||
|
DWORD ret = 0;
|
||||||
|
|
||||||
|
scm = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CREATE_SERVICE);
|
||||||
|
if (!scm)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to open the service control manager.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetSystemDirectory(path, MAX_PATH);
|
||||||
|
lstrcatA(path, "\\msiexec.exe /V");
|
||||||
|
|
||||||
|
service = CreateServiceA(scm, "MSIServer", "MSIServer", GENERIC_ALL,
|
||||||
|
SERVICE_WIN32_SHARE_PROCESS, SERVICE_DEMAND_START,
|
||||||
|
SERVICE_ERROR_NORMAL, path, NULL, NULL,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (service) CloseServiceHandle(service);
|
||||||
|
else if (GetLastError() != ERROR_SERVICE_EXISTS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create MSI service\n");
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
CloseServiceHandle(scm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INT DoEmbedding( LPWSTR key )
|
||||||
|
{
|
||||||
|
printf("Remote custom actions are not supported yet\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* state machine to break up the command line properly
|
* state machine to break up the command line properly
|
||||||
*/
|
*/
|
||||||
|
@ -426,6 +487,7 @@ static BOOL process_args_from_reg( LPWSTR ident, int *pargc, WCHAR ***pargv )
|
||||||
process_args(buf, pargc, pargv);
|
process_args(buf, pargc, pargv);
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, buf);
|
||||||
}
|
}
|
||||||
RegCloseKey(hkeyArgs);
|
RegCloseKey(hkeyArgs);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -443,6 +505,7 @@ int main(int argc, char **argv)
|
||||||
BOOL FunctionDllUnregisterServer = FALSE;
|
BOOL FunctionDllUnregisterServer = FALSE;
|
||||||
BOOL FunctionRegServer = FALSE;
|
BOOL FunctionRegServer = FALSE;
|
||||||
BOOL FunctionUnregServer = FALSE;
|
BOOL FunctionUnregServer = FALSE;
|
||||||
|
BOOL FunctionServer = FALSE;
|
||||||
BOOL FunctionUnknown = FALSE;
|
BOOL FunctionUnknown = FALSE;
|
||||||
|
|
||||||
LPWSTR PackageName = NULL;
|
LPWSTR PackageName = NULL;
|
||||||
|
@ -451,7 +514,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
DWORD RepairMode = 0;
|
DWORD RepairMode = 0;
|
||||||
|
|
||||||
DWORD AdvertiseMode = 0;
|
DWORD_PTR AdvertiseMode = 0;
|
||||||
struct string_list *transform_list = NULL;
|
struct string_list *transform_list = NULL;
|
||||||
LANGID Language = 0;
|
LANGID Language = 0;
|
||||||
|
|
||||||
|
@ -477,25 +540,28 @@ int main(int argc, char **argv)
|
||||||
* We do that before starting to process the real commandline,
|
* We do that before starting to process the real commandline,
|
||||||
* then overwrite the commandline again.
|
* then overwrite the commandline again.
|
||||||
*/
|
*/
|
||||||
if(!msi_strequal(argvW[1], "/@"))
|
if(argc>1 && msi_option_equal(argvW[1], "@"))
|
||||||
{
|
{
|
||||||
if(!process_args_from_reg( argvW[2], &argc, &argvW ))
|
if(!process_args_from_reg( argvW[2], &argc, &argvW ))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc == 3 && msi_option_equal(argvW[1], "Embedding"))
|
||||||
|
return DoEmbedding( argvW[2] );
|
||||||
|
|
||||||
for(i = 1; i < argc; i++)
|
for(i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
|
|
||||||
if (!msi_strequal(argvW[i], "/regserver"))
|
if (msi_option_equal(argvW[i], "regserver"))
|
||||||
{
|
{
|
||||||
FunctionRegServer = TRUE;
|
FunctionRegServer = TRUE;
|
||||||
}
|
}
|
||||||
else if (!msi_strequal(argvW[i], "/unregserver") || !msi_strequal(argvW[i], "/unregister"))
|
else if (msi_option_equal(argvW[i], "unregserver") || msi_option_equal(argvW[i], "unregister"))
|
||||||
{
|
{
|
||||||
FunctionUnregServer = TRUE;
|
FunctionUnregServer = TRUE;
|
||||||
}
|
}
|
||||||
else if(!msi_strprefix(argvW[i], "/i"))
|
else if(msi_option_prefix(argvW[i], "i"))
|
||||||
{
|
{
|
||||||
LPWSTR argvWi = argvW[i];
|
LPWSTR argvWi = argvW[i];
|
||||||
FunctionInstall = TRUE;
|
FunctionInstall = TRUE;
|
||||||
|
@ -511,7 +577,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
PackageName = argvWi;
|
PackageName = argvWi;
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/a"))
|
else if(msi_option_equal(argvW[i], "a"))
|
||||||
{
|
{
|
||||||
FunctionInstall = TRUE;
|
FunctionInstall = TRUE;
|
||||||
FunctionInstallAdmin = TRUE;
|
FunctionInstallAdmin = TRUE;
|
||||||
|
@ -523,7 +589,7 @@ int main(int argc, char **argv)
|
||||||
PackageName = argvW[i];
|
PackageName = argvW[i];
|
||||||
StringListAppend(&property_list, ActionAdmin);
|
StringListAppend(&property_list, ActionAdmin);
|
||||||
}
|
}
|
||||||
else if(!msi_strprefix(argvW[i], "/f"))
|
else if(msi_option_prefix(argvW[i], "f"))
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
int len = lstrlenW(argvW[i]);
|
int len = lstrlenW(argvW[i]);
|
||||||
|
@ -591,17 +657,21 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
PackageName = argvW[i];
|
PackageName = argvW[i];
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/x"))
|
else if(msi_option_prefix(argvW[i], "x"))
|
||||||
{
|
{
|
||||||
FunctionInstall = TRUE;
|
FunctionInstall = TRUE;
|
||||||
|
PackageName = argvW[i]+2;
|
||||||
|
if (!PackageName[0])
|
||||||
|
{
|
||||||
i++;
|
i++;
|
||||||
if(i >= argc)
|
if(i >= argc)
|
||||||
ShowUsage(1);
|
ShowUsage(1);
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
|
||||||
PackageName = argvW[i];
|
PackageName = argvW[i];
|
||||||
|
}
|
||||||
|
WINE_TRACE("PackageName = %s\n", wine_dbgstr_w(PackageName));
|
||||||
StringListAppend(&property_list, RemoveAll);
|
StringListAppend(&property_list, RemoveAll);
|
||||||
}
|
}
|
||||||
else if(!msi_strprefix(argvW[i], "/j"))
|
else if(msi_option_prefix(argvW[i], "j"))
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
int len = lstrlenW(argvW[i]);
|
int len = lstrlenW(argvW[i]);
|
||||||
|
@ -629,7 +699,7 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
PackageName = argvW[i];
|
PackageName = argvW[i];
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "u"))
|
else if(msi_strequal(argvW[i], "u"))
|
||||||
{
|
{
|
||||||
FunctionAdvertise = TRUE;
|
FunctionAdvertise = TRUE;
|
||||||
AdvertiseMode = ADVERTISEFLAGS_USERASSIGN;
|
AdvertiseMode = ADVERTISEFLAGS_USERASSIGN;
|
||||||
|
@ -639,7 +709,7 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
PackageName = argvW[i];
|
PackageName = argvW[i];
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "m"))
|
else if(msi_strequal(argvW[i], "m"))
|
||||||
{
|
{
|
||||||
FunctionAdvertise = TRUE;
|
FunctionAdvertise = TRUE;
|
||||||
AdvertiseMode = ADVERTISEFLAGS_MACHINEASSIGN;
|
AdvertiseMode = ADVERTISEFLAGS_MACHINEASSIGN;
|
||||||
|
@ -649,7 +719,7 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
PackageName = argvW[i];
|
PackageName = argvW[i];
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/t"))
|
else if(msi_option_equal(argvW[i], "t"))
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
if(i >= argc)
|
if(i >= argc)
|
||||||
|
@ -657,7 +727,7 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
StringListAppend(&transform_list, argvW[i]);
|
StringListAppend(&transform_list, argvW[i]);
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/g"))
|
else if(msi_option_equal(argvW[i], "g"))
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
if(i >= argc)
|
if(i >= argc)
|
||||||
|
@ -665,7 +735,7 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
Language = msi_atou(argvW[i]);
|
Language = msi_atou(argvW[i]);
|
||||||
}
|
}
|
||||||
else if(!msi_strprefix(argvW[i], "/l"))
|
else if(msi_option_prefix(argvW[i], "l"))
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
int len = lstrlenW(argvW[i]);
|
int len = lstrlenW(argvW[i]);
|
||||||
|
@ -756,7 +826,7 @@ int main(int argc, char **argv)
|
||||||
ExitProcess(1);
|
ExitProcess(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/p"))
|
else if(msi_option_equal(argvW[i], "p"))
|
||||||
{
|
{
|
||||||
FunctionPatch = TRUE;
|
FunctionPatch = TRUE;
|
||||||
i++;
|
i++;
|
||||||
|
@ -765,37 +835,38 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
PatchFileName = argvW[i];
|
PatchFileName = argvW[i];
|
||||||
}
|
}
|
||||||
else if(!msi_strprefix(argvW[i], "/q"))
|
else if(msi_option_prefix(argvW[i], "q"))
|
||||||
{
|
{
|
||||||
if(lstrlenW(argvW[i]) == 2 || !msi_strequal(argvW[i]+2, "n"))
|
if(lstrlenW(argvW[i]) == 2 || msi_strequal(argvW[i]+2, "n") ||
|
||||||
|
msi_strequal(argvW[i] + 2, "uiet"))
|
||||||
{
|
{
|
||||||
InstallUILevel = INSTALLUILEVEL_NONE;
|
InstallUILevel = INSTALLUILEVEL_NONE;
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i]+2, "b"))
|
else if(msi_strequal(argvW[i]+2, "b"))
|
||||||
{
|
{
|
||||||
InstallUILevel = INSTALLUILEVEL_BASIC;
|
InstallUILevel = INSTALLUILEVEL_BASIC;
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i]+2, "r"))
|
else if(msi_strequal(argvW[i]+2, "r"))
|
||||||
{
|
{
|
||||||
InstallUILevel = INSTALLUILEVEL_REDUCED;
|
InstallUILevel = INSTALLUILEVEL_REDUCED;
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i]+2, "f"))
|
else if(msi_strequal(argvW[i]+2, "f"))
|
||||||
{
|
{
|
||||||
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_FULL|INSTALLUILEVEL_ENDDIALOG);
|
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_FULL|INSTALLUILEVEL_ENDDIALOG);
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i]+2, "n+"))
|
else if(msi_strequal(argvW[i]+2, "n+"))
|
||||||
{
|
{
|
||||||
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_NONE|INSTALLUILEVEL_ENDDIALOG);
|
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_NONE|INSTALLUILEVEL_ENDDIALOG);
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i]+2, "b+"))
|
else if(msi_strequal(argvW[i]+2, "b+"))
|
||||||
{
|
{
|
||||||
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG);
|
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG);
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i]+2, "b-"))
|
else if(msi_strequal(argvW[i]+2, "b-"))
|
||||||
{
|
{
|
||||||
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_BASIC|INSTALLUILEVEL_PROGRESSONLY);
|
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_BASIC|INSTALLUILEVEL_PROGRESSONLY);
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i]+2, "b+!"))
|
else if(msi_strequal(argvW[i]+2, "b+!"))
|
||||||
{
|
{
|
||||||
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG);
|
InstallUILevel = (INSTALLUILEVEL) (INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG);
|
||||||
WINE_FIXME("Unknown modifier: !\n");
|
WINE_FIXME("Unknown modifier: !\n");
|
||||||
|
@ -806,7 +877,7 @@ int main(int argc, char **argv)
|
||||||
wine_dbgstr_w(argvW[i]+2));
|
wine_dbgstr_w(argvW[i]+2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/y"))
|
else if(msi_option_equal(argvW[i], "y"))
|
||||||
{
|
{
|
||||||
FunctionDllRegisterServer = TRUE;
|
FunctionDllRegisterServer = TRUE;
|
||||||
i++;
|
i++;
|
||||||
|
@ -815,7 +886,7 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
DllName = argvW[i];
|
DllName = argvW[i];
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/z"))
|
else if(msi_option_equal(argvW[i], "z"))
|
||||||
{
|
{
|
||||||
FunctionDllUnregisterServer = TRUE;
|
FunctionDllUnregisterServer = TRUE;
|
||||||
i++;
|
i++;
|
||||||
|
@ -824,29 +895,26 @@ int main(int argc, char **argv)
|
||||||
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
|
||||||
DllName = argvW[i];
|
DllName = argvW[i];
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/h") || !msi_strequal(argvW[i], "/?"))
|
else if(msi_option_equal(argvW[i], "h") || msi_option_equal(argvW[i], "?"))
|
||||||
{
|
{
|
||||||
ShowUsage(0);
|
ShowUsage(0);
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/m"))
|
else if(msi_option_equal(argvW[i], "m"))
|
||||||
{
|
{
|
||||||
FunctionUnknown = TRUE;
|
FunctionUnknown = TRUE;
|
||||||
WINE_FIXME("Unknown parameter /m\n");
|
WINE_FIXME("Unknown parameter /m\n");
|
||||||
}
|
}
|
||||||
else if(!msi_strequal(argvW[i], "/D"))
|
else if(msi_option_equal(argvW[i], "D"))
|
||||||
{
|
{
|
||||||
FunctionUnknown = TRUE;
|
FunctionUnknown = TRUE;
|
||||||
WINE_FIXME("Unknown parameter /D\n");
|
WINE_FIXME("Unknown parameter /D\n");
|
||||||
}
|
}
|
||||||
else if(strchrW(argvW[i], '='))
|
else if (msi_option_equal(argvW[i], "V"))
|
||||||
{
|
{
|
||||||
StringListAppend(&property_list, argvW[i]);
|
FunctionServer = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
StringListAppend(&property_list, argvW[i]);
|
||||||
FunctionInstall = TRUE;
|
|
||||||
PackageName = argvW[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start the GUI */
|
/* start the GUI */
|
||||||
|
@ -891,12 +959,16 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
else if (FunctionRegServer)
|
else if (FunctionRegServer)
|
||||||
{
|
{
|
||||||
WINE_FIXME( "/regserver not implemented yet, ignoring\n" );
|
ReturnCode = DoRegServer();
|
||||||
}
|
}
|
||||||
else if (FunctionUnregServer)
|
else if (FunctionUnregServer)
|
||||||
{
|
{
|
||||||
WINE_FIXME( "/unregserver not implemented yet, ignoring\n" );
|
WINE_FIXME( "/unregserver not implemented yet, ignoring\n" );
|
||||||
}
|
}
|
||||||
|
else if (FunctionServer)
|
||||||
|
{
|
||||||
|
ReturnCode = DoService();
|
||||||
|
}
|
||||||
else if (FunctionUnknown)
|
else if (FunctionUnknown)
|
||||||
{
|
{
|
||||||
WINE_FIXME( "Unknown function, ignoring\n" );
|
WINE_FIXME( "Unknown function, ignoring\n" );
|
||||||
|
|
BIN
reactos/base/system/msiexec/msiexec.ico
Normal file
BIN
reactos/base/system/msiexec/msiexec.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 766 B |
|
@ -15,5 +15,7 @@
|
||||||
<library>ole32</library>
|
<library>ole32</library>
|
||||||
<library>msi</library>
|
<library>msi</library>
|
||||||
<file>msiexec.c</file>
|
<file>msiexec.c</file>
|
||||||
|
<file>rsrc.rc</file>
|
||||||
|
<file>service.c</file>
|
||||||
<file>version.rc</file>
|
<file>version.rc</file>
|
||||||
</module>
|
</module>
|
||||||
|
|
26
reactos/base/system/msiexec/rsrc.rc
Normal file
26
reactos/base/system/msiexec/rsrc.rc
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Mike McCormack
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "version.rc"
|
||||||
|
|
||||||
|
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
|
||||||
|
/* @makedep: msiexec.ico */
|
||||||
|
1 ICON DISCARDABLE msiexec.ico
|
174
reactos/base/system/msiexec/service.c
Normal file
174
reactos/base/system/msiexec/service.c
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* msiexec.exe implementation
|
||||||
|
*
|
||||||
|
* Copyright 2007 Google (James Hawkins)
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(msiexec);
|
||||||
|
|
||||||
|
static SERVICE_STATUS_HANDLE hstatus;
|
||||||
|
|
||||||
|
static HANDLE thread;
|
||||||
|
static HANDLE kill_event;
|
||||||
|
|
||||||
|
void KillService(void)
|
||||||
|
{
|
||||||
|
WINE_TRACE("Killing service\n");
|
||||||
|
SetEvent(kill_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL UpdateSCMStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
|
||||||
|
DWORD dwServiceSpecificExitCode)
|
||||||
|
{
|
||||||
|
SERVICE_STATUS status;
|
||||||
|
|
||||||
|
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||||
|
status.dwCurrentState = dwCurrentState;
|
||||||
|
|
||||||
|
if (dwCurrentState == SERVICE_START_PENDING)
|
||||||
|
status.dwControlsAccepted = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
|
||||||
|
SERVICE_ACCEPT_PAUSE_CONTINUE |
|
||||||
|
SERVICE_ACCEPT_SHUTDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwServiceSpecificExitCode == 0)
|
||||||
|
{
|
||||||
|
status.dwWin32ExitCode = dwWin32ExitCode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
|
||||||
|
status.dwCheckPoint = 0;
|
||||||
|
status.dwWaitHint = 0;
|
||||||
|
|
||||||
|
if (!SetServiceStatus(hstatus, &status))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to set service status\n");
|
||||||
|
KillService();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI ServiceCtrlHandler(DWORD code)
|
||||||
|
{
|
||||||
|
WINE_TRACE("%d\n", code);
|
||||||
|
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTROL_SHUTDOWN:
|
||||||
|
case SERVICE_CONTROL_STOP:
|
||||||
|
UpdateSCMStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
|
||||||
|
KillService();
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unhandled service control code: %d\n", code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI ServiceExecutionThread(LPVOID param)
|
||||||
|
{
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL StartServiceThread(void)
|
||||||
|
{
|
||||||
|
DWORD id;
|
||||||
|
|
||||||
|
thread = CreateThread(0, 0, ServiceExecutionThread, 0, 0, &id);
|
||||||
|
if (!thread)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create thread\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI ServiceMain(DWORD argc, LPSTR *argv)
|
||||||
|
{
|
||||||
|
hstatus = RegisterServiceCtrlHandlerA("MSIServer", ServiceCtrlHandler);
|
||||||
|
if (!hstatus)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to register service ctrl handler\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSCMStatus(SERVICE_START_PENDING, NO_ERROR, 0);
|
||||||
|
|
||||||
|
kill_event = CreateEvent(0, TRUE, FALSE, 0);
|
||||||
|
if (!kill_event)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create event\n");
|
||||||
|
KillService();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StartServiceThread())
|
||||||
|
{
|
||||||
|
KillService();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSCMStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||||
|
|
||||||
|
WaitForSingleObject(kill_event, INFINITE);
|
||||||
|
KillService();
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD DoService(void)
|
||||||
|
{
|
||||||
|
char service_name[] = "MSIServer";
|
||||||
|
|
||||||
|
const SERVICE_TABLE_ENTRY service[] =
|
||||||
|
{
|
||||||
|
{service_name, ServiceMain},
|
||||||
|
{NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
WINE_TRACE("Starting MSIServer service\n");
|
||||||
|
|
||||||
|
if (!StartServiceCtrlDispatcher(service))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to start MSIServer service\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WINE_FILEDESCRIPTION_STR "Wine Installer"
|
#define WINE_FILEDESCRIPTION_STR "Wine Installer"
|
||||||
|
|
|
@ -103,7 +103,7 @@ ReactOS shares the following programs with Winehq.
|
||||||
reactos/base/applications/games/winemine # Out of sync
|
reactos/base/applications/games/winemine # Out of sync
|
||||||
reactos/base/applications/regedit # Out of sync
|
reactos/base/applications/regedit # Out of sync
|
||||||
reactos/base/system/expand # Out of sync
|
reactos/base/system/expand # Out of sync
|
||||||
reactos/base/system/msiexec # Synced to Wine-0_9_3
|
reactos/base/system/msiexec # Synced to Wine-20080105
|
||||||
|
|
||||||
In addition the following libs, dlls and source files are mostly based on code ported
|
In addition the following libs, dlls and source files are mostly based on code ported
|
||||||
from Winehq CVS. If you are looking to update something in these files
|
from Winehq CVS. If you are looking to update something in these files
|
||||||
|
|
Loading…
Reference in a new issue