Send SW_HIDE instead of SW_SHOWNOACTIVATE to newdev.dll when 2nd stage setup is running
[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 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: services/umpnpmgr/umpnpmgr.c
23 * PURPOSE: User-mode Plug and Play manager
24 * PROGRAMMER: Eric Kohl
25 * Hervé Poussineau (hpoussin@reactos.org)
26 */
27
28 /* INCLUDES *****************************************************************/
29 #define WIN32_NO_STATUS
30 #include <windows.h>
31 #define NTOS_MODE_USER
32 #include <ndk/ntndk.h>
33 #include <ndk/sysguid.h>
34 #include <ddk/wdmguid.h>
35 #include <ddk/cfgmgr32.h>
36
37 #include <rpc.h>
38 #include <rpcdce.h>
39
40 #include "pnp_c.h"
41
42 #define NDEBUG
43 #include <debug.h>
44
45 /* GLOBALS ******************************************************************/
46
47 static VOID CALLBACK
48 ServiceMain(DWORD argc, LPTSTR *argv);
49
50 static SERVICE_TABLE_ENTRY ServiceTable[2] =
51 {
52 {TEXT("PlugPlay"), ServiceMain},
53 {NULL, NULL}
54 };
55
56 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
57
58 static HKEY hEnumKey = NULL;
59 static HKEY hClassKey = NULL;
60
61 /* FUNCTIONS *****************************************************************/
62
63 static DWORD WINAPI
64 RpcServerThread(LPVOID lpParameter)
65 {
66 RPC_STATUS Status;
67
68 DPRINT("RpcServerThread() called\n");
69
70 Status = RpcServerUseProtseqEpW(L"ncacn_np",
71 20,
72 L"\\pipe\\umpnpmgr",
73 NULL); // Security descriptor
74 if (Status != RPC_S_OK)
75 {
76 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
77 return 0;
78 }
79
80 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
81 NULL,
82 NULL);
83 if (Status != RPC_S_OK)
84 {
85 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
86 return 0;
87 }
88
89 Status = RpcServerListen(1,
90 20,
91 FALSE);
92 if (Status != RPC_S_OK)
93 {
94 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
95 return 0;
96 }
97
98 DPRINT("RpcServerThread() done\n");
99
100 return 0;
101 }
102
103
104 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
105 {
106 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
107 }
108
109
110 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
111 {
112 HeapFree(GetProcessHeap(), 0, ptr);
113 }
114
115
116 static CONFIGRET WINAPI
117 NtStatusToCrError(NTSTATUS Status)
118 {
119 switch (Status)
120 {
121 case STATUS_NO_SUCH_DEVICE:
122 return CR_NO_SUCH_DEVINST;
123 default:
124 /* FIXME: add more mappings */
125 DPRINT1("Unable to map status 0x%08lx\n", Status);
126 return CR_FAILURE;
127 }
128 }
129
130
131 CONFIGRET
132 PNP_GetVersion(handle_t BindingHandle,
133 unsigned short *Version)
134 {
135 *Version = 0x0400;
136 return CR_SUCCESS;
137 }
138
139
140 CONFIGRET
141 PNP_GetGlobalState(handle_t BindingHandle,
142 unsigned long *State,
143 unsigned long Flags)
144 {
145 *State = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
146 return CR_SUCCESS;
147 }
148
149
150 CONFIGRET
151 PNP_ValidateDeviceInstance(handle_t BindingHandle,
152 wchar_t *DeviceInstance,
153 unsigned long Flags)
154 {
155 CONFIGRET ret = CR_SUCCESS;
156 HKEY hEnumKey = NULL;
157 HKEY hDeviceKey = NULL;
158
159 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
160 DeviceInstance, Flags);
161
162 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
163 L"System\\CurrentControlSet\\Enum",
164 0,
165 KEY_ALL_ACCESS,
166 &hEnumKey))
167 {
168 DPRINT("Could not open the Enum Key!\n");
169 ret = CR_FAILURE;
170 goto Done;
171 }
172
173 if (RegOpenKeyExW(hEnumKey,
174 DeviceInstance,
175 0,
176 KEY_READ,
177 &hDeviceKey))
178 {
179 DPRINT("Could not open the Device Key!\n");
180 ret = CR_NO_SUCH_DEVNODE;
181 goto Done;
182 }
183
184 /* FIXME: add more tests */
185
186 Done:
187 if (hDeviceKey != NULL)
188 RegCloseKey(hDeviceKey);
189
190 if (hEnumKey != NULL)
191 RegCloseKey(hEnumKey);
192
193 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
194
195 return ret;
196 }
197
198
199 CONFIGRET
200 PNP_GetRootDeviceInstance(handle_t BindingHandle,
201 wchar_t *DeviceInstance,
202 unsigned long Length)
203 {
204 CONFIGRET ret = CR_SUCCESS;
205
206 DPRINT("PNP_GetRootDeviceInstance() called\n");
207
208 if (Length < lstrlenW(szRootDeviceId) + 1)
209 {
210 ret = CR_BUFFER_SMALL;
211 goto Done;
212 }
213
214 lstrcpyW(DeviceInstance,
215 szRootDeviceId);
216
217 Done:
218 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
219
220 return ret;
221 }
222
223
224 CONFIGRET
225 PNP_GetRelatedDeviceInstance(handle_t BindingHandle,
226 unsigned long Relationship,
227 wchar_t *DeviceId,
228 wchar_t *RelatedDeviceId,
229 unsigned long Length,
230 unsigned long Flags)
231 {
232 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
233 CONFIGRET ret = CR_SUCCESS;
234 NTSTATUS Status;
235
236 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
237 DPRINT(" Relationship %ld\n", Relationship);
238 DPRINT(" DeviceId %S\n", DeviceId);
239
240 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
241 DeviceId);
242
243 PlugPlayData.Relation = Relationship;
244
245 PlugPlayData.RelatedDeviceInstance.Length = 0;
246 PlugPlayData.RelatedDeviceInstance.MaximumLength = Length;
247 PlugPlayData.RelatedDeviceInstance.Buffer = RelatedDeviceId;
248
249 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
250 (PVOID)&PlugPlayData,
251 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
252 if (!NT_SUCCESS(Status))
253 {
254 ret = NtStatusToCrError(Status);
255 }
256
257 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
258 if (ret == CR_SUCCESS)
259 {
260 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
261 }
262
263 return ret;
264 }
265
266
267 CONFIGRET
268 PNP_EnumerateSubKeys(handle_t BindingHandle,
269 unsigned long Branch,
270 unsigned long Index,
271 wchar_t *Buffer,
272 unsigned long Length,
273 unsigned long *RequiredLength,
274 DWORD Flags)
275 {
276 CONFIGRET ret = CR_SUCCESS;
277 HKEY hKey;
278 DWORD dwError;
279
280 DPRINT("PNP_EnumerateSubKeys() called\n");
281
282 switch (Branch)
283 {
284 case PNP_BRANCH_ENUM:
285 hKey = hEnumKey;
286 break;
287
288 case PNP_BRANCH_CLASS:
289 hKey = hClassKey;
290 break;
291
292 default:
293 return CR_FAILURE;
294 }
295
296 *RequiredLength = Length;
297 dwError = RegEnumKeyExW(hKey,
298 Index,
299 Buffer,
300 RequiredLength,
301 NULL,
302 NULL,
303 NULL,
304 NULL);
305 if (dwError != ERROR_SUCCESS)
306 {
307 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
308 }
309 else
310 {
311 (*RequiredLength)++;
312 }
313
314 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
315
316 return ret;
317 }
318
319
320 CONFIGRET
321 PNP_GetDeviceListSize(handle_t BindingHandle,
322 wchar_t *Filter,
323 unsigned long *Length,
324 DWORD Flags)
325 {
326 DPRINT("PNP_GetDeviceListSize() called\n");
327
328 /* FIXME */
329 *Length = 2;
330
331 return CR_SUCCESS;
332 }
333
334
335 CONFIGRET
336 PNP_GetDepth(handle_t BindingHandle,
337 wchar_t *DeviceInstance,
338 unsigned long *Depth,
339 DWORD Flags)
340 {
341 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
342 CONFIGRET ret = CR_SUCCESS;
343 NTSTATUS Status;
344
345 DPRINT("PNP_GetDepth() called\n");
346
347 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
348 DeviceInstance);
349
350 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
351 (PVOID)&PlugPlayData,
352 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
353 if (NT_SUCCESS(Status))
354 {
355 *Depth = PlugPlayData.Depth;
356 }
357 else
358 {
359 ret = NtStatusToCrError(Status);
360 }
361
362 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
363
364 return ret;
365 }
366
367
368 CONFIGRET
369 PNP_SetDeviceRegProp(handle_t BindingHandle,
370 wchar_t *DeviceId,
371 unsigned long Property,
372 unsigned long DataType,
373 char *Buffer,
374 unsigned long Length,
375 unsigned long Flags)
376 {
377 CONFIGRET ret = CR_SUCCESS;
378 LPWSTR lpValueName = NULL;
379 HKEY hKey = 0;
380
381 DPRINT("PNP_SetDeviceRegProp() called\n");
382
383 DPRINT("DeviceId: %S\n", DeviceId);
384 DPRINT("Property: %lu\n", Property);
385 DPRINT("DataType: %lu\n", DataType);
386 DPRINT("Length: %lu\n", Length);
387
388 switch (Property)
389 {
390 case CM_DRP_DEVICEDESC:
391 lpValueName = L"DeviceDesc";
392 break;
393
394 case CM_DRP_HARDWAREID:
395 lpValueName = L"HardwareID";
396 break;
397
398 case CM_DRP_COMPATIBLEIDS:
399 lpValueName = L"CompatibleIDs";
400 break;
401
402 case CM_DRP_SERVICE:
403 lpValueName = L"Service";
404 break;
405
406 case CM_DRP_CLASS:
407 lpValueName = L"Class";
408 break;
409
410 case CM_DRP_CLASSGUID:
411 lpValueName = L"ClassGUID";
412 break;
413
414 case CM_DRP_DRIVER:
415 lpValueName = L"Driver";
416 break;
417
418 case CM_DRP_CONFIGFLAGS:
419 lpValueName = L"ConfigFlags";
420 break;
421
422 case CM_DRP_MFG:
423 lpValueName = L"Mfg";
424 break;
425
426 case CM_DRP_FRIENDLYNAME:
427 lpValueName = L"FriendlyName";
428 break;
429
430 case CM_DRP_LOCATION_INFORMATION:
431 lpValueName = L"LocationInformation";
432 break;
433
434 case CM_DRP_UPPERFILTERS:
435 lpValueName = L"UpperFilters";
436 break;
437
438 case CM_DRP_LOWERFILTERS:
439 lpValueName = L"LowerFilters";
440 break;
441
442 default:
443 return CR_INVALID_PROPERTY;
444 }
445
446 DPRINT("Value name: %S\n", lpValueName);
447
448 if (RegOpenKeyExW(hEnumKey,
449 DeviceId,
450 0,
451 KEY_ALL_ACCESS,
452 &hKey))
453 return CR_INVALID_DEVNODE;
454
455 if (Length == 0)
456 {
457 if (RegDeleteValueW(hKey,
458 lpValueName))
459 ret = CR_REGISTRY_ERROR;
460 }
461 else
462 {
463 if (RegSetValueExW(hKey,
464 lpValueName,
465 0,
466 DataType,
467 (const BYTE*)Buffer,
468 Length))
469 ret = CR_REGISTRY_ERROR;
470 }
471
472 RegCloseKey(hKey);
473
474 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
475
476 return ret;
477 }
478
479
480 CONFIGRET
481 PNP_GetDeviceRegProp(handle_t BindingHandle,
482 wchar_t *DeviceInstance,
483 unsigned long Property,
484 unsigned long *DataType,
485 char *Buffer,
486 unsigned long *TransferLen,
487 unsigned long *Length,
488 DWORD Flags)
489 {
490 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
491 CONFIGRET ret = CR_SUCCESS;
492 LPWSTR lpValueName = NULL;
493 HKEY hKey = 0;
494 NTSTATUS Status;
495
496 DPRINT("PNP_GetDeviceRegProp() called\n");
497
498 switch (Property)
499 {
500 case CM_DRP_DEVICEDESC:
501 lpValueName = L"DeviceDesc";
502 break;
503
504 case CM_DRP_HARDWAREID:
505 lpValueName = L"HardwareID";
506 break;
507
508 case CM_DRP_COMPATIBLEIDS:
509 lpValueName = L"CompatibleIDs";
510 break;
511
512 case CM_DRP_SERVICE:
513 lpValueName = L"Service";
514 break;
515
516 case CM_DRP_CLASS:
517 lpValueName = L"Class";
518 break;
519
520 case CM_DRP_CLASSGUID:
521 lpValueName = L"ClassGUID";
522 break;
523
524 case CM_DRP_DRIVER:
525 lpValueName = L"Driver";
526 break;
527
528 case CM_DRP_CONFIGFLAGS:
529 lpValueName = L"ConfigFlags";
530 break;
531
532 case CM_DRP_MFG:
533 lpValueName = L"Mfg";
534 break;
535
536 case CM_DRP_FRIENDLYNAME:
537 lpValueName = L"FriendlyName";
538 break;
539
540 case CM_DRP_LOCATION_INFORMATION:
541 lpValueName = L"LocationInformation";
542 break;
543
544 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
545 lpValueName = NULL;
546 break;
547
548 case CM_DRP_CAPABILITIES:
549 lpValueName = L"Capabilities";
550 break;
551
552 case CM_DRP_UI_NUMBER:
553 lpValueName = NULL;
554 break;
555
556 case CM_DRP_UPPERFILTERS:
557 lpValueName = L"UpperFilters";
558 break;
559
560 case CM_DRP_LOWERFILTERS:
561 lpValueName = L"LowerFilters";
562 break;
563
564 case CM_DRP_BUSTYPEGUID:
565 lpValueName = NULL;
566 break;
567
568 case CM_DRP_LEGACYBUSTYPE:
569 lpValueName = NULL;
570 break;
571
572 case CM_DRP_BUSNUMBER:
573 lpValueName = NULL;
574 break;
575
576 case CM_DRP_ENUMERATOR_NAME:
577 lpValueName = NULL;
578 break;
579
580 default:
581 return CR_INVALID_PROPERTY;
582 }
583
584 DPRINT("Value name: %S\n", lpValueName);
585
586 if (lpValueName)
587 {
588 /* Retrieve information from the Registry */
589 if (RegOpenKeyExW(hEnumKey,
590 DeviceInstance,
591 0,
592 KEY_ALL_ACCESS,
593 &hKey))
594 return CR_INVALID_DEVNODE;
595
596 if (RegQueryValueExW(hKey,
597 lpValueName,
598 NULL,
599 DataType,
600 (LPBYTE)Buffer,
601 Length))
602 ret = CR_REGISTRY_ERROR;
603
604 /* FIXME: Check buffer size */
605
606 RegCloseKey(hKey);
607 }
608 else
609 {
610 /* Retrieve information from the Device Node */
611 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
612 DeviceInstance);
613 PlugPlayData.Buffer = Buffer;
614 PlugPlayData.BufferSize = *TransferLen;
615
616 switch (Property)
617 {
618 #if 0
619 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
620 PlugPlayData.Property = DevicePropertyPhysicalDeviceObjectName;
621 break;
622
623 case CM_DRP_UI_NUMBER:
624 PlugPlayData.Property = DevicePropertyUINumber;
625 break;
626
627 case CM_DRP_BUSTYPEGUID:
628 PlugPlayData.Property = DevicePropertyBusTypeGuid;
629 break;
630
631 case CM_DRP_LEGACYBUSTYPE:
632 PlugPlayData.Property = DevicePropertyLegacyBusType;
633 break;
634
635 case CM_DRP_BUSNUMBER:
636 PlugPlayData.Property = DevicePropertyBusNumber;
637 break;
638
639 case CM_DRP_ENUMERATOR_NAME:
640 PlugPlayData.Property = DevicePropertyEnumeratorName;
641 break;
642 #endif
643
644 default:
645 return CR_INVALID_PROPERTY;
646 }
647
648 Status = NtPlugPlayControl(PlugPlayControlProperty,
649 (PVOID)&PlugPlayData,
650 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
651 if (NT_SUCCESS(Status))
652 {
653 *Length = PlugPlayData.BufferSize;
654 }
655 else
656 {
657 ret = NtStatusToCrError(Status);
658 }
659 }
660
661 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
662
663 return ret;
664 }
665
666
667 CONFIGRET
668 PNP_CreateKey(handle_t BindingHandle,
669 wchar_t *SubKey,
670 unsigned long samDesired,
671 unsigned long Flags)
672 {
673 CONFIGRET ret = CR_SUCCESS;
674
675 DPRINT("PNP_CreateKey() called\n");
676
677 DPRINT("PNP_CreateKey() done (returns %lx)\n", ret);
678
679 return ret;
680 }
681
682
683 CONFIGRET
684 PNP_GetClassName(handle_t BindingHandle,
685 wchar_t *ClassGuid,
686 wchar_t *Buffer,
687 unsigned long *Length,
688 unsigned long Flags)
689 {
690 WCHAR szKeyName[MAX_PATH];
691 CONFIGRET ret = CR_SUCCESS;
692 HKEY hKey = NULL;
693 ULONG ulSize;
694
695 DPRINT("PNP_GetClassName() called\n");
696
697 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class");
698 lstrcatW(szKeyName, L"\\");
699 lstrcatW(szKeyName, ClassGuid);
700
701 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
702 szKeyName,
703 0,
704 KEY_QUERY_VALUE,
705 &hKey))
706 return CR_REGISTRY_ERROR;
707
708 ulSize = *Length * sizeof(WCHAR);
709 if (RegQueryValueExW(hKey,
710 L"Class",
711 NULL,
712 NULL,
713 (LPBYTE)Buffer,
714 &ulSize))
715 {
716 *Length = 0;
717 ret = CR_REGISTRY_ERROR;
718 }
719 else
720 {
721 *Length = ulSize / sizeof(WCHAR);
722 }
723
724 RegCloseKey(hKey);
725
726 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
727
728 return ret;
729 }
730
731
732 CONFIGRET
733 PNP_DeleteClassKey(handle_t BindingHandle,
734 wchar_t *ClassGuid,
735 unsigned long Flags)
736 {
737 CONFIGRET ret = CR_SUCCESS;
738
739 DPRINT("PNP_GetClassName(%S, %lx) called\n", ClassGuid, Flags);
740
741 if (Flags & CM_DELETE_CLASS_SUBKEYS)
742 {
743 if (RegDeleteTreeW(hClassKey, ClassGuid) != ERROR_SUCCESS)
744 ret = CR_REGISTRY_ERROR;
745 }
746 else
747 {
748 if (RegDeleteKeyW(hClassKey, ClassGuid) != ERROR_SUCCESS)
749 ret = CR_REGISTRY_ERROR;
750 }
751
752 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
753
754 return ret;
755 }
756
757
758 CONFIGRET
759 PNP_GetDeviceStatus(handle_t BindingHandle,
760 wchar_t *DeviceInstance,
761 unsigned long *pStatus,
762 unsigned long *pProblem,
763 DWORD Flags)
764 {
765 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
766 CONFIGRET ret = CR_SUCCESS;
767 NTSTATUS Status;
768
769 DPRINT("PNP_GetDeviceStatus() called\n");
770
771 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
772 DeviceInstance);
773 PlugPlayData.Operation = 0; /* Get status */
774
775 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
776 (PVOID)&PlugPlayData,
777 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
778 if (NT_SUCCESS(Status))
779 {
780 *pStatus = PlugPlayData.DeviceStatus;
781 *pProblem = PlugPlayData.DeviceProblem;
782 }
783 else
784 {
785 ret = NtStatusToCrError(Status);
786 }
787
788 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
789
790 return ret;
791 }
792
793
794 CONFIGRET
795 PNP_SetDeviceProblem(handle_t BindingHandle,
796 wchar_t *DeviceInstance,
797 unsigned long Problem,
798 DWORD Flags)
799 {
800 CONFIGRET ret = CR_SUCCESS;
801
802 DPRINT1("PNP_SetDeviceProblem() called\n");
803
804 /* FIXME */
805
806 DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret);
807
808 return ret;
809 }
810
811
812 /* Function 38 */
813 CONFIGRET
814 PNP_IsDockStationPresent(handle_t BindingHandle,
815 unsigned long *Present)
816 {
817 HKEY hKey;
818 DWORD dwType;
819 DWORD dwValue;
820 DWORD dwSize;
821 CONFIGRET ret = CR_SUCCESS;
822
823 DPRINT1("PNP_IsDockStationPresent() called\n");
824
825 *Present = FALSE;
826
827 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
828 L"CurrentDockInfo",
829 0,
830 KEY_READ,
831 &hKey) != ERROR_SUCCESS)
832 return CR_REGISTRY_ERROR;
833
834 dwSize = sizeof(DWORD);
835 if (RegQueryValueExW(hKey,
836 L"DockingState",
837 NULL,
838 &dwType,
839 (LPBYTE)&dwValue,
840 &dwSize) != ERROR_SUCCESS)
841 ret = CR_REGISTRY_ERROR;
842
843 RegCloseKey(hKey);
844
845 if (ret == CR_SUCCESS)
846 {
847 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
848 {
849 ret = CR_REGISTRY_ERROR;
850 }
851 else if (dwValue != 0)
852 {
853 *Present = TRUE;
854 }
855 }
856
857 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
858
859 return ret;
860 }
861
862
863 /* Function 39 */
864 CONFIGRET
865 PNP_RequestEjectPC(handle_t BindingHandle)
866 {
867 CONFIGRET ret = CR_SUCCESS;
868
869 DPRINT1("PNP_RequestEjectPC() called\n");
870
871 ret = CR_FAILURE; /* FIXME */
872
873 DPRINT1("PNP_RequestEjectPC() done (returns %lx)\n", ret);
874
875 return ret;
876 }
877
878 typedef BOOL (WINAPI *PDEV_INSTALL_W)(HWND, HINSTANCE, LPCWSTR, INT);
879
880 static BOOL
881 InstallDevice(PCWSTR DeviceInstance, BOOL SetupIsActive)
882 {
883 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
884 HMODULE hNewDev = NULL;
885 PDEV_INSTALL_W DevInstallW;
886 NTSTATUS Status;
887 BOOL DeviceInstalled = FALSE;
888
889 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
890 DeviceInstance);
891 PlugPlayData.Operation = 0; /* Get status */
892
893 /* Get device status */
894 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
895 (PVOID)&PlugPlayData,
896 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
897 if (!NT_SUCCESS(Status))
898 return FALSE;
899
900 if (PlugPlayData.DeviceStatus & DNF_STARTED || PlugPlayData.DeviceStatus & DNF_START_FAILED)
901 /* Device is already started, or disabled due to some problem. Don't install it */
902 return TRUE;
903
904 /* Install device */
905 SetEnvironmentVariable(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
906 hNewDev = LoadLibraryW(L"newdev.dll");
907 if (!hNewDev)
908 goto cleanup;
909 DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
910 if (!DevInstallW)
911 goto cleanup;
912 if (!DevInstallW(NULL, NULL, DeviceInstance, SetupIsActive ? SW_HIDE : SW_SHOWNOACTIVATE))
913 goto cleanup;
914
915 DeviceInstalled = TRUE;
916
917 cleanup:
918 if (hNewDev != NULL)
919 FreeLibrary(hNewDev);
920
921 return DeviceInstalled;
922 }
923
924 static BOOL
925 SetupIsActive(VOID)
926 {
927 HKEY hKey = INVALID_HANDLE_VALUE;
928 DWORD regType, active, size;
929 LONG rc;
930 BOOL ret = FALSE;
931
932 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
933 if (rc != ERROR_SUCCESS)
934 goto cleanup;
935
936 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
937 if (rc != ERROR_SUCCESS)
938 goto cleanup;
939 if (regType != REG_DWORD)
940 goto cleanup;
941
942 ret = (active != 0);
943
944 cleanup:
945 if (hKey != INVALID_HANDLE_VALUE)
946 RegCloseKey(hKey);
947 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
948 return ret;
949 }
950
951 static DWORD WINAPI
952 PnpEventThread(LPVOID lpParameter)
953 {
954 PPLUGPLAY_EVENT_BLOCK PnpEvent;
955 ULONG PnpEventSize;
956 NTSTATUS Status;
957 RPC_STATUS RpcStatus;
958 BOOL setupActive;
959
960 PnpEventSize = 0x1000;
961 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
962 if (PnpEvent == NULL)
963 return ERROR_OUTOFMEMORY;
964
965 setupActive = SetupIsActive();
966
967 for (;;)
968 {
969 DPRINT("Calling NtGetPlugPlayEvent()\n");
970
971 /* Wait for the next pnp event */
972 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
973
974 /* Resize the buffer for the PnP event if it's too small. */
975 if (Status == STATUS_BUFFER_TOO_SMALL)
976 {
977 PnpEventSize += 0x400;
978 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
979 if (PnpEvent == NULL)
980 return ERROR_OUTOFMEMORY;
981 continue;
982 }
983
984 if (!NT_SUCCESS(Status))
985 {
986 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
987 break;
988 }
989
990 DPRINT("Received PnP Event\n");
991 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
992 {
993 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
994 InstallDevice(PnpEvent->TargetDevice.DeviceIds, setupActive);
995 }
996 else
997 {
998 DPRINT1("Unknown event\n");
999 }
1000
1001 /* FIXME: Process the pnp event */
1002
1003 /* Dequeue the current pnp event and signal the next one */
1004 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
1005 }
1006
1007 HeapFree(GetProcessHeap(), 0, PnpEvent);
1008
1009 return ERROR_SUCCESS;
1010 }
1011
1012
1013 static VOID CALLBACK
1014 ServiceMain(DWORD argc, LPTSTR *argv)
1015 {
1016 HANDLE hThread;
1017 DWORD dwThreadId;
1018
1019 DPRINT("ServiceMain() called\n");
1020
1021 hThread = CreateThread(NULL,
1022 0,
1023 PnpEventThread,
1024 NULL,
1025 0,
1026 &dwThreadId);
1027 if (hThread != NULL)
1028 CloseHandle(hThread);
1029
1030 hThread = CreateThread(NULL,
1031 0,
1032 RpcServerThread,
1033 NULL,
1034 0,
1035 &dwThreadId);
1036 if (hThread != NULL)
1037 CloseHandle(hThread);
1038
1039 DPRINT("ServiceMain() done\n");
1040 }
1041
1042
1043 int
1044 main(int argc, char *argv[])
1045 {
1046 DWORD dwError;
1047
1048 DPRINT("Umpnpmgr: main() started\n");
1049
1050 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1051 L"System\\CurrentControlSet\\Enum",
1052 0,
1053 KEY_ALL_ACCESS,
1054 &hEnumKey);
1055 if (dwError != ERROR_SUCCESS)
1056 {
1057 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
1058 return dwError;
1059 }
1060
1061 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1062 L"System\\CurrentControlSet\\Control\\Class",
1063 0,
1064 KEY_ALL_ACCESS,
1065 &hClassKey);
1066 if (dwError != ERROR_SUCCESS)
1067 {
1068 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
1069 return dwError;
1070 }
1071
1072 StartServiceCtrlDispatcher(ServiceTable);
1073
1074 DPRINT("Umpnpmgr: main() done\n");
1075
1076 ExitThread(0);
1077
1078 return 0;
1079 }
1080
1081 /* EOF */