ReactOS  0.4.13-dev-455-g28ed234
umpnpmgr.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2005 ReactOS Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * COPYRIGHT: See COPYING in the top level directory
21  * PROJECT: ReactOS kernel
22  * FILE: base/services/umpnpmgr/umpnpmgr.c
23  * PURPOSE: User-mode Plug and Play manager
24  * PROGRAMMER: Eric Kohl (eric.kohl@reactos.org)
25  * Hervé Poussineau (hpoussin@reactos.org)
26  * Colin Finck (colin@reactos.org)
27  */
28 
29 /* INCLUDES *****************************************************************/
30 
31 #include "precomp.h"
32 
33 #define NDEBUG
34 #include <debug.h>
35 
36 
37 /* GLOBALS ******************************************************************/
38 
39 static WCHAR ServiceName[] = L"PlugPlay";
40 
43 
46 
47 
48 /* FUNCTIONS *****************************************************************/
49 
50 static DWORD WINAPI
52 {
53  PLUGPLAY_CONTROL_USER_RESPONSE_DATA ResponseData = {0, 0, 0, 0};
54  DWORD dwRet = ERROR_SUCCESS;
56  RPC_STATUS RpcStatus;
57  PPLUGPLAY_EVENT_BLOCK PnpEvent, NewPnpEvent;
58  ULONG PnpEventSize;
59 
61 
62  PnpEventSize = 0x1000;
63  PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
64  if (PnpEvent == NULL)
65  return ERROR_OUTOFMEMORY;
66 
67  for (;;)
68  {
69  DPRINT("Calling NtGetPlugPlayEvent()\n");
70 
71  /* Wait for the next PnP event */
72  Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
73 
74  /* Resize the buffer for the PnP event if it's too small */
76  {
77  PnpEventSize += 0x400;
78  NewPnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
79  if (NewPnpEvent == NULL)
80  {
81  dwRet = ERROR_OUTOFMEMORY;
82  break;
83  }
84  PnpEvent = NewPnpEvent;
85  continue;
86  }
87 
88  if (!NT_SUCCESS(Status))
89  {
90  DPRINT1("NtGetPlugPlayEvent() failed (Status 0x%08lx)\n", Status);
91  break;
92  }
93 
94  /* Process the PnP event */
95  DPRINT("Received PnP Event\n");
96  if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
97  {
98  DeviceInstallParams* Params;
99  DWORD len;
100  DWORD DeviceIdLength;
101 
102  DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
103 
104  DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
105  if (DeviceIdLength)
106  {
107  /* Queue device install (will be dequeued by DeviceInstallThread) */
108  len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
109  Params = HeapAlloc(GetProcessHeap(), 0, len);
110  if (Params)
111  {
112  wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
115  }
116  }
117  }
118  else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
119  {
120 // DWORD dwRecipient;
121 
122  DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
123 
124 // dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
125 // BroadcastSystemMessageW(BSF_POSTMESSAGE,
126 // &dwRecipient,
127 // WM_DEVICECHANGE,
128 // DBT_DEVNODES_CHANGED,
129 // 0);
131  }
132  else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
133  {
134  DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
135  }
136  else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
137  {
138  DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
139  }
140  else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
141  {
142 // DWORD dwRecipient;
143 
144  DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
145 
146 // dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
147 // BroadcastSystemMessageW(BSF_POSTMESSAGE,
148 // &dwRecipient,
149 // WM_DEVICECHANGE,
150 // DBT_DEVNODES_CHANGED,
151 // 0);
153  }
154  else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
155  {
156 // DWORD dwRecipient;
157 
158  DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
159 
160 // dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
161 // BroadcastSystemMessageW(BSF_POSTMESSAGE,
162 // &dwRecipient,
163 // WM_DEVICECHANGE,
164 // DBT_DEVNODES_CHANGED,
165 // 0);
167  }
168  else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
169  {
170  DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
171  }
172  else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
173  {
174  DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
175  }
176  else
177  {
178  DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
179  PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
180  PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
181  PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
182  PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
183  }
184 
185  /* Dequeue the current PnP event and signal the next one */
187  &ResponseData,
188  sizeof(ResponseData));
189  if (!NT_SUCCESS(Status))
190  {
191  DPRINT1("NtPlugPlayControl(PlugPlayControlUserResponse) failed (Status 0x%08lx)\n", Status);
192  break;
193  }
194  }
195 
196  HeapFree(GetProcessHeap(), 0, PnpEvent);
197 
198  return dwRet;
199 }
200 
201 
202 static VOID
204 {
206  ServiceStatus.dwCurrentState = dwState;
211 
212  if (dwState == SERVICE_START_PENDING ||
213  dwState == SERVICE_STOP_PENDING ||
214  dwState == SERVICE_PAUSE_PENDING ||
215  dwState == SERVICE_CONTINUE_PENDING)
216  ServiceStatus.dwWaitHint = 10000;
217  else
219 
221  &ServiceStatus);
222 }
223 
224 
225 static DWORD WINAPI
227  DWORD dwEventType,
228  LPVOID lpEventData,
229  LPVOID lpContext)
230 {
231  DPRINT1("ServiceControlHandler() called\n");
232 
233  switch (dwControl)
234  {
236  DPRINT1(" SERVICE_CONTROL_STOP received\n");
237  /* Stop listening to RPC Messages */
240  return ERROR_SUCCESS;
241 
243  DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
245  return ERROR_SUCCESS;
246 
248  DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
250  return ERROR_SUCCESS;
251 
253  DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
255  &ServiceStatus);
256  return ERROR_SUCCESS;
257 
259  DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
260  /* Stop listening to RPC Messages */
263  return ERROR_SUCCESS;
264 
265  default :
266  DPRINT1(" Control %lu received\n", dwControl);
268  }
269 }
270 
271 
272 VOID WINAPI
274 {
275  HANDLE hThread;
277 
280 
281  DPRINT("ServiceMain() called\n");
282 
285  NULL);
286  if (!ServiceStatusHandle)
287  {
288  DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
289  return;
290  }
291 
293 
295  0,
297  NULL,
298  0,
299  &dwThreadId);
300  if (hThread != NULL)
302 
304  0,
306  NULL,
307  0,
308  &dwThreadId);
309  if (hThread != NULL)
311 
313  0,
315  NULL,
316  0,
317  &dwThreadId);
318  if (hThread != NULL)
320 
322 
323  DPRINT("ServiceMain() done\n");
324 }
325 
326 static DWORD
328 {
329  BOOLEAN OldValue;
330  DWORD dwError;
331 
332  DPRINT("UMPNPMGR: InitializePnPManager() started\n");
333 
334  /* We need this privilege for using CreateProcessAsUserW */
336 
338  if (hInstallEvent == NULL)
339  {
340  dwError = GetLastError();
341  DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
342  return dwError;
343  }
344 
347  {
348  dwError = GetLastError();
349  DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
350  return dwError;
351  }
352 
354  TRUE,
355  FALSE,
356  L"Global\\PnP_No_Pending_Install_Events");
357  if (hNoPendingInstalls == NULL)
358  {
359  dwError = GetLastError();
360  DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
361  return dwError;
362  }
363 
365 
367  L"System\\CurrentControlSet\\Enum",
368  0,
370  &hEnumKey);
371  if (dwError != ERROR_SUCCESS)
372  {
373  DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
374  return dwError;
375  }
376 
378  L"System\\CurrentControlSet\\Control\\Class",
379  0,
381  &hClassKey);
382  if (dwError != ERROR_SUCCESS)
383  {
384  DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
385  return dwError;
386  }
387 
388  DPRINT("UMPNPMGR: InitializePnPManager() done\n");
389 
390  return 0;
391 }
392 
393 BOOL WINAPI
395  DWORD fdwReason,
397 {
398  switch (fdwReason)
399  {
400  case DLL_PROCESS_ATTACH:
401  DisableThreadLibraryCalls(hinstDLL);
403  break;
404 
405  case DLL_PROCESS_DETACH:
406  break;
407  }
408 
409  return TRUE;
410 }
411 
412 /* EOF */
static int argc
Definition: ServiceArgs.c:12
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Definition: umpnpmgr.c:394
#define TRUE
Definition: types.h:120
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
Definition: umpnpmgr.c:273
#define CloseHandle
Definition: compat.h:398
RPC_STATUS WINAPI RpcMgmtStopServerListening(RPC_BINDING_HANDLE Binding)
Definition: rpc_server.c:1599
static SERVICE_STATUS ServiceStatus
Definition: umpnpmgr.c:42
#define ERROR_SUCCESS
Definition: deptool.c:10
DWORD dwCurrentState
Definition: winsvc.h:100
#define DBT_DEVNODES_CHANGED
Definition: dbt.h:28
#define SERVICE_PAUSE_PENDING
Definition: winsvc.h:26
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define SERVICE_PAUSED
Definition: winsvc.h:27
HANDLE hInstallEvent
Definition: install.c:40
LONG NTSTATUS
Definition: precomp.h:26
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
NTSYSAPI NTSTATUS NTAPI RtlAdjustPrivilege(_In_ ULONG Privilege, _In_ BOOLEAN NewValue, _In_ BOOLEAN ForThread, _Out_ PBOOLEAN OldValue)
#define SERVICE_START_PENDING
Definition: winsvc.h:22
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
static VOID UpdateServiceStatus(DWORD dwState)
Definition: umpnpmgr.c:203
#define DLL_PROCESS_ATTACH
Definition: compat.h:120
int WINAPI UuidEqual(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status)
Definition: rpcrt4_main.c:253
SLIST_HEADER DeviceInstallListHead
Definition: install.c:43
#define argv
Definition: mplay32.c:18
#define lstrlenW
Definition: compat.h:407
CHAR * LPTSTR
Definition: xmlstorage.h:192
static IN DWORD IN LPVOID lpvReserved
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:597
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:986
long RPC_STATUS
Definition: rpc.h:52
DWORD dwCheckPoint
Definition: winsvc.h:104
#define SERVICE_STOPPED
Definition: winsvc.h:21
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSTATUS NTAPI NtGetPlugPlayEvent(IN ULONG Reserved1, IN ULONG Reserved2, OUT PPLUGPLAY_EVENT_BLOCK Buffer, IN ULONG BufferSize)
Definition: plugplay.c:1169
#define SERVICE_RUNNING
Definition: winsvc.h:24
static SERVICE_STATUS_HANDLE ServiceStatusHandle
Definition: umpnpmgr.c:41
static DWORD WINAPI PnpEventThread(LPVOID lpParameter)
Definition: umpnpmgr.c:51
HKEY hEnumKey
Definition: umpnpmgr.c:44
unsigned char BOOLEAN
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:111
static BOOL SetupIsActive(VOID)
Definition: setup.c:27
smooth NULL
Definition: ftsmooth.c:416
WCHAR DeviceIds[1]
Definition: precomp.h:39
void DPRINT(...)
Definition: polytest.cpp:61
#define SERVICE_CONTROL_INTERROGATE
Definition: winsvc.h:39
static DWORD InitializePnPManager(VOID)
Definition: umpnpmgr.c:327
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:960
HANDLE hNoPendingInstalls
Definition: install.c:41
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3353
#define DLL_PROCESS_DETACH
Definition: compat.h:119
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
DWORD dwWaitHint
Definition: winsvc.h:105
#define WINAPI
Definition: msvc.h:8
DWORD dwWin32ExitCode
Definition: winsvc.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD dwServiceType
Definition: winsvc.h:99
#define SERVICE_CONTROL_PAUSE
Definition: winsvc.h:37
DWORD dwThreadId
Definition: fdebug.c:31
_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
static DWORD WINAPI ServiceControlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
Definition: umpnpmgr.c:226
LPVOID lpParameter
Definition: kernel32.h:234
GLenum GLsizei len
Definition: glext.h:6722
SLIST_ENTRY ListEntry
Definition: precomp.h:38
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext)
Definition: sctrl.c:802
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
HANDLE hDeviceInstallListNotEmpty
Definition: install.c:44
Status
Definition: gdiplustypes.h:24
DWORD dwControlsAccepted
Definition: winsvc.h:101
NTSTATUS NTAPI NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, IN OUT PVOID Buffer, IN ULONG BufferLength)
Definition: plugplay.c:1299
#define SERVICE_CONTINUE_PENDING
Definition: winsvc.h:25
DWORD WINAPI RpcServerThread(LPVOID lpParameter)
Definition: rpcserver.c:45
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define SERVICE_CONTROL_CONTINUE
Definition: winsvc.h:38
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define HeapReAlloc
Definition: compat.h:393
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
HANDLE hThread
Definition: wizard.c:27
#define WM_DEVICECHANGE
Definition: winuser.h:1787
#define DPRINT1
Definition: precomp.h:8
struct _PLUGPLAY_EVENT_BLOCK::@2273::@2276 TargetDevice
#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
Definition: security.c:657
unsigned int ULONG
Definition: retypes.h:1
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
static WCHAR ServiceName[]
Definition: umpnpmgr.c:39
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define HWND_BROADCAST
Definition: winuser.h:1190
DWORD WINAPI DeviceInstallThread(LPVOID lpParameter)
Definition: install.c:346
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define HeapFree(x, y, z)
Definition: compat.h:394
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
HKEY hClassKey
Definition: umpnpmgr.c:45
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12