Merge 14551:14980 from trunk
[reactos.git] / reactos / services / umpnpmgr / umpnpmgr.c
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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/umpnpmgr/umpnpmgr.c
24 * PURPOSE: User-mode Plug and Play manager
25 * PROGRAMMER: Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #define NTOS_MODE_USER
31 #include <ntos.h>
32 #include <ntos/ntpnp.h>
33 #include <ddk/wdmguid.h>
34 #include <windows.h>
35 #include <tchar.h>
36 #include <stdio.h>
37
38 #include <rpc.h>
39 #include <rpcdce.h>
40
41 #include "pnp_s.h"
42
43 #define NDEBUG
44 #include <debug.h>
45
46
47
48 /* GLOBALS ******************************************************************/
49
50 static VOID CALLBACK
51 ServiceMain(DWORD argc, LPTSTR *argv);
52
53 static SERVICE_TABLE_ENTRY ServiceTable[2] =
54 {
55 {_T("PlugPlay"), ServiceMain},
56 {NULL, NULL}
57 };
58
59
60 /* FUNCTIONS *****************************************************************/
61
62 static DWORD WINAPI
63 RpcServerThread(LPVOID lpParameter)
64 {
65 RPC_STATUS Status;
66
67 DPRINT("RpcServerThread() called\n");
68
69 Status = RpcServerUseProtseqEpW(L"ncacn_np",
70 20,
71 L"\\pipe\\umpnpmgr",
72 NULL); // Security descriptor
73 if (Status != RPC_S_OK)
74 {
75 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
76 return 0;
77 }
78
79 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
80 NULL,
81 NULL);
82 if (Status != RPC_S_OK)
83 {
84 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
85 return 0;
86 }
87
88 Status = RpcServerListen(1,
89 20,
90 FALSE);
91 if (Status != RPC_S_OK)
92 {
93 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
94 return 0;
95 }
96
97 DPRINT("RpcServerThread() done\n");
98
99 return 0;
100 }
101
102
103 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
104 {
105 return GlobalAlloc(GPTR, len);
106 }
107
108
109 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
110 {
111 GlobalFree(ptr);
112 }
113
114
115 //WORD PNP_GetVersion(RPC_BINDING_HANDLE BindingHandle)
116 WORD PNP_GetVersion(handle_t BindingHandle)
117 {
118 return 0x0400;
119 }
120
121
122 static DWORD WINAPI
123 PnpEventThread(LPVOID lpParameter)
124 {
125 PPLUGPLAY_EVENT_BLOCK PnpEvent;
126 ULONG PnpEventSize;
127 NTSTATUS Status;
128 RPC_STATUS RpcStatus;
129
130 PnpEventSize = 0x1000;
131 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
132 if (PnpEvent == NULL)
133 return ERROR_OUTOFMEMORY;
134
135 for (;;)
136 {
137 DPRINT("Calling NtGetPlugPlayEvent()\n");
138
139 /* Wait for the next pnp event */
140 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
141 /* Resize the buffer for the PnP event if it's too small. */
142 if (Status == STATUS_BUFFER_TOO_SMALL)
143 {
144 PnpEventSize += 0x400;
145 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
146 if (PnpEvent == NULL)
147 return ERROR_OUTOFMEMORY;
148 continue;
149 }
150 if (!NT_SUCCESS(Status))
151 {
152 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
153 break;
154 }
155
156 DPRINT("Received PnP Event\n");
157 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
158 {
159 DPRINT1("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
160 }
161 else
162 {
163 DPRINT1("Unknown event\n");
164 }
165
166 /* FIXME: Process the pnp event */
167
168 /* Dequeue the current pnp event and signal the next one */
169 NtPlugPlayControl(PLUGPLAY_USER_RESPONSE, NULL, 0);
170 }
171
172 HeapFree(GetProcessHeap(), 0, PnpEvent);
173
174 return ERROR_SUCCESS;
175 }
176
177
178 static VOID CALLBACK
179 ServiceMain(DWORD argc, LPTSTR *argv)
180 {
181 HANDLE hThread;
182 DWORD dwThreadId;
183
184 DPRINT("ServiceMain() called\n");
185
186 hThread = CreateThread(NULL,
187 0,
188 PnpEventThread,
189 NULL,
190 0,
191 &dwThreadId);
192 if (hThread != NULL)
193 CloseHandle(hThread);
194
195 hThread = CreateThread(NULL,
196 0,
197 RpcServerThread,
198 NULL,
199 0,
200 &dwThreadId);
201 if (hThread != NULL)
202 CloseHandle(hThread);
203
204 DPRINT("ServiceMain() done\n");
205 }
206
207
208 int
209 main(int argc, char *argv[])
210 {
211 DPRINT("Umpnpmgr: main() started\n");
212
213 StartServiceCtrlDispatcher(ServiceTable);
214
215 DPRINT("Umpnpmgr: main() done\n");
216
217 ExitThread(0);
218
219 return 0;
220 }
221
222 /* EOF */