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:
Aleksey Bragin 2008-01-10 13:33:25 +00:00
parent ba8ac4fd2f
commit 11cd25ed6f
7 changed files with 322 additions and 48 deletions

View file

@ -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" );

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View file

@ -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>

View 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

View 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;
}

View file

@ -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"

View file

@ -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