[4/4] services: Move process related fields into a separate struct.

Sebastian Lackner sebastian at fds-team.de
Wed Mar 2 23:28:16 CST 2016


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---

The next step will be to allocate the process struct only when a process is running,
and to maintain an scmdatabase specific list of active processes.

 programs/services/rpc.c      |   28 ++++++------
 programs/services/services.c |  100 +++++++++++++++++++++++++++----------------
 programs/services/services.h |   20 ++++++--
 3 files changed, 92 insertions(+), 56 deletions(-)

diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index ece8dce..933f18d 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -773,8 +773,8 @@ DWORD __cdecl svcctl_SetServiceStatus(
 
     if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
         run_after_timeout(service_terminate, service->service_entry, service_kill_timeout);
-    else if (service->service_entry->status_changed_event)
-        SetEvent(service->service_entry->status_changed_event);
+    else if (service->service_entry->process->status_changed_event)
+        SetEvent(service->service_entry->process->status_changed_event);
 
     return ERROR_SUCCESS;
 }
@@ -984,26 +984,26 @@ static BOOL service_accepts_control(const struct service_entry *service, DWORD d
 }
 
 /******************************************************************************
- * service_send_command
+ * process_send_command
  */
-BOOL service_send_command( struct service_entry *service, const void *data, DWORD size, DWORD *result )
+BOOL process_send_command(struct process_entry *process, const void *data, DWORD size, DWORD *result)
 {
     OVERLAPPED overlapped;
     DWORD count, ret;
     BOOL r;
 
-    overlapped.hEvent = service->overlapped_event;
-    r = WriteFile(service->control_pipe, data, size, &count, &overlapped);
+    overlapped.hEvent = process->overlapped_event;
+    r = WriteFile(process->control_pipe, data, size, &count, &overlapped);
     if (!r && GetLastError() == ERROR_IO_PENDING)
     {
-        ret = WaitForSingleObject( service->overlapped_event, service_pipe_timeout );
+        ret = WaitForSingleObject(process->overlapped_event, service_pipe_timeout);
         if (ret == WAIT_TIMEOUT)
         {
             WINE_ERR("sending command timed out\n");
             *result = ERROR_SERVICE_REQUEST_TIMEOUT;
             return FALSE;
         }
-        r = GetOverlappedResult(service->control_pipe, &overlapped, &count, FALSE);
+        r = GetOverlappedResult(process->control_pipe, &overlapped, &count, FALSE);
     }
     if (!r || count != size)
     {
@@ -1011,17 +1011,17 @@ BOOL service_send_command( struct service_entry *service, const void *data, DWOR
         *result  = (!r ? GetLastError() : ERROR_WRITE_FAULT);
         return FALSE;
     }
-    r = ReadFile(service->control_pipe, result, sizeof *result, &count, &overlapped);
+    r = ReadFile(process->control_pipe, result, sizeof *result, &count, &overlapped);
     if (!r && GetLastError() == ERROR_IO_PENDING)
     {
-        ret = WaitForSingleObject( service->overlapped_event, service_pipe_timeout );
+        ret = WaitForSingleObject(process->overlapped_event, service_pipe_timeout);
         if (ret == WAIT_TIMEOUT)
         {
             WINE_ERR("receiving command result timed out\n");
             *result = ERROR_SERVICE_REQUEST_TIMEOUT;
             return FALSE;
         }
-        r = GetOverlappedResult(service->control_pipe, &overlapped, &count, FALSE);
+        r = GetOverlappedResult(process->control_pipe, &overlapped, &count, FALSE);
     }
     if (!r || count != sizeof *result)
     {
@@ -1054,7 +1054,7 @@ static BOOL service_send_control(struct service_entry *service, DWORD dwControl,
     ssi->name_size = strlenW(service->name) + 1;
     strcpyW( ssi->data, service->name );
 
-    r = service_send_command( service, ssi, ssi->total_size, result );
+    r = process_send_command(service->process, ssi, ssi->total_size, result);
     HeapFree( GetProcessHeap(), 0, ssi );
     return r;
 }
@@ -1170,7 +1170,7 @@ DWORD __cdecl svcctl_ControlService(
     if (dwControl == SERVICE_CONTROL_STOP)
         service->service_entry->force_shutdown = TRUE;
 
-    control_mutex = service->service_entry->control_mutex;
+    control_mutex = service->service_entry->process->control_mutex;
     service_unlock(service->service_entry);
 
     ret = WaitForSingleObject(control_mutex, 30000);
@@ -1926,7 +1926,7 @@ DWORD events_loop(void)
                 WINE_TRACE("Exceeded maximum wait object count\n");
                 break;
             }
-            wait_handles[num_handles] = iter->service_entry->process;
+            wait_handles[num_handles] = iter->service_entry->process->process;
             num_handles++;
         }
         LeaveCriticalSection(&timeout_queue_cs);
diff --git a/programs/services/services.c b/programs/services/services.c
index 02a46f9..c49dad3 100644
--- a/programs/services/services.c
+++ b/programs/services/services.c
@@ -68,8 +68,30 @@ static const WCHAR SZ_DESCRIPTION[]       = {'D','e','s','c','r','i','p','t','i'
 static const WCHAR SZ_PRESHUTDOWN[]       = {'P','r','e','s','h','u','t','d','o','w','n','T','i','m','e','o','u','t',0};
 static const WCHAR SZ_WOW64[]             = {'W','O','W','6','4',0};
 
+static DWORD process_create(struct process_entry **entry)
+{
+    *entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**entry));
+    if (!*entry)
+        return ERROR_NOT_ENOUGH_SERVER_MEMORY;
+    (*entry)->control_pipe = INVALID_HANDLE_VALUE;
+    /* all other fields are zero */
+    return ERROR_SUCCESS;
+}
+
+static void free_process_entry(struct process_entry *entry)
+{
+    CloseHandle(entry->process);
+    CloseHandle(entry->control_mutex);
+    CloseHandle(entry->control_pipe);
+    CloseHandle(entry->overlapped_event);
+    CloseHandle(entry->status_changed_event);
+    HeapFree(GetProcessHeap(), 0, entry);
+}
+
 DWORD service_create(LPCWSTR name, struct service_entry **entry)
 {
+    DWORD err;
+
     *entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**entry));
     if (!*entry)
         return ERROR_NOT_ENOUGH_SERVER_MEMORY;
