services: Move process related fields into a separate struct.
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
00b1184f10
commit
7fc3f72de7
@ -773,8 +773,8 @@ DWORD __cdecl svcctl_SetServiceStatus(
|
|||||||
|
|
||||||
if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
|
if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
|
||||||
run_after_timeout(service_terminate, service->service_entry, service_kill_timeout);
|
run_after_timeout(service_terminate, service->service_entry, service_kill_timeout);
|
||||||
else if (service->service_entry->status_changed_event)
|
else if (service->service_entry->process->status_changed_event)
|
||||||
SetEvent(service->service_entry->status_changed_event);
|
SetEvent(service->service_entry->process->status_changed_event);
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
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;
|
OVERLAPPED overlapped;
|
||||||
DWORD count, ret;
|
DWORD count, ret;
|
||||||
BOOL r;
|
BOOL r;
|
||||||
|
|
||||||
overlapped.hEvent = service->overlapped_event;
|
overlapped.hEvent = process->overlapped_event;
|
||||||
r = WriteFile(service->control_pipe, data, size, &count, &overlapped);
|
r = WriteFile(process->control_pipe, data, size, &count, &overlapped);
|
||||||
if (!r && GetLastError() == ERROR_IO_PENDING)
|
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)
|
if (ret == WAIT_TIMEOUT)
|
||||||
{
|
{
|
||||||
WINE_ERR("sending command timed out\n");
|
WINE_ERR("sending command timed out\n");
|
||||||
*result = ERROR_SERVICE_REQUEST_TIMEOUT;
|
*result = ERROR_SERVICE_REQUEST_TIMEOUT;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
r = GetOverlappedResult(service->control_pipe, &overlapped, &count, FALSE);
|
r = GetOverlappedResult(process->control_pipe, &overlapped, &count, FALSE);
|
||||||
}
|
}
|
||||||
if (!r || count != size)
|
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);
|
*result = (!r ? GetLastError() : ERROR_WRITE_FAULT);
|
||||||
return FALSE;
|
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)
|
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)
|
if (ret == WAIT_TIMEOUT)
|
||||||
{
|
{
|
||||||
WINE_ERR("receiving command result timed out\n");
|
WINE_ERR("receiving command result timed out\n");
|
||||||
*result = ERROR_SERVICE_REQUEST_TIMEOUT;
|
*result = ERROR_SERVICE_REQUEST_TIMEOUT;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
r = GetOverlappedResult(service->control_pipe, &overlapped, &count, FALSE);
|
r = GetOverlappedResult(process->control_pipe, &overlapped, &count, FALSE);
|
||||||
}
|
}
|
||||||
if (!r || count != sizeof *result)
|
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;
|
ssi->name_size = strlenW(service->name) + 1;
|
||||||
strcpyW( ssi->data, service->name );
|
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 );
|
HeapFree( GetProcessHeap(), 0, ssi );
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1170,7 +1170,7 @@ DWORD __cdecl svcctl_ControlService(
|
|||||||
if (dwControl == SERVICE_CONTROL_STOP)
|
if (dwControl == SERVICE_CONTROL_STOP)
|
||||||
service->service_entry->force_shutdown = TRUE;
|
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);
|
service_unlock(service->service_entry);
|
||||||
|
|
||||||
ret = WaitForSingleObject(control_mutex, 30000);
|
ret = WaitForSingleObject(control_mutex, 30000);
|
||||||
@ -1926,7 +1926,7 @@ DWORD events_loop(void)
|
|||||||
WINE_TRACE("Exceeded maximum wait object count\n");
|
WINE_TRACE("Exceeded maximum wait object count\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wait_handles[num_handles] = iter->service_entry->process;
|
wait_handles[num_handles] = iter->service_entry->process->process;
|
||||||
num_handles++;
|
num_handles++;
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&timeout_queue_cs);
|
LeaveCriticalSection(&timeout_queue_cs);
|
||||||
|
@ -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_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 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 service_create(LPCWSTR name, struct service_entry **entry)
|
||||||
{
|
{
|
||||||
|
DWORD err;
|
||||||
|
|
||||||
*entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**entry));
|
*entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**entry));
|
||||||
if (!*entry)
|
if (!*entry)
|
||||||
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
|
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
|
||||||
@ -79,7 +101,12 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry)
|
|||||||
HeapFree(GetProcessHeap(), 0, *entry);
|
HeapFree(GetProcessHeap(), 0, *entry);
|
||||||
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
|
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.dwCurrentState = SERVICE_STOPPED;
|
||||||
(*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
|
(*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
|
||||||
(*entry)->preshutdown_timeout = default_preshutdown_timeout;
|
(*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->description);
|
||||||
HeapFree(GetProcessHeap(), 0, entry->dependOnServices);
|
HeapFree(GetProcessHeap(), 0, entry->dependOnServices);
|
||||||
HeapFree(GetProcessHeap(), 0, entry->dependOnGroups);
|
HeapFree(GetProcessHeap(), 0, entry->dependOnGroups);
|
||||||
CloseHandle(entry->process);
|
free_process_entry(entry->process);
|
||||||
CloseHandle(entry->control_mutex);
|
|
||||||
CloseHandle(entry->control_pipe);
|
|
||||||
CloseHandle(entry->overlapped_event);
|
|
||||||
CloseHandle(entry->status_changed_event);
|
|
||||||
HeapFree(GetProcessHeap(), 0, entry);
|
HeapFree(GetProcessHeap(), 0, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,13 +355,14 @@ static void scmdatabase_wait_terminate(struct scmdatabase *db)
|
|||||||
run = FALSE;
|
run = FALSE;
|
||||||
LIST_FOR_EACH_ENTRY(service, &db->services, struct service_entry, entry)
|
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);
|
scmdatabase_unlock(db);
|
||||||
WaitForSingleObject(service->process, INFINITE);
|
WaitForSingleObject(process->process, INFINITE);
|
||||||
scmdatabase_lock(db);
|
scmdatabase_lock(db);
|
||||||
CloseHandle(service->process);
|
CloseHandle(process->process);
|
||||||
service->process = NULL;
|
process->process = NULL;
|
||||||
run = TRUE;
|
run = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -729,7 +753,7 @@ static DWORD service_start_process(struct service_entry *service_entry, HANDLE *
|
|||||||
}
|
}
|
||||||
|
|
||||||
service_entry->status.dwProcessId = pi.dwProcessId;
|
service_entry->status.dwProcessId = pi.dwProcessId;
|
||||||
service_entry->process = pi.hProcess;
|
service_entry->process->process = pi.hProcess;
|
||||||
*process = pi.hProcess;
|
*process = pi.hProcess;
|
||||||
CloseHandle( pi.hThread );
|
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)
|
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;
|
DWORD state, ret;
|
||||||
|
|
||||||
WINE_TRACE("%p\n", service_entry);
|
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,
|
static BOOL service_send_start_message(struct service_entry *service, HANDLE process_handle,
|
||||||
LPCWSTR *argv, DWORD argc)
|
LPCWSTR *argv, DWORD argc)
|
||||||
{
|
{
|
||||||
|
struct process_entry *process = service->process;
|
||||||
OVERLAPPED overlapped;
|
OVERLAPPED overlapped;
|
||||||
DWORD i, len, result;
|
DWORD i, len, result;
|
||||||
service_start_info *ssi;
|
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);
|
WINE_TRACE("%s %p %d\n", wine_dbgstr_w(service->name), argv, argc);
|
||||||
|
|
||||||
overlapped.hEvent = service->overlapped_event;
|
overlapped.hEvent = process->overlapped_event;
|
||||||
if (!ConnectNamedPipe(service->control_pipe, &overlapped))
|
if (!ConnectNamedPipe(process->control_pipe, &overlapped))
|
||||||
{
|
{
|
||||||
if (GetLastError() == ERROR_IO_PENDING)
|
if (GetLastError() == ERROR_IO_PENDING)
|
||||||
{
|
{
|
||||||
HANDLE handles[2];
|
HANDLE handles[2];
|
||||||
handles[0] = service->overlapped_event;
|
handles[0] = process->overlapped_event;
|
||||||
handles[1] = process_handle;
|
handles[1] = process_handle;
|
||||||
if (WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout ) != WAIT_OBJECT_0)
|
if (WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout ) != WAIT_OBJECT_0)
|
||||||
CancelIo( service->control_pipe );
|
CancelIo(process->control_pipe);
|
||||||
if (!HasOverlappedIoCompleted( &overlapped ))
|
if (!HasOverlappedIoCompleted( &overlapped ))
|
||||||
{
|
{
|
||||||
WINE_ERR( "service %s failed to start\n", wine_dbgstr_w( service->name ));
|
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;
|
*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)
|
if (r && result)
|
||||||
{
|
{
|
||||||
SetLastError(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)
|
DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *service_argv)
|
||||||
{
|
{
|
||||||
|
struct process_entry *process = service->process;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
LPWSTR name;
|
LPWSTR name;
|
||||||
HANDLE process_handle = NULL;
|
HANDLE process_handle = NULL;
|
||||||
@ -844,26 +870,26 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
|
|||||||
if (err != ERROR_SUCCESS)
|
if (err != ERROR_SUCCESS)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (WaitForSingleObject(service->process, 0) == WAIT_TIMEOUT)
|
if (WaitForSingleObject(process->process, 0) == WAIT_TIMEOUT)
|
||||||
{
|
{
|
||||||
scmdatabase_unlock_startup(service->db);
|
scmdatabase_unlock_startup(service->db);
|
||||||
return ERROR_SERVICE_ALREADY_RUNNING;
|
return ERROR_SERVICE_ALREADY_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(service->control_pipe);
|
CloseHandle(process->control_pipe);
|
||||||
service->control_mutex = CreateMutexW(NULL, TRUE, NULL);
|
process->control_mutex = CreateMutexW(NULL, TRUE, NULL);
|
||||||
service->force_shutdown = FALSE;
|
service->force_shutdown = FALSE;
|
||||||
|
|
||||||
if (!service->status_changed_event)
|
if (!process->status_changed_event)
|
||||||
service->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
process->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
if (!service->overlapped_event)
|
if (!process->overlapped_event)
|
||||||
service->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
process->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
name = service_get_pipe_name();
|
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 );
|
PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL );
|
||||||
HeapFree(GetProcessHeap(), 0, name);
|
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_ERR("failed to create pipe for %s, error = %d\n",
|
||||||
wine_dbgstr_w(service->name), GetLastError());
|
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)
|
if (err == ERROR_SUCCESS)
|
||||||
ReleaseMutex(service->control_mutex);
|
ReleaseMutex(process->control_mutex);
|
||||||
else
|
else
|
||||||
service_terminate(service);
|
service_terminate(service);
|
||||||
scmdatabase_unlock_startup(service->db);
|
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)
|
void service_terminate(struct service_entry *service)
|
||||||
{
|
{
|
||||||
|
struct process_entry *process = service->process;
|
||||||
|
|
||||||
service_lock(service);
|
service_lock(service);
|
||||||
TerminateProcess(service->process, 0);
|
TerminateProcess(process->process, 0);
|
||||||
CloseHandle(service->process);
|
CloseHandle(process->process);
|
||||||
service->process = NULL;
|
process->process = NULL;
|
||||||
CloseHandle(service->status_changed_event);
|
CloseHandle(process->status_changed_event);
|
||||||
service->status_changed_event = NULL;
|
process->status_changed_event = NULL;
|
||||||
CloseHandle(service->control_mutex);
|
CloseHandle(process->control_mutex);
|
||||||
service->control_mutex = NULL;
|
process->control_mutex = NULL;
|
||||||
CloseHandle(service->control_pipe);
|
CloseHandle(process->control_pipe);
|
||||||
service->control_pipe = INVALID_HANDLE_VALUE;
|
process->control_pipe = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
service->status.dwProcessId = 0;
|
service->status.dwProcessId = 0;
|
||||||
service->status.dwCurrentState = SERVICE_STOPPED;
|
service->status.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
@ -31,6 +31,15 @@ struct scmdatabase
|
|||||||
CRITICAL_SECTION cs;
|
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 service_entry
|
||||||
{
|
{
|
||||||
struct list entry;
|
struct list entry;
|
||||||
@ -43,11 +52,7 @@ struct service_entry
|
|||||||
LPWSTR description;
|
LPWSTR description;
|
||||||
LPWSTR dependOnServices;
|
LPWSTR dependOnServices;
|
||||||
LPWSTR dependOnGroups;
|
LPWSTR dependOnGroups;
|
||||||
HANDLE process;
|
struct process_entry *process;
|
||||||
HANDLE control_mutex;
|
|
||||||
HANDLE control_pipe;
|
|
||||||
HANDLE overlapped_event;
|
|
||||||
HANDLE status_changed_event;
|
|
||||||
BOOL force_shutdown;
|
BOOL force_shutdown;
|
||||||
BOOL marked_for_delete;
|
BOOL marked_for_delete;
|
||||||
BOOL is_wow64;
|
BOOL is_wow64;
|
||||||
@ -79,7 +84,10 @@ void service_lock(struct service_entry *service);
|
|||||||
void service_unlock(struct service_entry *service);
|
void service_unlock(struct service_entry *service);
|
||||||
DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *service_argv);
|
DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *service_argv);
|
||||||
void service_terminate(struct service_entry *service);
|
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;
|
extern HANDLE g_hStartedEvent;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user