ReactOS  0.4.13-dev-66-gc714b7f
service.c File Reference
#include <apitest.h>
#include <windef.h>
#include <winbase.h>
#include <wingdi.h>
#include <winreg.h>
#include <winsvc.h>
#include <winspool.h>
#include <winsplp.h>
#include <tlhelp32.h>
#include "localspl_apitest.h"
#include <debug.h>
Include dependency graph for service.c:

Go to the source code of this file.

Macros

#define WIN32_NO_STATUS
 

Functions

static void _DoDLLInjection ()
 
static DWORD WINAPI _ServiceControlHandlerEx (DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
 
static void WINAPI _ServiceMain (DWORD dwArgc, LPWSTR *lpszArgv)
 
 START_TEST (service)
 

Macro Definition Documentation

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 10 of file service.c.

Function Documentation

◆ _DoDLLInjection()

static void _DoDLLInjection ( )
static

Definition at line 27 of file service.c.

28 {
29  DWORD cbDLLPath;
31  HANDLE hSnapshot;
33  PROCESSENTRY32W pe;
34  PVOID pLoadLibraryAddress;
35  PVOID pLoadLibraryArgument;
36  PWSTR p;
37  WCHAR wszFilePath[MAX_PATH];
38 
39  // Get the full path to our EXE file.
40  if (!GetModuleFileNameW(NULL, wszFilePath, _countof(wszFilePath)))
41  {
42  DPRINT("GetModuleFileNameW failed with error %lu!\n", GetLastError());
43  return;
44  }
45 
46  // Replace the extension.
47  p = wcsrchr(wszFilePath, L'.');
48  if (!p)
49  {
50  DPRINT("File path has no file extension: %S\n", wszFilePath);
51  return;
52  }
53 
54  wcscpy(p, L".dll");
55  cbDLLPath = (wcslen(wszFilePath) + 1) * sizeof(WCHAR);
56 
57  // Create a snapshot of the currently running processes.
59  if (hSnapshot == INVALID_HANDLE_VALUE)
60  {
61  DPRINT("CreateToolhelp32Snapshot failed with error %lu!\n", GetLastError());
62  return;
63  }
64 
65  // Enumerate through all running processes.
66  pe.dwSize = sizeof(pe);
67  if (!Process32FirstW(hSnapshot, &pe))
68  {
69  DPRINT("Process32FirstW failed with error %lu!\n", GetLastError());
70  return;
71  }
72 
73  do
74  {
75  // Check if this is the spooler server process.
76  if (wcsicmp(pe.szExeFile, L"spoolsv.exe") != 0)
77  continue;
78 
79  // Open a handle to the process.
81  if (!hProcess)
82  {
83  DPRINT("OpenProcess failed with error %lu!\n", GetLastError());
84  return;
85  }
86 
87  // Get the address of LoadLibraryW.
88  pLoadLibraryAddress = (PVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW");
89  if (!pLoadLibraryAddress)
90  {
91  DPRINT("GetProcAddress failed with error %lu!\n", GetLastError());
92  return;
93  }
94 
95  // Allocate memory for the DLL path in the spooler process.
96  pLoadLibraryArgument = VirtualAllocEx(hProcess, NULL, cbDLLPath, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
97  if (!pLoadLibraryArgument)
98  {
99  DPRINT("VirtualAllocEx failed with error %lu!\n", GetLastError());
100  return;
101  }
102 
103  // Write the DLL path to the process memory.
104  if (!WriteProcessMemory(hProcess, pLoadLibraryArgument, wszFilePath, cbDLLPath, NULL))
105  {
106  DPRINT("WriteProcessMemory failed with error %lu!\n", GetLastError());
107  return;
108  }
109 
110  // Create a new thread in the spooler process that calls LoadLibraryW as the start routine with our DLL as the argument.
111  // This effectively injects our DLL into the spooler process and we can inspect localspl.dll there just like the spooler.
112  hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibraryAddress, pLoadLibraryArgument, 0, NULL);
113  if (!hThread)
114  {
115  DPRINT("CreateRemoteThread failed with error %lu!\n", GetLastError());
116  return;
117  }
118 
120  break;
121  }
122  while (Process32NextW(hSnapshot, &pe));
123 }
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:607
DWORD(WINAPI * LPTHREAD_START_ROUTINE)(LPVOID)
Definition: winbase.h:707
#define CloseHandle
Definition: compat.h:398
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
uint16_t * PWSTR
Definition: typedefs.h:54
#define _countof(array)
Definition: fontsub.cpp:30
WCHAR szExeFile[MAX_PATH]
Definition: tlhelp32.h:58
LPVOID NTAPI VirtualAllocEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:23
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
#define MEM_COMMIT
Definition: nt_native.h:1313
DWORD th32ProcessID
Definition: tlhelp32.h:51
#define MEM_RESERVE
Definition: nt_native.h:1314
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
BOOL WINAPI Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
Definition: toolhelp.c:984
void * PVOID
Definition: retypes.h:9
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1250
BOOL WINAPI Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
Definition: toolhelp.c:1073
#define wcsicmp
Definition: string.h:1152
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1257
#define TH32CS_SNAPPROCESS
Definition: tlhelp32.h:26
HANDLE hThread
Definition: wizard.c:27
HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)
Definition: toolhelp.c:1255
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:845
#define GetProcAddress(x, y)
Definition: compat.h:410
GLfloat GLfloat p
Definition: glext.h:8902
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOL NTAPI WriteProcessMemory(IN HANDLE hProcess, IN LPVOID lpBaseAddress, IN LPCVOID lpBuffer, IN SIZE_T nSize, OUT SIZE_T *lpNumberOfBytesWritten)
Definition: proc.c:2086
#define PAGE_READWRITE
Definition: nt_native.h:1304
HANDLE WINAPI CreateRemoteThread(IN HANDLE hProcess, IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:134

Referenced by _ServiceMain().

◆ _ServiceControlHandlerEx()

static DWORD WINAPI _ServiceControlHandlerEx ( DWORD  dwControl,
DWORD  dwEventType,
LPVOID  lpEventData,
LPVOID  lpContext 
)
static

Definition at line 126 of file service.c.

127 {
128  return NO_ERROR;
129 }
#define NO_ERROR
Definition: dderror.h:5

Referenced by _ServiceMain().

◆ _ServiceMain()

static void WINAPI _ServiceMain ( DWORD  dwArgc,
LPWSTR lpszArgv 
)
static

Definition at line 132 of file service.c.

133 {
136 
137  UNREFERENCED_PARAMETER(dwArgc);
138  UNREFERENCED_PARAMETER(lpszArgv);
139 
140  // Register our service for control.
142 
143  // Report SERVICE_RUNNING status.
147  ServiceStatus.dwWaitHint = 4000;
151 
152  // Do our funky crazy stuff.
153  _DoDLLInjection();
154 
155  // Our work is done.
158 }
DWORD dwCurrentState
Definition: winsvc.h:100
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
static SERVICE_STATUS ServiceStatus
Definition: dcomlaunch.c:27
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
static void _DoDLLInjection()
Definition: service.c:27
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
#define NO_ERROR
Definition: dderror.h:5
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:986
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_RUNNING
Definition: winsvc.h:24
smooth NULL
Definition: ftsmooth.c:416
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:960
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwServiceType
Definition: winsvc.h:99
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext)
Definition: sctrl.c:802
SERVICE_STATUS_HANDLE hServiceStatus
Definition: main.c:10
DWORD dwControlsAccepted
Definition: winsvc.h:101
#define SERVICE_NAME
Definition: wlansvc.c:18
static DWORD WINAPI _ServiceControlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
Definition: service.c:126
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR

Referenced by START_TEST().

◆ START_TEST()

START_TEST ( service  )

Definition at line 160 of file service.c.

161 {
162  int argc;
163  char** argv;
164 
166  {
168  { NULL, NULL }
169  };
170 
171  // This is no real test, but an easy way to integrate the service handler routines into the API-Test executable.
172  // Therefore, bail out if someone tries to run "service" as a usual test.
174  if (argc != 3)
175  return;
176 
177  // If we have exactly 3 arguments, we're run as a service, so initialize the corresponding service handler functions.
179 
180  // Prevent the testing framework from outputting a "0 tests executed" line here.
181  ExitProcess(0);
182 }
static int argc
Definition: ServiceArgs.c:12
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1517
#define argv
Definition: mplay32.c:18
BOOL WINAPI StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
Definition: sctrl.c:1123
static void WINAPI _ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
Definition: service.c:132
smooth NULL
Definition: ftsmooth.c:416
int winetest_get_mainargs(char ***pargv)
static SERVICE_TABLE_ENTRYW ServiceTable[2]
Definition: eventlog.c:24
#define SERVICE_NAME
Definition: wlansvc.c:18