Dynamically reallocate the buffer for PnP event if it's too small.
[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 UNICODE
31 #define _UNICODE
32
33 #define NTOS_MODE_USER
34 #include <ntos.h>
35 #include <ntos/ntpnp.h>
36 #include <ddk/wdmguid.h>
37 #include <windows.h>
38 #include <tchar.h>
39 #include <stdio.h>
40
41 #include <rpc.h>
42 #include <rpcdce.h>
43
44 #define DBG
45 #define NDEBUG
46 #include <debug.h>
47
48
49
50 /* GLOBALS ******************************************************************/
51
52 static VOID CALLBACK
53 ServiceMain(DWORD argc, LPTSTR *argv);
54
55 static SERVICE_TABLE_ENTRY ServiceTable[2] =
56 {
57 {_T("PlugPlay"), ServiceMain},
58 {NULL, NULL}
59 };
60
61
62 /* FUNCTIONS *****************************************************************/
63
64 static DWORD WINAPI
65 PnpEventThread(LPVOID lpParameter)
66 {
67 PPLUGPLAY_EVENT_BLOCK PnpEvent;
68 ULONG PnpEventSize;
69 NTSTATUS Status;
70 RPC_STATUS RpcStatus;
71
72 PnpEventSize = 0x1000;
73 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
74 if (PnpEvent == NULL)
75 return ERROR_OUTOFMEMORY;
76
77 for (;;)
78 {
79 DPRINT("Calling NtGetPlugPlayEvent()\n");
80
81 /* Wait for the next pnp event */
82 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, 1024);
83 /* Resize the buffer for the PnP event if it's too small. */
84 if (Status == STATUS_BUFFER_TOO_SMALL)
85 {
86 PnpEventSize += 0x400;
87 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
88 if (PnpEvent == NULL)
89 return ERROR_OUTOFMEMORY;
90 continue;
91 }
92 if (!NT_SUCCESS(Status))
93 {
94 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
95 break;
96 }
97
98 DPRINT("Received PnP Event\n");
99 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
100 {
101 DPRINT1("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
102 }
103 else
104 {
105 DPRINT1("Unknown event\n");
106 }
107
108 /* FIXME: Process the pnp event */
109
110 /* Dequeue the current pnp event and signal the next one */
111 NtPlugPlayControl(PLUGPLAY_USER_RESPONSE, NULL, 0);
112 }
113
114 HeapFree(GetProcessHeap(), 0, PnpEvent);
115
116 return ERROR_SUCCESS;
117 }
118
119
120 static VOID CALLBACK
121 ServiceMain(DWORD argc, LPTSTR *argv)
122 {
123 HANDLE hThread;
124 DWORD dwThreadId;
125
126 DPRINT("ServiceMain() called\n");
127
128 hThread = CreateThread(NULL,
129 0,
130 PnpEventThread,
131 NULL,
132 0,
133 &dwThreadId);
134 if (hThread != NULL)
135 CloseHandle(hThread);
136
137 DPRINT("ServiceMain() done\n");
138 }
139
140
141 int
142 main(int argc, char *argv[])
143 {
144 DPRINT("Umpnpmgr: main() started\n");
145
146 StartServiceCtrlDispatcher(ServiceTable);
147
148 DPRINT("Umpnpmgr: main() done\n");
149
150 ExitThread(0);
151
152 return 0;
153 }
154
155 /* EOF */