xref: /reactos/base/services/umpnpmgr/event.c (revision d326ca1f)
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/event.c
23  * PURPOSE:          PNP Event thread
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 /* FUNCTIONS *****************************************************************/
37 
38 static
39 VOID
40 ProcessTargetDeviceEvent(
41     _In_ PPLUGPLAY_EVENT_BLOCK PnpEvent)
42 {
43     RPC_STATUS RpcStatus;
44 
45     DPRINT("ProcessTargetDeviceEvent(%p)\n", PnpEvent);
46 
47     if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
48     {
49 //        DWORD dwRecipient;
50 
51         DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
52 
53 //       dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
54 //       BroadcastSystemMessageW(BSF_POSTMESSAGE,
55 //                               &dwRecipient,
56 //                               WM_DEVICECHANGE,
57 //                               DBT_DEVNODES_CHANGED,
58 //                               0);
59         SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
60     }
61     else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
62     {
63         DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
64     }
65     else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
66     {
67         DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
68     }
69     else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
70     {
71 //        DWORD dwRecipient;
72 
73         DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
74 
75 //        dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
76 //        BroadcastSystemMessageW(BSF_POSTMESSAGE,
77 //                                &dwRecipient,
78 //                                WM_DEVICECHANGE,
79 //                                DBT_DEVNODES_CHANGED,
80 //                                0);
81         SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
82     }
83     else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
84     {
85 //        DWORD dwRecipient;
86 
87         DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
88 
89 //        dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
90 //        BroadcastSystemMessageW(BSF_POSTMESSAGE,
91 //                                &dwRecipient,
92 //                                WM_DEVICECHANGE,
93 //                                DBT_DEVNODES_CHANGED,
94 //                                0);
95         SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
96     }
97     else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
98     {
99         DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
100     }
101     else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
102     {
103         DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
104     }
105     else
106     {
107         DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
108                 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
109                 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
110                 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
111                 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
112     }
113 }
114 
115 
116 static
117 VOID
118 ProcessDeviceClassChangeEvent(
119     _In_ PPLUGPLAY_EVENT_BLOCK PnpEvent)
120 {
121     DPRINT("ProcessDeviceClassChangeEvent(%p)\n", PnpEvent);
122     DPRINT("SymbolicLink: %S\n", PnpEvent->DeviceClass.SymbolicLinkName);
123     DPRINT("ClassGuid: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
124            PnpEvent->DeviceClass.ClassGuid.Data1, PnpEvent->DeviceClass.ClassGuid.Data2, PnpEvent->DeviceClass.ClassGuid.Data3,
125            PnpEvent->DeviceClass.ClassGuid.Data4[0], PnpEvent->DeviceClass.ClassGuid.Data4[1], PnpEvent->DeviceClass.ClassGuid.Data4[2],
126            PnpEvent->DeviceClass.ClassGuid.Data4[3], PnpEvent->DeviceClass.ClassGuid.Data4[4], PnpEvent->DeviceClass.ClassGuid.Data4[5],
127            PnpEvent->DeviceClass.ClassGuid.Data4[6], PnpEvent->DeviceClass.ClassGuid.Data4[7]);
128 }
129 
130 
131 static
132 VOID
133 ProcessDeviceInstallEvent(
134     _In_ PPLUGPLAY_EVENT_BLOCK PnpEvent)
135 {
136     DeviceInstallParams* Params;
137     DWORD len;
138     DWORD DeviceIdLength;
139 //    DWORD dwRecipient;
140 
141     DPRINT("ProcessDeviceInstallEvent(%p)\n", PnpEvent);
142     DPRINT("Device enumerated: %S\n", PnpEvent->InstallDevice.DeviceId);
143 
144     DeviceIdLength = lstrlenW(PnpEvent->InstallDevice.DeviceId);
145     if (DeviceIdLength)
146     {
147         /* Allocate a new device-install event */
148         len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
149         Params = HeapAlloc(GetProcessHeap(), 0, len);
150         if (Params)
151         {
152             wcscpy(Params->DeviceIds, PnpEvent->InstallDevice.DeviceId);
153 
154             /* Queue the event (will be dequeued by DeviceInstallThread) */
155             WaitForSingleObject(hDeviceInstallListMutex, INFINITE);
156             InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
157             ReleaseMutex(hDeviceInstallListMutex);
158 
159             SetEvent(hDeviceInstallListNotEmpty);
160 
161 //            dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
162 //            BroadcastSystemMessageW(BSF_POSTMESSAGE,
163 //                                    &dwRecipient,
164 //                                    WM_DEVICECHANGE,
165 //                                    DBT_DEVNODES_CHANGED,
166 //                                    0);
167             SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
168         }
169     }
170 }
171 
172 
173 DWORD
174 WINAPI
175 PnpEventThread(
176     _In_ LPVOID lpParameter)
177 {
178     PLUGPLAY_CONTROL_USER_RESPONSE_DATA ResponseData = {0, 0, 0, 0};
179     DWORD dwRet = ERROR_SUCCESS;
180     NTSTATUS Status;
181     PPLUGPLAY_EVENT_BLOCK PnpEvent, NewPnpEvent;
182     ULONG PnpEventSize;
183 
184     UNREFERENCED_PARAMETER(lpParameter);
185 
186     PnpEventSize = 0x1000;
187     PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
188     if (PnpEvent == NULL)
189         return ERROR_OUTOFMEMORY;
190 
191     for (;;)
192     {
193         DPRINT("Calling NtGetPlugPlayEvent()\n");
194 
195         /* Wait for the next PnP event */
196         Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
197 
198         /* Resize the buffer for the PnP event if it's too small */
199         if (Status == STATUS_BUFFER_TOO_SMALL)
200         {
201             PnpEventSize += 0x400;
202             NewPnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
203             if (NewPnpEvent == NULL)
204             {
205                 dwRet = ERROR_OUTOFMEMORY;
206                 break;
207             }
208             PnpEvent = NewPnpEvent;
209             continue;
210         }
211 
212         if (!NT_SUCCESS(Status))
213         {
214             DPRINT1("NtGetPlugPlayEvent() failed (Status 0x%08lx)\n", Status);
215             break;
216         }
217 
218         /* Process the PnP event */
219         DPRINT("Received PnP Event\n");
220         switch (PnpEvent->EventCategory)
221         {
222 //            case HardwareProfileChangeEvent:
223 
224             case TargetDeviceChangeEvent:
225                 ProcessTargetDeviceEvent(PnpEvent);
226                 break;
227 
228             case DeviceClassChangeEvent:
229                 ProcessDeviceClassChangeEvent(PnpEvent);
230                 break;
231 
232 //            case CustomDeviceEvent:
233 
234             case DeviceInstallEvent:
235                 ProcessDeviceInstallEvent(PnpEvent);
236                 break;
237 
238 //            case DeviceArrivalEvent:
239 //            case PowerEvent:
240 //            case VetoEvent:
241 //            case BlockedDriverEvent:
242 
243             default:
244                 DPRINT1("Unsupported Event Category: %lu\n", PnpEvent->EventCategory);
245                 break;
246         }
247 
248         /* Dequeue the current PnP event and signal the next one */
249         Status = NtPlugPlayControl(PlugPlayControlUserResponse,
250                                    &ResponseData,
251                                    sizeof(ResponseData));
252         if (!NT_SUCCESS(Status))
253         {
254             DPRINT1("NtPlugPlayControl(PlugPlayControlUserResponse) failed (Status 0x%08lx)\n", Status);
255             break;
256         }
257     }
258 
259     HeapFree(GetProcessHeap(), 0, PnpEvent);
260 
261     return dwRet;
262 }
263 
264 /* EOF */
265