msiexec: Implement a stub MSIServer service [try2]

James Hawkins truiken at gmail.com
Mon Jul 30 13:53:16 CDT 2007


Hi,

Fixed the calling convention mismatches.

Changelog:
* Implement a stub MSIServer service.

 programs/msiexec/Makefile.in |    3 -
 programs/msiexec/msiexec.c   |   13 +++
 programs/msiexec/service.c   |  174 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 188 insertions(+), 2 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/programs/msiexec/Makefile.in b/programs/msiexec/Makefile.in
index c2bd981..0d09c4c 100644
--- a/programs/msiexec/Makefile.in
+++ b/programs/msiexec/Makefile.in
@@ -7,7 +7,8 @@ APPMODE   = -mconsole
 IMPORTS   = msi ole32 advapi32 user32 kernel32
 
 C_SRCS = \
-	msiexec.c
+	msiexec.c \
+	service.c
 
 RC_SRCS = rsrc.rc
 RC_BINSRC = rsrc.rc
diff --git a/programs/msiexec/msiexec.c b/programs/msiexec/msiexec.c
index e4ff579..71e81c8 100644
--- a/programs/msiexec/msiexec.c
+++ b/programs/msiexec/msiexec.c
@@ -34,6 +34,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msiexec);
 typedef HRESULT (WINAPI *DLLREGISTERSERVER)(void);
 typedef HRESULT (WINAPI *DLLUNREGISTERSERVER)(void);
 
+DWORD DoService(void);
+
 struct string_list
 {
 	struct string_list *next;
@@ -350,7 +352,7 @@ static DWORD DoRegServer(void)
     }
 
     GetSystemDirectory(path, MAX_PATH);
-    lstrcatA(path, "\\msiexec.exe");
+    lstrcatA(path, "\\msiexec.exe /V");
 
     service = CreateServiceA(scm, "MSIServer", "MSIServer", GENERIC_ALL,
                              SERVICE_WIN32_SHARE_PROCESS, SERVICE_DEMAND_START,
@@ -502,6 +504,7 @@ int main(int argc, char **argv)
 	BOOL FunctionDllUnregisterServer = FALSE;
 	BOOL FunctionRegServer = FALSE;
 	BOOL FunctionUnregServer = FALSE;
+	BOOL FunctionServer = FALSE;
 	BOOL FunctionUnknown = FALSE;
 
 	LPWSTR PackageName = NULL;
@@ -905,6 +908,10 @@ int main(int argc, char **argv)
 			FunctionUnknown = TRUE;
 			WINE_FIXME("Unknown parameter /D\n");
 		}
+		else if (msi_option_equal(argvW[i], "V"))
+		{
+		    FunctionServer = TRUE;
+		}
 		else
 			StringListAppend(&property_list, argvW[i]);
 	}
@@ -957,6 +964,10 @@ int main(int argc, char **argv)
 	{
 		WINE_FIXME( "/unregserver not implemented yet, ignoring\n" );
 	}
+	else if (FunctionServer)
+	{
+	    ReturnCode = DoService();
+	}
 	else if (FunctionUnknown)
 	{
 		WINE_FIXME( "Unknown function, ignoring\n" );
diff --git a/programs/msiexec/service.c b/programs/msiexec/service.c
new file mode 100644
index 0000000..64618b8
--- /dev/null
+++ b/programs/msiexec/service.c
@@ -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;
+}
-- 
1.4.1


More information about the wine-patches mailing list