@@ -79,7 +101,12 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry)
         HeapFree(GetProcessHeap(), 0, *entry);
         return ERROR_NOT_ENOUGH_SERVER_MEMORY;
     }
-    (*entry)->control_pipe = INVALID_HANDLE_VALUE;
+    if ((err = process_create(&(*entry)->process)) != ERROR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(), 0, (*entry)->process);
+        HeapFree(GetProcessHeap(), 0, *entry);
+        return err;
+    }
     (*entry)->status.dwCurrentState = SERVICE_STOPPED;
     (*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
     (*entry)->preshutdown_timeout = default_preshutdown_timeout;
@@ -98,11 +125,7 @@ void free_service_entry(struct service_entry *entry)
     HeapFree(GetProcessHeap(), 0, entry->description);
     HeapFree(GetProcessHeap(), 0, entry->dependOnServices);
     HeapFree(GetProcessHeap(), 0, entry->dependOnGroups);
-    CloseHandle(entry->process);
-    CloseHandle(entry->control_mutex);
-    CloseHandle(entry->control_pipe);
-    CloseHandle(entry->overlapped_event);
-    CloseHandle(entry->status_changed_event);
+    free_process_entry(entry->process);
     HeapFree(GetProcessHeap(), 0, entry);
 }
 
@@ -332,13 +355,14 @@ static void scmdatabase_wait_terminate(struct scmdatabase *db)
         run = FALSE;
         LIST_FOR_EACH_ENTRY(service, &db->services, struct service_entry, entry)
         {
-            if(service->process)
+            struct process_entry *process = service->process;
+            if (process->process)
             {
                 scmdatabase_unlock(db);
-                WaitForSingleObject(service->process, INFINITE);
+                WaitForSingleObject(process->process, INFINITE);
                 scmdatabase_lock(db);
-                CloseHandle(service->process);
-                service->process = NULL;
+                CloseHandle(process->process);
+                process->process = NULL;
                 run = TRUE;
                 break;
             }
@@ -729,7 +753,7 @@ static DWORD service_start_process(struct service_entry *service_entry, HANDLE *
     }
 
     service_entry->status.dwProcessId = pi.dwProcessId;
-    service_entry->process = pi.hProcess;
+    service_entry->process->process = pi.hProcess;
     *process = pi.hProcess;
     CloseHandle( pi.hThread );
 
@@ -738,7 +762,7 @@ static DWORD service_start_process(struct service_entry *service_entry, HANDLE *
 
 static DWORD service_wait_for_startup(struct service_entry *service_entry, HANDLE process_handle)
 {
-    HANDLE handles[2] = { service_entry->status_changed_event, process_handle };
+    HANDLE handles[2] = { service_entry->process->status_changed_event, process_handle };
     DWORD state, ret;
 
     WINE_TRACE("%p\n", service_entry);
@@ -769,6 +793,7 @@ static DWORD service_wait_for_startup(struct service_entry *service_entry, HANDL
 static BOOL service_send_start_message(struct service_entry *service, HANDLE process_handle,
                                        LPCWSTR *argv, DWORD argc)
 {
+    struct process_entry *process = service->process;
     OVERLAPPED overlapped;
     DWORD i, len, result;
     service_start_info *ssi;
@@ -777,16 +802,16 @@ static BOOL service_send_start_message(struct service_entry *service, HANDLE pro
 
     WINE_TRACE("%s %p %d\n", wine_dbgstr_w(service->name), argv, argc);
 
-    overlapped.hEvent = service->overlapped_event;
-    if (!ConnectNamedPipe(service->control_pipe, &overlapped))
+    overlapped.hEvent = process->overlapped_event;
+    if (!ConnectNamedPipe(process->control_pipe, &overlapped))
     {
         if (GetLastError() == ERROR_IO_PENDING)
         {
             HANDLE handles[2];
-            handles[0] = service->overlapped_event;
+            handles[0] = process->overlapped_event;
             handles[1] = process_handle;
             if (WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout ) != WAIT_OBJECT_0)
-                CancelIo( service->control_pipe );
+                CancelIo(process->control_pipe);
             if (!HasOverlappedIoCompleted( &overlapped ))
             {
                 WINE_ERR( "service %s failed to start\n", wine_dbgstr_w( service->name ));
@@ -822,7 +847,7 @@ static BOOL service_send_start_message(struct service_entry *service, HANDLE pro
     }
     *p=0;
 
-    r = service_send_command( service, ssi, ssi->total_size, &result );
+    r = process_send_command( process, ssi, ssi->total_size, &result );
     if (r && result)
     {
         SetLastError(result);
@@ -836,6 +861,7 @@ static BOOL service_send_start_message(struct service_entry *service, HANDLE pro
 
 DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *service_argv)
 {
+    struct process_entry *process = service->process;
     DWORD err;
     LPWSTR name;
     HANDLE process_handle = NULL;
@@ -844,26 +870,26 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
     if (err != ERROR_SUCCESS)
         return err;
 
-    if (WaitForSingleObject(service->process, 0) == WAIT_TIMEOUT)
+    if (WaitForSingleObject(process->process, 0) == WAIT_TIMEOUT)
     {
         scmdatabase_unlock_startup(service->db);
         return ERROR_SERVICE_ALREADY_RUNNING;
     }
 
-    CloseHandle(service->control_pipe);
-    service->control_mutex = CreateMutexW(NULL, TRUE, NULL);
+    CloseHandle(process->control_pipe);
+    process->control_mutex = CreateMutexW(NULL, TRUE, NULL);
     service->force_shutdown = FALSE;
 
-    if (!service->status_changed_event)
-        service->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-    if (!service->overlapped_event)
-        service->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if (!process->status_changed_event)
+        process->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (!process->overlapped_event)
+        process->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
 
     name = service_get_pipe_name();
-    service->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+    process->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
                   PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL );
     HeapFree(GetProcessHeap(), 0, name);
-    if (service->control_pipe==INVALID_HANDLE_VALUE)
+    if (process->control_pipe == INVALID_HANDLE_VALUE)
     {
         WINE_ERR("failed to create pipe for %s, error = %d\n",
             wine_dbgstr_w(service->name), GetLastError());
@@ -883,7 +909,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
     }
 
     if (err == ERROR_SUCCESS)
-        ReleaseMutex(service->control_mutex);
+        ReleaseMutex(process->control_mutex);
     else
         service_terminate(service);
     scmdatabase_unlock_startup(service->db);
@@ -895,16 +921,18 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
 
 void service_terminate(struct service_entry *service)
 {
+    struct process_entry *process = service->process;
+
     service_lock(service);
-    TerminateProcess(service->process, 0);
-    CloseHandle(service->process);
-    service->process = NULL;
-    CloseHandle(service->status_changed_event);
-    service->status_changed_event = NULL;
-    CloseHandle(service->control_mutex);
-    service->control_mutex = NULL;
-    CloseHandle(service->control_pipe);
-    service->control_pipe = INVALID_HANDLE_VALUE;
+    TerminateProcess(process->process, 0);
+    CloseHandle(process->process);
+    process->process = NULL;
+    CloseHandle(process->status_changed_event);
+    process->status_changed_event = NULL;
+    CloseHandle(process->control_mutex);
+    process->control_mutex = NULL;
+    CloseHandle(process->control_pipe);
+    process->control_pipe = INVALID_HANDLE_VALUE;
 
     service->status.dwProcessId = 0;
     service->status.dwCurrentState = SERVICE_STOPPED;
diff --git a/programs/services/services.h b/programs/services/services.h
index 7f43b22..206d655 100644
--- a/programs/services/services.h
+++ b/programs/services/services.h
@@ -31,6 +31,15 @@ struct scmdatabase
     CRITICAL_SECTION cs;
 };
 
+struct process_entry
+{
+    HANDLE process;
+    HANDLE control_mutex;
+    HANDLE control_pipe;
+    HANDLE overlapped_event;
+    HANDLE status_changed_event;
+};
+
 struct service_entry
 {
     struct list entry;
@@ -43,11 +52,7 @@ struct service_entry
     LPWSTR description;
     LPWSTR dependOnServices;
     LPWSTR dependOnGroups;
-    HANDLE process;
-    HANDLE control_mutex;
-    HANDLE control_pipe;
-    HANDLE overlapped_event;
-    HANDLE status_changed_event;
+    struct process_entry *process;
     BOOL force_shutdown;
     BOOL marked_for_delete;
     BOOL is_wow64;
@@ -79,7 +84,10 @@ void service_lock(struct service_entry *service);
 void service_unlock(struct service_entry *service);
 DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *service_argv);
 void service_terminate(struct service_entry *service);
-BOOL service_send_command( struct service_entry *service, const void *data, DWORD size, DWORD *result );
+
+/* Process functions */
+
+BOOL process_send_command(struct process_entry *process, const void *data, DWORD size, DWORD *result);
 
 extern HANDLE g_hStartedEvent;
 
-- 
2.7.1



More information about the wine-patches mailing list