8fd96c4d8c611a0f6dc0dee9283bb627f20d9893
[reactos.git] / base / 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 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: services/umpnpmgr/umpnpmgr.c
23 * PURPOSE: User-mode Plug and Play manager
24 * PROGRAMMER: Eric Kohl
25 * Hervé Poussineau (hpoussin@reactos.org)
26 * Colin Finck (colin@reactos.org)
27 */
28
29 /* INCLUDES *****************************************************************/
30 //#define HAVE_SLIST_ENTRY_IMPLEMENTED
31 #define WIN32_NO_STATUS
32 #include <windows.h>
33 #include <stdio.h>
34 #include <cmtypes.h>
35 #include <cmfuncs.h>
36 #include <rtlfuncs.h>
37 #include <setypes.h>
38 #include <umpnpmgr/sysguid.h>
39 #include <wdmguid.h>
40 #include <cfgmgr32.h>
41 #include <regstr.h>
42 #include <userenv.h>
43
44 #include <rpc.h>
45 #include <rpcdce.h>
46
47 #include "pnp_s.h"
48
49 #define NDEBUG
50 #include <debug.h>
51
52 /* GLOBALS ******************************************************************/
53
54 static VOID CALLBACK
55 ServiceMain(DWORD argc, LPTSTR *argv);
56
57 static SERVICE_TABLE_ENTRY ServiceTable[2] =
58 {
59 {TEXT("PlugPlay"), ServiceMain},
60 {NULL, NULL}
61 };
62
63 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
64
65 static HKEY hEnumKey = NULL;
66 static HKEY hClassKey = NULL;
67
68 static HANDLE hUserToken = NULL;
69 static HANDLE hInstallEvent = NULL;
70 static HANDLE hNoPendingInstalls = NULL;
71
72 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
73 static SLIST_HEADER DeviceInstallListHead;
74 #else
75 static LIST_ENTRY DeviceInstallListHead;
76 #endif
77 static HANDLE hDeviceInstallListNotEmpty;
78
79 typedef struct
80 {
81 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
82 SLIST_ENTRY ListEntry;
83 #else
84 LIST_ENTRY ListEntry;
85 #endif
86 WCHAR DeviceIds[1];
87 } DeviceInstallParams;
88
89 /* FUNCTIONS *****************************************************************/
90
91 static DWORD WINAPI
92 RpcServerThread(LPVOID lpParameter)
93 {
94 RPC_STATUS Status;
95
96 UNREFERENCED_PARAMETER(lpParameter);
97
98 DPRINT("RpcServerThread() called\n");
99
100 Status = RpcServerUseProtseqEpW(L"ncacn_np",
101 20,
102 L"\\pipe\\umpnpmgr",
103 NULL); // Security descriptor
104 if (Status != RPC_S_OK)
105 {
106 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
107 return 0;
108 }
109
110 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
111 NULL,
112 NULL);
113 if (Status != RPC_S_OK)
114 {
115 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
116 return 0;
117 }
118
119 Status = RpcServerListen(1,
120 20,
121 FALSE);
122 if (Status != RPC_S_OK)
123 {
124 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
125 return 0;
126 }
127
128 /* ROS HACK (this should never happen...) */
129 DPRINT1("*** Other devices won't be installed correctly. If something\n");
130 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
131
132 DPRINT("RpcServerThread() done\n");
133
134 return 0;
135 }
136
137
138 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
139 {
140 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
141 }
142
143
144 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
145 {
146 HeapFree(GetProcessHeap(), 0, ptr);
147 }
148
149
150 static CONFIGRET WINAPI
151 NtStatusToCrError(NTSTATUS Status)
152 {
153 switch (Status)
154 {
155 case STATUS_NO_SUCH_DEVICE:
156 return CR_NO_SUCH_DEVINST;
157
158 default:
159 /* FIXME: add more mappings */
160 DPRINT1("Unable to map status 0x%08lx\n", Status);
161 return CR_FAILURE;
162 }
163 }
164
165
166 /* Function 0 */
167 DWORD PNP_Disconnect(
168 handle_t hBinding)
169 {
170 UNREFERENCED_PARAMETER(hBinding);
171 UNIMPLEMENTED;
172 return CR_CALL_NOT_IMPLEMENTED;
173 }
174
175
176 /* Function 1 */
177 DWORD PNP_Connect(
178 handle_t hBinding)
179 {
180 UNREFERENCED_PARAMETER(hBinding);
181 UNIMPLEMENTED;
182 return CR_CALL_NOT_IMPLEMENTED;
183 }
184
185
186 /* Function 2 */
187 DWORD PNP_GetVersion(
188 handle_t hBinding,
189 WORD *pVersion)
190 {
191 UNREFERENCED_PARAMETER(hBinding);
192
193 *pVersion = 0x0400;
194 return CR_SUCCESS;
195 }
196
197
198 /* Function 3 */
199 DWORD PNP_GetGlobalState(
200 handle_t hBinding,
201 DWORD *pulState,
202 DWORD ulFlags)
203 {
204 UNREFERENCED_PARAMETER(hBinding);
205 UNREFERENCED_PARAMETER(ulFlags);
206
207 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
208 return CR_SUCCESS;
209 }
210
211
212 /* Function 4 */
213 DWORD PNP_InitDetection(
214 handle_t hBinding)
215 {
216 UNREFERENCED_PARAMETER(hBinding);
217
218 DPRINT("PNP_InitDetection() called\n");
219 return CR_SUCCESS;
220 }
221
222
223 /* Function 5 */
224 DWORD PNP_ReportLogOn(
225 handle_t hBinding,
226 BOOL Admin,
227 DWORD ProcessId)
228 {
229 DWORD ReturnValue = CR_FAILURE;
230 HANDLE hProcess;
231
232 UNREFERENCED_PARAMETER(hBinding);
233 UNREFERENCED_PARAMETER(Admin);
234
235 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
236
237 /* Get the users token */
238 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
239
240 if(!hProcess)
241 {
242 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
243 goto cleanup;
244 }
245
246 if (hUserToken)
247 {
248 CloseHandle(hUserToken);
249 hUserToken = NULL;
250 }
251
252 if(!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
253 {
254 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
255 goto cleanup;
256 }
257
258 /* Trigger the installer thread */
259 if (hInstallEvent)
260 SetEvent(hInstallEvent);
261
262 ReturnValue = CR_SUCCESS;
263
264 cleanup:
265 if(hProcess)
266 CloseHandle(hProcess);
267
268 return ReturnValue;
269 }
270
271
272 /* Function 6 */
273 DWORD PNP_ValidateDeviceInstance(
274 handle_t hBinding,
275 LPWSTR pDeviceID,
276 DWORD ulFlags)
277 {
278 CONFIGRET ret = CR_SUCCESS;
279 HKEY hDeviceKey = NULL;
280
281 UNREFERENCED_PARAMETER(hBinding);
282 UNREFERENCED_PARAMETER(ulFlags);
283
284 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
285 pDeviceID, ulFlags);
286
287 if (RegOpenKeyExW(hEnumKey,
288 pDeviceID,
289 0,
290 KEY_READ,
291 &hDeviceKey))
292 {
293 DPRINT("Could not open the Device Key!\n");
294 ret = CR_NO_SUCH_DEVNODE;
295 goto Done;
296 }
297
298 /* FIXME: add more tests */
299
300 Done:
301 if (hDeviceKey != NULL)
302 RegCloseKey(hDeviceKey);
303
304 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
305
306 return ret;
307 }
308
309
310 /* Function 7 */
311 DWORD PNP_GetRootDeviceInstance(
312 handle_t hBinding,
313 LPWSTR pDeviceID,
314 PNP_RPC_STRING_LEN ulLength)
315 {
316 CONFIGRET ret = CR_SUCCESS;
317
318 UNREFERENCED_PARAMETER(hBinding);
319
320 DPRINT("PNP_GetRootDeviceInstance() called\n");
321
322 if (!pDeviceID)
323 {
324 ret = CR_INVALID_POINTER;
325 goto Done;
326 }
327 if (ulLength < lstrlenW(szRootDeviceId) + 1)
328 {
329 ret = CR_BUFFER_SMALL;
330 goto Done;
331 }
332
333 lstrcpyW(pDeviceID,
334 szRootDeviceId);
335
336 Done:
337 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
338
339 return ret;
340 }
341
342
343 /* Function 8 */
344 DWORD PNP_GetRelatedDeviceInstance(
345 handle_t hBinding,
346 DWORD ulRelationship,
347 LPWSTR pDeviceID,
348 LPWSTR pRelatedDeviceId,
349 PNP_RPC_STRING_LEN *pulLength,
350 DWORD ulFlags)
351 {
352 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
353 CONFIGRET ret = CR_SUCCESS;
354 NTSTATUS Status;
355
356 UNREFERENCED_PARAMETER(hBinding);
357 UNREFERENCED_PARAMETER(ulFlags);
358
359 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
360 DPRINT(" Relationship %ld\n", ulRelationship);
361 DPRINT(" DeviceId %S\n", pDeviceID);
362
363 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
364 pDeviceID);
365
366 PlugPlayData.Relation = ulRelationship;
367
368 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
369 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
370
371 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
372 (PVOID)&PlugPlayData,
373 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
374 if (!NT_SUCCESS(Status))
375 {
376 ret = NtStatusToCrError(Status);
377 }
378
379 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
380 if (ret == CR_SUCCESS)
381 {
382 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
383 }
384
385 return ret;
386 }
387
388
389 /* Function 9 */
390 DWORD PNP_EnumerateSubKeys(
391 handle_t hBinding,
392 DWORD ulBranch,
393 DWORD ulIndex,
394 LPWSTR Buffer,
395 PNP_RPC_STRING_LEN ulLength,
396 PNP_RPC_STRING_LEN *pulRequiredLen,
397 DWORD ulFlags)
398 {
399 CONFIGRET ret = CR_SUCCESS;
400 HKEY hKey;
401 DWORD dwError;
402
403 UNREFERENCED_PARAMETER(hBinding);
404 UNREFERENCED_PARAMETER(ulFlags);
405
406 DPRINT("PNP_EnumerateSubKeys() called\n");
407
408 switch (ulBranch)
409 {
410 case PNP_ENUMERATOR_SUBKEYS:
411 hKey = hEnumKey;
412 break;
413
414 case PNP_CLASS_SUBKEYS:
415 hKey = hClassKey;
416 break;
417
418 default:
419 return CR_FAILURE;
420 }
421
422 *pulRequiredLen = ulLength;
423 dwError = RegEnumKeyExW(hKey,
424 ulIndex,
425 Buffer,
426 pulRequiredLen,
427 NULL,
428 NULL,
429 NULL,
430 NULL);
431 if (dwError != ERROR_SUCCESS)
432 {
433 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
434 }
435 else
436 {
437 (*pulRequiredLen)++;
438 }
439
440 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
441
442 return ret;
443 }
444
445
446 /* Function 10 */
447 DWORD PNP_GetDeviceList(
448 handle_t hBinding,
449 LPWSTR pszFilter,
450 LPWSTR Buffer,
451 PNP_RPC_STRING_LEN *pulLength,
452 DWORD ulFlags)
453 {
454 UNIMPLEMENTED;
455 return CR_CALL_NOT_IMPLEMENTED;
456 }
457
458
459 /* Function 11 */
460 DWORD PNP_GetDeviceListSize(
461 handle_t hBinding,
462 LPWSTR pszFilter,
463 PNP_RPC_BUFFER_SIZE *pulLen,
464 DWORD ulFlags)
465 {
466 UNIMPLEMENTED;
467 return CR_CALL_NOT_IMPLEMENTED;
468 }
469
470
471 /* Function 12 */
472 DWORD PNP_GetDepth(
473 handle_t hBinding,
474 LPWSTR pszDeviceID,
475 DWORD *pulDepth,
476 DWORD ulFlags)
477 {
478 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
479 CONFIGRET ret = CR_SUCCESS;
480 NTSTATUS Status;
481
482 UNREFERENCED_PARAMETER(hBinding);
483 UNREFERENCED_PARAMETER(ulFlags);
484
485 DPRINT("PNP_GetDepth() called\n");
486
487 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
488 pszDeviceID);
489
490 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
491 (PVOID)&PlugPlayData,
492 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
493 if (NT_SUCCESS(Status))
494 {
495 *pulDepth = PlugPlayData.Depth;
496 }
497 else
498 {
499 ret = NtStatusToCrError(Status);
500 }
501
502 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
503
504 return ret;
505 }
506
507
508 /* Function 13 */
509 DWORD PNP_GetDeviceRegProp(
510 handle_t hBinding,
511 LPWSTR pDeviceID,
512 DWORD ulProperty,
513 DWORD *pulRegDataType,
514 BYTE *Buffer,
515 PNP_PROP_SIZE *pulTransferLen,
516 PNP_PROP_SIZE *pulLength,
517 DWORD ulFlags)
518 {
519 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
520 CONFIGRET ret = CR_SUCCESS;
521 LPWSTR lpValueName = NULL;
522 HKEY hKey = 0;
523 NTSTATUS Status;
524
525 UNREFERENCED_PARAMETER(hBinding);
526 UNREFERENCED_PARAMETER(ulFlags);
527
528 DPRINT("PNP_GetDeviceRegProp() called\n");
529
530 switch (ulProperty)
531 {
532 case CM_DRP_DEVICEDESC:
533 lpValueName = L"DeviceDesc";
534 break;
535
536 case CM_DRP_HARDWAREID:
537 lpValueName = L"HardwareID";
538 break;
539
540 case CM_DRP_COMPATIBLEIDS:
541 lpValueName = L"CompatibleIDs";
542 break;
543
544 case CM_DRP_SERVICE:
545 lpValueName = L"Service";
546 break;
547
548 case CM_DRP_CLASS:
549 lpValueName = L"Class";
550 break;
551
552 case CM_DRP_CLASSGUID:
553 lpValueName = L"ClassGUID";
554 break;
555
556 case CM_DRP_DRIVER:
557 lpValueName = L"Driver";
558 break;
559
560 case CM_DRP_CONFIGFLAGS:
561 lpValueName = L"ConfigFlags";
562 break;
563
564 case CM_DRP_MFG:
565 lpValueName = L"Mfg";
566 break;
567
568 case CM_DRP_FRIENDLYNAME:
569 lpValueName = L"FriendlyName";
570 break;
571
572 case CM_DRP_LOCATION_INFORMATION:
573 lpValueName = L"LocationInformation";
574 break;
575
576 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
577 lpValueName = NULL;
578 break;
579
580 case CM_DRP_CAPABILITIES:
581 lpValueName = L"Capabilities";
582 break;
583
584 case CM_DRP_UI_NUMBER:
585 lpValueName = NULL;
586 break;
587
588 case CM_DRP_UPPERFILTERS:
589 lpValueName = L"UpperFilters";
590 break;
591
592 case CM_DRP_LOWERFILTERS:
593 lpValueName = L"LowerFilters";
594 break;
595
596 case CM_DRP_BUSTYPEGUID:
597 lpValueName = NULL;
598 break;
599
600 case CM_DRP_LEGACYBUSTYPE:
601 lpValueName = NULL;
602 break;
603
604 case CM_DRP_BUSNUMBER:
605 lpValueName = NULL;
606 break;
607
608 case CM_DRP_ENUMERATOR_NAME:
609 lpValueName = NULL;
610 break;
611
612 default:
613 return CR_INVALID_PROPERTY;
614 }
615
616 DPRINT("Value name: %S\n", lpValueName);
617
618 if (lpValueName)
619 {
620 /* Retrieve information from the Registry */
621 if (RegOpenKeyExW(hEnumKey,
622 pDeviceID,
623 0,
624 KEY_ALL_ACCESS,
625 &hKey))
626 return CR_INVALID_DEVNODE;
627
628 if (RegQueryValueExW(hKey,
629 lpValueName,
630 NULL,
631 pulRegDataType,
632 Buffer,
633 pulLength))
634 ret = CR_REGISTRY_ERROR;
635
636 /* FIXME: Check buffer size */
637
638 RegCloseKey(hKey);
639 }
640 else
641 {
642 /* Retrieve information from the Device Node */
643 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
644 pDeviceID);
645 PlugPlayData.Buffer = Buffer;
646 PlugPlayData.BufferSize = *pulTransferLen;
647
648 switch (ulProperty)
649 {
650 #if 0
651 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
652 PlugPlayData.Property = DevicePropertyPhysicalDeviceObjectName;
653 break;
654
655 case CM_DRP_UI_NUMBER:
656 PlugPlayData.Property = DevicePropertyUINumber;
657 break;
658
659 case CM_DRP_BUSTYPEGUID:
660 PlugPlayData.Property = DevicePropertyBusTypeGuid;
661 break;
662
663 case CM_DRP_LEGACYBUSTYPE:
664 PlugPlayData.Property = DevicePropertyLegacyBusType;
665 break;
666
667 case CM_DRP_BUSNUMBER:
668 PlugPlayData.Property = DevicePropertyBusNumber;
669 break;
670
671 case CM_DRP_ENUMERATOR_NAME:
672 PlugPlayData.Property = DevicePropertyEnumeratorName;
673 break;
674 #endif
675
676 default:
677 return CR_INVALID_PROPERTY;
678 }
679
680 Status = NtPlugPlayControl(PlugPlayControlProperty,
681 (PVOID)&PlugPlayData,
682 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
683 if (NT_SUCCESS(Status))
684 {
685 *pulLength = PlugPlayData.BufferSize;
686 }
687 else
688 {
689 ret = NtStatusToCrError(Status);
690 }
691 }
692
693 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
694
695 return ret;
696 }
697
698
699 /* Function 14 */
700 DWORD PNP_SetDeviceRegProp(
701 handle_t hBinding,
702 LPWSTR pDeviceId,
703 DWORD ulProperty,
704 DWORD ulDataType,
705 BYTE *Buffer,
706 PNP_PROP_SIZE ulLength,
707 DWORD ulFlags)
708 {
709 CONFIGRET ret = CR_SUCCESS;
710 LPWSTR lpValueName = NULL;
711 HKEY hKey = 0;
712
713 UNREFERENCED_PARAMETER(hBinding);
714 UNREFERENCED_PARAMETER(ulFlags);
715
716 DPRINT("PNP_SetDeviceRegProp() called\n");
717
718 DPRINT("DeviceId: %S\n", pDeviceId);
719 DPRINT("Property: %lu\n", ulProperty);
720 DPRINT("DataType: %lu\n", ulDataType);
721 DPRINT("Length: %lu\n", ulLength);
722
723 switch (ulProperty)
724 {
725 case CM_DRP_DEVICEDESC:
726 lpValueName = L"DeviceDesc";
727 break;
728
729 case CM_DRP_HARDWAREID:
730 lpValueName = L"HardwareID";
731 break;
732
733 case CM_DRP_COMPATIBLEIDS:
734 lpValueName = L"CompatibleIDs";
735 break;
736
737 case CM_DRP_SERVICE:
738 lpValueName = L"Service";
739 break;
740
741 case CM_DRP_CLASS:
742 lpValueName = L"Class";
743 break;
744
745 case CM_DRP_CLASSGUID:
746 lpValueName = L"ClassGUID";
747 break;
748
749 case CM_DRP_DRIVER:
750 lpValueName = L"Driver";
751 break;
752
753 case CM_DRP_CONFIGFLAGS:
754 lpValueName = L"ConfigFlags";
755 break;
756
757 case CM_DRP_MFG:
758 lpValueName = L"Mfg";
759 break;
760
761 case CM_DRP_FRIENDLYNAME:
762 lpValueName = L"FriendlyName";
763 break;
764
765 case CM_DRP_LOCATION_INFORMATION:
766 lpValueName = L"LocationInformation";
767 break;
768
769 case CM_DRP_UPPERFILTERS:
770 lpValueName = L"UpperFilters";
771 break;
772
773 case CM_DRP_LOWERFILTERS:
774 lpValueName = L"LowerFilters";
775 break;
776
777 default:
778 return CR_INVALID_PROPERTY;
779 }
780
781 DPRINT("Value name: %S\n", lpValueName);
782
783 if (RegOpenKeyExW(hEnumKey,
784 pDeviceId,
785 0,
786 KEY_ALL_ACCESS, /* FIXME: so much? */
787 &hKey))
788 return CR_INVALID_DEVNODE;
789
790 if (ulLength == 0)
791 {
792 if (RegDeleteValueW(hKey,
793 lpValueName))
794 ret = CR_REGISTRY_ERROR;
795 }
796 else
797 {
798 if (RegSetValueExW(hKey,
799 lpValueName,
800 0,
801 ulDataType,
802 Buffer,
803 ulLength))
804 ret = CR_REGISTRY_ERROR;
805 }
806
807 RegCloseKey(hKey);
808
809 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
810
811 return ret;
812 }
813
814
815 /* Function 15 */
816 DWORD PNP_GetClassInstance(
817 handle_t hBinding,
818 LPWSTR pDeviceId,
819 LPWSTR pszClassInstance,
820 PNP_RPC_STRING_LEN ulLength)
821 {
822 UNIMPLEMENTED;
823 return CR_CALL_NOT_IMPLEMENTED;
824 }
825
826
827 /* Function 16 */
828 DWORD PNP_CreateKey(
829 handle_t hBinding,
830 LPWSTR pszSubKey,
831 DWORD samDesired,
832 DWORD ulFlags)
833 {
834 UNIMPLEMENTED;
835 return CR_CALL_NOT_IMPLEMENTED;
836 }
837
838
839 /* Function 17 */
840 DWORD PNP_DeleteRegistryKey(
841 handle_t hBinding,
842 LPWSTR pszDeviceID,
843 LPWSTR pszParentKey,
844 LPWSTR pszChildKey,
845 DWORD ulFlags)
846 {
847 UNIMPLEMENTED;
848 return CR_CALL_NOT_IMPLEMENTED;
849 }
850
851
852 /* Function 18 */
853 DWORD PNP_GetClassCount(
854 handle_t hBinding,
855 DWORD *pulClassCount,
856 DWORD ulFlags)
857 {
858 HKEY hKey;
859 DWORD dwError;
860
861 UNREFERENCED_PARAMETER(hBinding);
862 UNREFERENCED_PARAMETER(ulFlags);
863
864 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
865 REGSTR_PATH_CLASS,
866 0,
867 KEY_QUERY_VALUE,
868 &hKey);
869 if (dwError != ERROR_SUCCESS)
870 return CR_INVALID_DATA;
871
872 dwError = RegQueryInfoKeyW(hKey,
873 NULL,
874 NULL,
875 NULL,
876 pulClassCount,
877 NULL,
878 NULL,
879 NULL,
880 NULL,
881 NULL,
882 NULL,
883 NULL);
884 RegCloseKey(hKey);
885 if (dwError != ERROR_SUCCESS)
886 return CR_INVALID_DATA;
887
888 return CR_SUCCESS;
889 }
890
891
892 /* Function 19 */
893 DWORD PNP_GetClassName(
894 handle_t hBinding,
895 LPWSTR pszClassGuid,
896 LPWSTR Buffer,
897 PNP_RPC_STRING_LEN *pulLength,
898 DWORD ulFlags)
899 {
900 WCHAR szKeyName[MAX_PATH];
901 CONFIGRET ret = CR_SUCCESS;
902 HKEY hKey;
903 DWORD dwSize;
904
905 UNREFERENCED_PARAMETER(hBinding);
906 UNREFERENCED_PARAMETER(ulFlags);
907
908 DPRINT("PNP_GetClassName() called\n");
909
910 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
911 if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
912 lstrcatW(szKeyName, pszClassGuid);
913 else return CR_INVALID_DATA;
914
915 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
916 szKeyName,
917 0,
918 KEY_QUERY_VALUE,
919 &hKey))
920 return CR_REGISTRY_ERROR;
921
922 dwSize = *pulLength * sizeof(WCHAR);
923 if (RegQueryValueExW(hKey,
924 L"Class",
925 NULL,
926 NULL,
927 (LPBYTE)Buffer,
928 &dwSize))
929 {
930 *pulLength = 0;
931 ret = CR_REGISTRY_ERROR;
932 }
933 else
934 {
935 *pulLength = dwSize / sizeof(WCHAR);
936 }
937
938 RegCloseKey(hKey);
939
940 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
941
942 return ret;
943 }
944
945
946 /* Function 20 */
947 DWORD PNP_DeleteClassKey(
948 handle_t hBinding,
949 LPWSTR pszClassGuid,
950 DWORD ulFlags)
951 {
952 CONFIGRET ret = CR_SUCCESS;
953
954 UNREFERENCED_PARAMETER(hBinding);
955
956 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
957
958 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
959 {
960 if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
961 ret = CR_REGISTRY_ERROR;
962 }
963 else
964 {
965 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
966 ret = CR_REGISTRY_ERROR;
967 }
968
969 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
970
971 return ret;
972 }
973
974
975 /* Function 21 */
976 DWORD PNP_GetInterfaceDeviceAlias(
977 handle_t hBinding,
978 LPWSTR pszInterfaceDevice,
979 GUID *AliasInterfaceGuid,
980 LPWSTR pszAliasInterfaceDevice,
981 PNP_RPC_STRING_LEN *pulLength,
982 PNP_RPC_STRING_LEN *pulTransferLen,
983 DWORD ulFlags)
984 {
985 UNIMPLEMENTED;
986 return CR_CALL_NOT_IMPLEMENTED;
987 }
988
989
990 /* Function 22 */
991 DWORD PNP_GetInterfaceDeviceList(
992 handle_t hBinding,
993 GUID *InterfaceGuid,
994 LPWSTR pszDeviceID,
995 BYTE *Buffer,
996 PNP_RPC_BUFFER_SIZE *pulLength,
997 DWORD ulFlags)
998 {
999 UNIMPLEMENTED;
1000 return CR_CALL_NOT_IMPLEMENTED;
1001 }
1002
1003
1004 /* Function 23 */
1005 DWORD PNP_GetInterfaceDeviceListSize(
1006 handle_t hBinding,
1007 PNP_RPC_BUFFER_SIZE *pulLen,
1008 GUID *InterfaceGuid,
1009 LPWSTR pszDeviceID,
1010 DWORD ulFlags)
1011 {
1012 UNIMPLEMENTED;
1013 return CR_CALL_NOT_IMPLEMENTED;
1014 }
1015
1016
1017 /* Function 24 */
1018 DWORD PNP_RegisterDeviceClassAssociation(
1019 handle_t hBinding,
1020 LPWSTR pszDeviceID,
1021 GUID *InterfaceGuid,
1022 LPWSTR pszReference,
1023 LPWSTR pszSymLink,
1024 PNP_RPC_STRING_LEN *pulLength,
1025 PNP_RPC_STRING_LEN *pulTransferLen,
1026 DWORD ulFlags)
1027 {
1028 UNIMPLEMENTED;
1029 return CR_CALL_NOT_IMPLEMENTED;
1030 }
1031
1032
1033 /* Function 25 */
1034 DWORD PNP_UnregisterDeviceClassAssociation(
1035 handle_t hBinding,
1036 LPWSTR pszInterfaceDevice,
1037 DWORD ulFlags)
1038 {
1039 UNIMPLEMENTED;
1040 return CR_CALL_NOT_IMPLEMENTED;
1041 }
1042
1043
1044 /* Function 26 */
1045 DWORD PNP_GetClassRegProp(
1046 handle_t hBinding,
1047 LPWSTR pszClassGuid,
1048 DWORD ulProperty,
1049 DWORD *pulRegDataType,
1050 BYTE *Buffer,
1051 PNP_RPC_STRING_LEN *pulTransferLen,
1052 PNP_RPC_STRING_LEN *pulLength,
1053 DWORD ulFlags)
1054 {
1055 UNIMPLEMENTED;
1056 return CR_CALL_NOT_IMPLEMENTED;
1057 }
1058
1059
1060 /* Function 27 */
1061 DWORD PNP_SetClassRegProp(
1062 handle_t hBinding,
1063 LPWSTR *pszClassGuid,
1064 DWORD ulProperty,
1065 DWORD ulDataType,
1066 BYTE *Buffer,
1067 PNP_PROP_SIZE ulLength,
1068 DWORD ulFlags)
1069 {
1070 UNIMPLEMENTED;
1071 return CR_CALL_NOT_IMPLEMENTED;
1072 }
1073
1074
1075 /* Function 28 */
1076 DWORD PNP_CreateDevInst(
1077 handle_t hBinding,
1078 LPWSTR pszDeviceID,
1079 LPWSTR pszParentDeviceID,
1080 PNP_RPC_STRING_LEN ulLength,
1081 DWORD ulFlags)
1082 {
1083 UNIMPLEMENTED;
1084 return CR_CALL_NOT_IMPLEMENTED;
1085 }
1086
1087
1088 /* Function 29 */
1089 #define PNP_DEVINST_SETUP 0x3
1090 #define PNP_DEVINST_ENABLE 0x4
1091 #define PNP_DEVINST_REENUMERATE 0x7
1092 DWORD PNP_DeviceInstanceAction(
1093 handle_t hBinding,
1094 DWORD ulMajorAction,
1095 DWORD ulMinorAction,
1096 LPWSTR pszDeviceInstance1,
1097 LPWSTR pszDeviceInstance2)
1098 {
1099 CONFIGRET ret = CR_SUCCESS;
1100 NTSTATUS Status;
1101
1102 UNREFERENCED_PARAMETER(hBinding);
1103 UNREFERENCED_PARAMETER(ulMinorAction);
1104 UNREFERENCED_PARAMETER(pszDeviceInstance2);
1105
1106 DPRINT("PNP_DeviceInstanceAction() called\n");
1107
1108 switch (ulMajorAction)
1109 {
1110 case PNP_DEVINST_SETUP:
1111 DPRINT("Setup device instance\n");
1112 /* FIXME */
1113 ret = CR_CALL_NOT_IMPLEMENTED;
1114 break;
1115
1116 case PNP_DEVINST_ENABLE:
1117 {
1118 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1119 DPRINT("Enable device instance\n");
1120 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance1);
1121 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1122 if (!NT_SUCCESS(Status))
1123 ret = NtStatusToCrError(Status);
1124 break;
1125 }
1126
1127 case PNP_DEVINST_REENUMERATE:
1128 DPRINT("Reenumerate device instance\n");
1129 /* FIXME */
1130 ret = CR_CALL_NOT_IMPLEMENTED;
1131 break;
1132
1133 default:
1134 DPRINT1("Unknown function %lu\n", ulMajorAction);
1135 ret = CR_CALL_NOT_IMPLEMENTED;
1136 }
1137
1138 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1139
1140 return ret;
1141 }
1142
1143
1144 /* Function 30 */
1145 DWORD PNP_GetDeviceStatus(
1146 handle_t hBinding,
1147 LPWSTR pDeviceID,
1148 DWORD *pulStatus,
1149 DWORD *pulProblem,
1150 DWORD ulFlags)
1151 {
1152 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1153 CONFIGRET ret = CR_SUCCESS;
1154 NTSTATUS Status;
1155
1156 UNREFERENCED_PARAMETER(hBinding);
1157 UNREFERENCED_PARAMETER(ulFlags);
1158
1159 DPRINT("PNP_GetDeviceStatus() called\n");
1160
1161 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1162 pDeviceID);
1163 PlugPlayData.Operation = 0; /* Get status */
1164
1165 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1166 (PVOID)&PlugPlayData,
1167 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1168 if (NT_SUCCESS(Status))
1169 {
1170 *pulStatus = PlugPlayData.DeviceStatus;
1171 *pulProblem = PlugPlayData.DeviceProblem;
1172 }
1173 else
1174 {
1175 ret = NtStatusToCrError(Status);
1176 }
1177
1178 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1179
1180 return ret;
1181 }
1182
1183
1184 /* Function 31 */
1185 DWORD PNP_SetDeviceProblem(
1186 handle_t hBinding,
1187 LPWSTR pDeviceID,
1188 DWORD ulProblem,
1189 DWORD ulFlags)
1190 {
1191 UNIMPLEMENTED;
1192 return CR_CALL_NOT_IMPLEMENTED;
1193 }
1194
1195
1196 /* Function 32 */
1197 DWORD PNP_DisableDevInst(
1198 handle_t hBinding,
1199 LPWSTR pDeviceID,
1200 PPNP_VETO_TYPE pVetoType,
1201 LPWSTR pszVetoName,
1202 DWORD ulNameLength,
1203 DWORD ulFlags)
1204 {
1205 UNIMPLEMENTED;
1206 return CR_CALL_NOT_IMPLEMENTED;
1207 }
1208
1209 /* Function 33 */
1210 DWORD PNP_UninstallDevInst(
1211 handle_t hBinding,
1212 LPWSTR pDeviceID,
1213 DWORD ulFlags)
1214 {
1215 UNIMPLEMENTED;
1216 return CR_CALL_NOT_IMPLEMENTED;
1217 }
1218
1219
1220 static BOOL
1221 CheckForDeviceId(LPWSTR lpDeviceIdList,
1222 LPWSTR lpDeviceId)
1223 {
1224 LPWSTR lpPtr;
1225 DWORD dwLength;
1226
1227 lpPtr = lpDeviceIdList;
1228 while (*lpPtr != 0)
1229 {
1230 dwLength = wcslen(lpPtr);
1231 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1232 return TRUE;
1233
1234 lpPtr += (dwLength + 1);
1235 }
1236
1237 return FALSE;
1238 }
1239
1240
1241 static VOID
1242 AppendDeviceId(LPWSTR lpDeviceIdList,
1243 LPDWORD lpDeviceIdListSize,
1244 LPWSTR lpDeviceId)
1245 {
1246 DWORD dwLen;
1247 DWORD dwPos;
1248
1249 dwLen = wcslen(lpDeviceId);
1250 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1251
1252 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1253
1254 dwPos += (dwLen + 1);
1255
1256 lpDeviceIdList[dwPos] = 0;
1257
1258 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1259 }
1260
1261
1262 /* Function 34 */
1263 DWORD PNP_AddID(
1264 handle_t hBinding,
1265 LPWSTR pszDeviceID,
1266 LPWSTR pszID,
1267 DWORD ulFlags)
1268 {
1269 CONFIGRET ret = CR_SUCCESS;
1270 HKEY hDeviceKey;
1271 LPWSTR pszSubKey;
1272 DWORD dwDeviceIdListSize;
1273 DWORD dwNewDeviceIdSize;
1274 WCHAR * pszDeviceIdList = NULL;
1275
1276 UNREFERENCED_PARAMETER(hBinding);
1277
1278 DPRINT("PNP_AddID() called\n");
1279 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1280 DPRINT(" DeviceId: %S\n", pszID);
1281 DPRINT(" Flags: %lx\n", ulFlags);
1282
1283 if (RegOpenKeyExW(hEnumKey,
1284 pszDeviceID,
1285 0,
1286 KEY_QUERY_VALUE | KEY_SET_VALUE,
1287 &hDeviceKey) != ERROR_SUCCESS)
1288 {
1289 DPRINT("Failed to open the device key!\n");
1290 return CR_INVALID_DEVNODE;
1291 }
1292
1293 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1294
1295 if (RegQueryValueExW(hDeviceKey,
1296 pszSubKey,
1297 NULL,
1298 NULL,
1299 NULL,
1300 &dwDeviceIdListSize) != ERROR_SUCCESS)
1301 {
1302 DPRINT("Failed to query the desired ID string!\n");
1303 ret = CR_REGISTRY_ERROR;
1304 goto Done;
1305 }
1306
1307 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1308 if (!dwNewDeviceIdSize)
1309 {
1310 ret = CR_INVALID_POINTER;
1311 goto Done;
1312 }
1313
1314 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1315
1316 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1317 if (!pszDeviceIdList)
1318 {
1319 DPRINT("Failed to allocate memory for the desired ID string!\n");
1320 ret = CR_OUT_OF_MEMORY;
1321 goto Done;
1322 }
1323
1324 if (RegQueryValueExW(hDeviceKey,
1325 pszSubKey,
1326 NULL,
1327 NULL,
1328 (LPBYTE)pszDeviceIdList,
1329 &dwDeviceIdListSize) != ERROR_SUCCESS)
1330 {
1331 DPRINT("Failed to query the desired ID string!\n");
1332 ret = CR_REGISTRY_ERROR;
1333 goto Done;
1334 }
1335
1336 /* Check whether the device ID is already in use */
1337 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1338 {
1339 DPRINT("Device ID was found in the ID string!\n");
1340 ret = CR_SUCCESS;
1341 goto Done;
1342 }
1343
1344 /* Append the Device ID */
1345 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1346
1347 if (RegSetValueExW(hDeviceKey,
1348 pszSubKey,
1349 0,
1350 REG_MULTI_SZ,
1351 (LPBYTE)pszDeviceIdList,
1352 dwDeviceIdListSize) != ERROR_SUCCESS)
1353 {
1354 DPRINT("Failed to set the desired ID string!\n");
1355 ret = CR_REGISTRY_ERROR;
1356 }
1357
1358 Done:
1359 RegCloseKey(hDeviceKey);
1360 if (pszDeviceIdList)
1361 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1362
1363 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1364
1365 return ret;
1366 }
1367
1368
1369 /* Function 35 */
1370 DWORD PNP_RegisterDriver(
1371 handle_t hBinding,
1372 LPWSTR pszDeviceID,
1373 DWORD ulFlags)
1374 {
1375 UNIMPLEMENTED;
1376 return CR_CALL_NOT_IMPLEMENTED;
1377 }
1378
1379
1380 /* Function 36 */
1381 DWORD PNP_QueryRemove(
1382 handle_t hBinding,
1383 LPWSTR pszDeviceID,
1384 PPNP_VETO_TYPE pVetoType,
1385 LPWSTR pszVetoName,
1386 DWORD ulNameLength,
1387 DWORD ulFlags)
1388 {
1389 UNIMPLEMENTED;
1390 return CR_CALL_NOT_IMPLEMENTED;
1391 }
1392
1393
1394 /* Function 37 */
1395 DWORD PNP_RequestDeviceEject(
1396 handle_t hBinding,
1397 LPWSTR pszDeviceID,
1398 PPNP_VETO_TYPE pVetoType,
1399 LPWSTR pszVetoName,
1400 DWORD ulNameLength,
1401 DWORD ulFlags)
1402 {
1403 UNIMPLEMENTED;
1404 return CR_CALL_NOT_IMPLEMENTED;
1405 }
1406
1407 /* Function 38 */
1408 CONFIGRET
1409 PNP_IsDockStationPresent(handle_t hBinding,
1410 BOOL *Present)
1411 {
1412 HKEY hKey;
1413 DWORD dwType;
1414 DWORD dwValue;
1415 DWORD dwSize;
1416 CONFIGRET ret = CR_SUCCESS;
1417
1418 UNREFERENCED_PARAMETER(hBinding);
1419
1420 DPRINT1("PNP_IsDockStationPresent() called\n");
1421
1422 *Present = FALSE;
1423
1424 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1425 L"CurrentDockInfo",
1426 0,
1427 KEY_READ,
1428 &hKey) != ERROR_SUCCESS)
1429 return CR_REGISTRY_ERROR;
1430
1431 dwSize = sizeof(DWORD);
1432 if (RegQueryValueExW(hKey,
1433 L"DockingState",
1434 NULL,
1435 &dwType,
1436 (LPBYTE)&dwValue,
1437 &dwSize) != ERROR_SUCCESS)
1438 ret = CR_REGISTRY_ERROR;
1439
1440 RegCloseKey(hKey);
1441
1442 if (ret == CR_SUCCESS)
1443 {
1444 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1445 {
1446 ret = CR_REGISTRY_ERROR;
1447 }
1448 else if (dwValue != 0)
1449 {
1450 *Present = TRUE;
1451 }
1452 }
1453
1454 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1455
1456 return ret;
1457 }
1458
1459
1460 /* Function 39 */
1461 DWORD PNP_RequestEjectPC(
1462 handle_t hBinding)
1463 {
1464 UNIMPLEMENTED;
1465 return CR_CALL_NOT_IMPLEMENTED;
1466 }
1467
1468
1469 /* Function 40 */
1470 DWORD PNP_HwProfFlags(
1471 handle_t hBinding,
1472 DWORD ulAction,
1473 LPWSTR pDeviceID,
1474 DWORD ulConfig,
1475 DWORD *pulValue,
1476 PPNP_VETO_TYPE pVetoType,
1477 LPWSTR pszVetoName,
1478 DWORD ulNameLength,
1479 DWORD ulFlags)
1480 {
1481 UNIMPLEMENTED;
1482 return CR_CALL_NOT_IMPLEMENTED;
1483 }
1484
1485
1486 /* Function 41 */
1487 DWORD PNP_GetHwProfInfo(
1488 handle_t hBinding,
1489 DWORD ulIndex,
1490 HWPROFILEINFO *pHWProfileInfo,
1491 DWORD ulProfileInfoSize,
1492 DWORD ulFlags)
1493 {
1494 UNIMPLEMENTED;
1495 return CR_CALL_NOT_IMPLEMENTED;
1496 }
1497
1498
1499 /* Function 42 */
1500 DWORD PNP_AddEmptyLogConf(
1501 handle_t hBinding,
1502 LPWSTR pDeviceID,
1503 DWORD ulPriority,
1504 DWORD *pulLogConfTag,
1505 DWORD ulFlags)
1506 {
1507 UNIMPLEMENTED;
1508 return CR_CALL_NOT_IMPLEMENTED;
1509 }
1510
1511
1512 /* Function 43 */
1513 DWORD PNP_FreeLogConf(
1514 handle_t hBinding,
1515 LPWSTR pDeviceID,
1516 DWORD ulLogConfType,
1517 DWORD ulLogConfTag,
1518 DWORD ulFlags)
1519 {
1520 UNIMPLEMENTED;
1521 return CR_CALL_NOT_IMPLEMENTED;
1522 }
1523
1524
1525 /* Function 44 */
1526 DWORD PNP_GetFirstLogConf(
1527 handle_t hBinding,
1528 LPWSTR pDeviceID,
1529 DWORD ulLogConfType,
1530 DWORD *pulLogConfTag,
1531 DWORD ulFlags)
1532 {
1533 UNIMPLEMENTED;
1534 return CR_CALL_NOT_IMPLEMENTED;
1535 }
1536
1537
1538 /* Function 45 */
1539 DWORD PNP_GetNextLogConf(
1540 handle_t hBinding,
1541 LPWSTR pDeviceID,
1542 DWORD ulLogConfType,
1543 DWORD ulCurrentTag,
1544 DWORD *pulNextTag,
1545 DWORD ulFlags)
1546 {
1547 UNIMPLEMENTED;
1548 return CR_CALL_NOT_IMPLEMENTED;
1549 }
1550
1551
1552 /* Function 46 */
1553 DWORD PNP_GetLogConfPriority(
1554 handle_t hBinding,
1555 LPWSTR pDeviceID,
1556 DWORD ulType,
1557 DWORD ulTag,
1558 DWORD *pPriority,
1559 DWORD ulFlags)
1560 {
1561 UNIMPLEMENTED;
1562 return CR_CALL_NOT_IMPLEMENTED;
1563 }
1564
1565
1566 /* Function 47 */
1567 DWORD PNP_AddResDes(
1568 handle_t hBinding,
1569 LPWSTR pDeviceID,
1570 DWORD ulLogConfTag,
1571 DWORD ulLogConfType,
1572 RESOURCEID ResourceID,
1573 DWORD *pulResourceTag,
1574 BYTE *ResourceData,
1575 PNP_RPC_BUFFER_SIZE ResourceLen,
1576 DWORD ulFlags)
1577 {
1578 UNIMPLEMENTED;
1579 return CR_CALL_NOT_IMPLEMENTED;
1580 }
1581
1582
1583 /* Function 48 */
1584 DWORD PNP_FreeResDes(
1585 handle_t hBinding,
1586 LPWSTR pDeviceID,
1587 DWORD ulLogConfTag,
1588 DWORD ulLogConfType,
1589 RESOURCEID ResourceID,
1590 DWORD ulResourceTag,
1591 DWORD *pulPreviousResType,
1592 DWORD *pulPreviousResTag,
1593 DWORD ulFlags)
1594 {
1595 UNIMPLEMENTED;
1596 return CR_CALL_NOT_IMPLEMENTED;
1597 }
1598
1599
1600 /* Function 49 */
1601 DWORD PNP_GetNextResDes(
1602 handle_t hBinding,
1603 LPWSTR pDeviceID,
1604 DWORD ulLogConfTag,
1605 DWORD ulLogConfType,
1606 RESOURCEID ResourceID,
1607 DWORD ulResourceTag,
1608 DWORD *pulNextResType,
1609 DWORD *pulNextResTag,
1610 DWORD ulFlags)
1611 {
1612 UNIMPLEMENTED;
1613 return CR_CALL_NOT_IMPLEMENTED;
1614 }
1615
1616
1617 /* Function 50 */
1618 DWORD PNP_GetResDesData(
1619 handle_t hBinding,
1620 LPWSTR pDeviceID,
1621 DWORD ulLogConfTag,
1622 DWORD ulLogConfType,
1623 RESOURCEID ResourceID,
1624 DWORD ulResourceTag,
1625 BYTE *Buffer,
1626 PNP_RPC_BUFFER_SIZE BufferLen,
1627 DWORD ulFlags)
1628 {
1629 UNIMPLEMENTED;
1630 return CR_CALL_NOT_IMPLEMENTED;
1631 }
1632
1633
1634 /* Function 51 */
1635 DWORD PNP_GetResDesDataSize(
1636 handle_t hBinding,
1637 LPWSTR pDeviceID,
1638 DWORD ulLogConfTag,
1639 DWORD ulLogConfType,
1640 RESOURCEID ResourceID,
1641 DWORD ulResourceTag,
1642 DWORD *pulSize,
1643 DWORD ulFlags)
1644 {
1645 UNIMPLEMENTED;
1646 return CR_CALL_NOT_IMPLEMENTED;
1647 }
1648
1649
1650 /* Function 52 */
1651 DWORD PNP_ModifyResDes(
1652 handle_t hBinding,
1653 LPWSTR pDeviceID,
1654 DWORD ulLogConfTag,
1655 DWORD ulLogConfType,
1656 RESOURCEID CurrentResourceID,
1657 RESOURCEID NewResourceID,
1658 DWORD ulResourceTag,
1659 BYTE *ResourceData,
1660 PNP_RPC_BUFFER_SIZE ResourceLen,
1661 DWORD ulFlags)
1662 {
1663 UNIMPLEMENTED;
1664 return CR_CALL_NOT_IMPLEMENTED;
1665 }
1666
1667
1668 /* Function 53 */
1669 DWORD PNP_DetectResourceConflict(
1670 handle_t hBinding,
1671 LPWSTR pDeviceID,
1672 RESOURCEID ResourceID,
1673 BYTE *ResourceData,
1674 PNP_RPC_BUFFER_SIZE ResourceLen,
1675 BOOL *pbConflictDetected,
1676 DWORD ulFlags)
1677 {
1678 UNIMPLEMENTED;
1679 return CR_CALL_NOT_IMPLEMENTED;
1680 }
1681
1682
1683 /* Function 54 */
1684 DWORD PNP_QueryResConfList(
1685 handle_t hBinding,
1686 LPWSTR pDeviceID,
1687 RESOURCEID ResourceID,
1688 BYTE *ResourceData,
1689 PNP_RPC_BUFFER_SIZE ResourceLen,
1690 BYTE *Buffer,
1691 PNP_RPC_BUFFER_SIZE BufferLen,
1692 DWORD ulFlags)
1693 {
1694 UNIMPLEMENTED;
1695 return CR_CALL_NOT_IMPLEMENTED;
1696 }
1697
1698
1699 /* Function 55 */
1700 DWORD PNP_SetHwProf(
1701 handle_t hBinding)
1702 {
1703 UNIMPLEMENTED;
1704 return CR_CALL_NOT_IMPLEMENTED;
1705 }
1706
1707
1708 /* Function 56 */
1709 DWORD PNP_QueryArbitratorFreeData(
1710 handle_t hBinding)
1711 {
1712 UNIMPLEMENTED;
1713 return CR_CALL_NOT_IMPLEMENTED;
1714 }
1715
1716
1717 /* Function 57 */
1718 DWORD PNP_QueryArbitratorFreeSize(
1719 handle_t hBinding)
1720 {
1721 UNIMPLEMENTED;
1722 return CR_CALL_NOT_IMPLEMENTED;
1723 }
1724
1725
1726 /* Function 58 */
1727 CONFIGRET
1728 PNP_RunDetection(
1729 handle_t hBinding,
1730 DWORD ulFlags)
1731 {
1732 UNIMPLEMENTED;
1733 return CR_CALL_NOT_IMPLEMENTED;
1734 }
1735
1736
1737 /* Function 59 */
1738 DWORD PNP_RegisterNotification(
1739 handle_t hBinding)
1740 {
1741 UNIMPLEMENTED;
1742 return CR_CALL_NOT_IMPLEMENTED;
1743 }
1744
1745
1746 /* Function 60 */
1747 DWORD PNP_UnregisterNotification(
1748 handle_t hBinding)
1749 {
1750 UNIMPLEMENTED;
1751 return CR_CALL_NOT_IMPLEMENTED;
1752 }
1753
1754
1755 /* Function 61 */
1756 DWORD PNP_GetCustomDevProp(
1757 handle_t hBinding,
1758 LPWSTR pDeviceID,
1759 LPWSTR CustomPropName,
1760 DWORD *pulRegDataType,
1761 BYTE *Buffer,
1762 PNP_RPC_STRING_LEN *pulTransferLen,
1763 PNP_RPC_STRING_LEN *pulLength,
1764 DWORD ulFlags)
1765 {
1766 UNIMPLEMENTED;
1767 return CR_CALL_NOT_IMPLEMENTED;
1768 }
1769
1770
1771 /* Function 62 */
1772 DWORD PNP_GetVersionInternal(
1773 handle_t hBinding,
1774 WORD *pwVersion)
1775 {
1776 UNIMPLEMENTED;
1777 return CR_CALL_NOT_IMPLEMENTED;
1778 }
1779
1780
1781 /* Function 63 */
1782 DWORD PNP_GetBlockedDriverInfo(
1783 handle_t hBinding,
1784 BYTE *Buffer,
1785 PNP_RPC_BUFFER_SIZE *pulTransferLen,
1786 PNP_RPC_BUFFER_SIZE *pulLength,
1787 DWORD ulFlags)
1788 {
1789 UNIMPLEMENTED;
1790 return CR_CALL_NOT_IMPLEMENTED;
1791 }
1792
1793
1794 /* Function 64 */
1795 DWORD PNP_GetServerSideDeviceInstallFlags(
1796 handle_t hBinding,
1797 DWORD *pulSSDIFlags,
1798 DWORD ulFlags)
1799 {
1800 UNIMPLEMENTED;
1801 return CR_CALL_NOT_IMPLEMENTED;
1802 }
1803
1804
1805 /* Function 65 */
1806 DWORD PNP_GetObjectPropKeys(
1807 handle_t hBinding,
1808 LPWSTR ObjectName,
1809 DWORD ObjectType,
1810 LPWSTR PropertyCultureName,
1811 PNP_PROP_COUNT *PropertyCount,
1812 PNP_PROP_COUNT *TransferLen,
1813 DEVPROPKEY *PropertyKeys,
1814 DWORD Flags)
1815 {
1816 UNIMPLEMENTED;
1817 return CR_CALL_NOT_IMPLEMENTED;
1818 }
1819
1820
1821 /* Function 66 */
1822 DWORD PNP_GetObjectProp(
1823 handle_t hBinding,
1824 LPWSTR ObjectName,
1825 DWORD ObjectType,
1826 LPWSTR PropertyCultureName,
1827 const DEVPROPKEY *PropertyKey,
1828 DEVPROPTYPE *PropertyType,
1829 PNP_PROP_SIZE *PropertySize,
1830 PNP_PROP_SIZE *TransferLen,
1831 BYTE *PropertyBuffer,
1832 DWORD Flags)
1833 {
1834 UNIMPLEMENTED;
1835 return CR_CALL_NOT_IMPLEMENTED;
1836 }
1837
1838
1839 /* Function 67 */
1840 DWORD PNP_SetObjectProp(
1841 handle_t hBinding,
1842 LPWSTR ObjectName,
1843 DWORD ObjectType,
1844 LPWSTR PropertyCultureName,
1845 const DEVPROPKEY *PropertyKey,
1846 DEVPROPTYPE PropertyType,
1847 PNP_PROP_SIZE PropertySize,
1848 BYTE *PropertyBuffer,
1849 DWORD Flags)
1850 {
1851 UNIMPLEMENTED;
1852 return CR_CALL_NOT_IMPLEMENTED;
1853 }
1854
1855
1856 /* Function 68 */
1857 DWORD PNP_InstallDevInst(
1858 handle_t hBinding)
1859 {
1860 UNIMPLEMENTED;
1861 return CR_CALL_NOT_IMPLEMENTED;
1862 }
1863
1864
1865 /* Function 69 */
1866 DWORD PNP_ApplyPowerSettings(
1867 handle_t hBinding)
1868 {
1869 UNIMPLEMENTED;
1870 return CR_CALL_NOT_IMPLEMENTED;
1871 }
1872
1873
1874 /* Function 70 */
1875 DWORD PNP_DriverStoreAddDriverPackage(
1876 handle_t hBinding)
1877 {
1878 UNIMPLEMENTED;
1879 return CR_CALL_NOT_IMPLEMENTED;
1880 }
1881
1882
1883 /* Function 71 */
1884 DWORD PNP_DriverStoreDeleteDriverPackage(
1885 handle_t hBinding)
1886 {
1887 UNIMPLEMENTED;
1888 return CR_CALL_NOT_IMPLEMENTED;
1889 }
1890
1891
1892 /* Function 72 */
1893 DWORD PNP_RegisterServiceNotification(
1894 handle_t hBinding)
1895 {
1896 UNIMPLEMENTED;
1897 return CR_CALL_NOT_IMPLEMENTED;
1898 }
1899
1900
1901 /* Function 73 */
1902 DWORD PNP_SetActiveService(
1903 handle_t hBinding)
1904 {
1905 UNIMPLEMENTED;
1906 return CR_CALL_NOT_IMPLEMENTED;
1907 }
1908
1909
1910 /* Function 74 */
1911 DWORD PNP_DeleteServiceDevices(
1912 handle_t hBinding)
1913 {
1914 UNIMPLEMENTED;
1915 return CR_CALL_NOT_IMPLEMENTED;
1916 }
1917
1918
1919 static BOOL
1920 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
1921 {
1922 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1923 NTSTATUS Status;
1924 BOOL DeviceInstalled = FALSE;
1925 DWORD BytesWritten;
1926 DWORD Value;
1927 HANDLE hPipe = INVALID_HANDLE_VALUE;
1928 LPVOID Environment = NULL;
1929 PROCESS_INFORMATION ProcessInfo;
1930 STARTUPINFOW StartupInfo;
1931 UUID RandomUuid;
1932
1933 /* The following lengths are constant (see below), they cannot overflow */
1934 WCHAR CommandLine[116];
1935 WCHAR InstallEventName[73];
1936 WCHAR PipeName[74];
1937 WCHAR UuidString[39];
1938
1939 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
1940
1941 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
1942
1943 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1944 DeviceInstance);
1945 PlugPlayData.Operation = 0; /* Get status */
1946
1947 /* Get device status */
1948 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1949 (PVOID)&PlugPlayData,
1950 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1951 if (!NT_SUCCESS(Status))
1952 {
1953 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status);
1954 return FALSE;
1955 }
1956
1957 if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
1958 {
1959 /* Device is already started, or disabled due to some problem. Don't install it */
1960 DPRINT("No need to install '%S'\n", DeviceInstance);
1961 return TRUE;
1962 }
1963
1964 /* Create a random UUID for the named pipe */
1965 UuidCreate(&RandomUuid);
1966 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
1967 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
1968 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
1969 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
1970 RandomUuid.Data4[6], RandomUuid.Data4[7]);
1971
1972 /* Create the named pipe */
1973 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
1974 wcscat(PipeName, UuidString);
1975 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
1976
1977 if(hPipe == INVALID_HANDLE_VALUE)
1978 {
1979 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
1980 goto cleanup;
1981 }
1982
1983 /* Launch rundll32 to call ClientSideInstallW */
1984 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
1985 wcscat(CommandLine, PipeName);
1986
1987 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
1988 StartupInfo.cb = sizeof(StartupInfo);
1989
1990 if(hUserToken)
1991 {
1992 /* newdev has to run under the environment of the current user */
1993 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
1994 {
1995 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
1996 goto cleanup;
1997 }
1998
1999 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
2000 {
2001 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2002 goto cleanup;
2003 }
2004 }
2005 else
2006 {
2007 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2008
2009 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2010 (ShowWizard is only set to FALSE for these two modes) */
2011 ASSERT(!ShowWizard);
2012
2013 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2014 {
2015 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2016 goto cleanup;
2017 }
2018 }
2019
2020 /* Wait for the function to connect to our pipe */
2021 if(!ConnectNamedPipe(hPipe, NULL))
2022 {
2023 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2024 goto cleanup;
2025 }
2026
2027 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2028 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2029 wcscat(InstallEventName, UuidString);
2030
2031 Value = sizeof(InstallEventName);
2032 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2033 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2034
2035 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2036 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2037 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2038
2039 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2040 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2041 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2042
2043 /* Wait for newdev.dll to finish processing */
2044 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2045
2046 /* The following check for success is probably not compatible to Windows, but should do its job */
2047 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2048 {
2049 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2050 goto cleanup;
2051 }
2052
2053 DeviceInstalled = Value;
2054
2055 cleanup:
2056 if(hPipe != INVALID_HANDLE_VALUE)
2057 CloseHandle(hPipe);
2058
2059 if(Environment)
2060 DestroyEnvironmentBlock(Environment);
2061
2062 if(ProcessInfo.hProcess)
2063 CloseHandle(ProcessInfo.hProcess);
2064
2065 if(ProcessInfo.hThread)
2066 CloseHandle(ProcessInfo.hThread);
2067
2068 return DeviceInstalled;
2069 }
2070
2071
2072 static LONG
2073 ReadRegSzKey(
2074 IN HKEY hKey,
2075 IN LPCWSTR pszKey,
2076 OUT LPWSTR* pValue)
2077 {
2078 LONG rc;
2079 DWORD dwType;
2080 DWORD cbData = 0;
2081 LPWSTR Value;
2082
2083 if (!pValue)
2084 return ERROR_INVALID_PARAMETER;
2085
2086 *pValue = NULL;
2087 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2088 if (rc != ERROR_SUCCESS)
2089 return rc;
2090 if (dwType != REG_SZ)
2091 return ERROR_FILE_NOT_FOUND;
2092 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2093 if (!Value)
2094 return ERROR_NOT_ENOUGH_MEMORY;
2095 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2096 if (rc != ERROR_SUCCESS)
2097 {
2098 HeapFree(GetProcessHeap(), 0, Value);
2099 return rc;
2100 }
2101 /* NULL-terminate the string */
2102 Value[cbData / sizeof(WCHAR)] = '\0';
2103
2104 *pValue = Value;
2105 return ERROR_SUCCESS;
2106 }
2107
2108
2109 static BOOL
2110 SetupIsActive(VOID)
2111 {
2112 HKEY hKey = NULL;
2113 DWORD regType, active, size;
2114 LONG rc;
2115 BOOL ret = FALSE;
2116
2117 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2118 if (rc != ERROR_SUCCESS)
2119 goto cleanup;
2120
2121 size = sizeof(DWORD);
2122 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2123 if (rc != ERROR_SUCCESS)
2124 goto cleanup;
2125 if (regType != REG_DWORD || size != sizeof(DWORD))
2126 goto cleanup;
2127
2128 ret = (active != 0);
2129
2130 cleanup:
2131 if (hKey != NULL)
2132 RegCloseKey(hKey);
2133
2134 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2135
2136 return ret;
2137 }
2138
2139
2140 static BOOL
2141 IsConsoleBoot(VOID)
2142 {
2143 HKEY ControlKey = NULL;
2144 LPWSTR SystemStartOptions = NULL;
2145 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2146 BOOL ConsoleBoot = FALSE;
2147 LONG rc;
2148
2149 rc = RegOpenKeyExW(
2150 HKEY_LOCAL_MACHINE,
2151 L"SYSTEM\\CurrentControlSet\\Control",
2152 0,
2153 KEY_QUERY_VALUE,
2154 &ControlKey);
2155
2156 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2157 if (rc != ERROR_SUCCESS)
2158 goto cleanup;
2159
2160 /* Check for CMDCONS in SystemStartOptions */
2161 CurrentOption = SystemStartOptions;
2162 while (CurrentOption)
2163 {
2164 NextOption = wcschr(CurrentOption, L' ');
2165 if (NextOption)
2166 *NextOption = L'\0';
2167 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2168 {
2169 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2170 ConsoleBoot = TRUE;
2171 goto cleanup;
2172 }
2173 CurrentOption = NextOption ? NextOption + 1 : NULL;
2174 }
2175
2176 cleanup:
2177 if (ControlKey != NULL)
2178 RegCloseKey(ControlKey);
2179 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2180 return ConsoleBoot;
2181 }
2182
2183
2184 /* Loop to install all queued devices installations */
2185 static DWORD WINAPI
2186 DeviceInstallThread(LPVOID lpParameter)
2187 {
2188 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2189 PSLIST_ENTRY ListEntry;
2190 #else
2191 PLIST_ENTRY ListEntry;
2192 #endif
2193 DeviceInstallParams* Params;
2194 BOOL showWizard;
2195
2196 UNREFERENCED_PARAMETER(lpParameter);
2197
2198 WaitForSingleObject(hInstallEvent, INFINITE);
2199
2200 showWizard = !SetupIsActive() && !IsConsoleBoot();
2201
2202 while (TRUE)
2203 {
2204 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2205 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2206 #else
2207 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2208 ListEntry = NULL;
2209 else
2210 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2211 #endif
2212 if (ListEntry == NULL)
2213 {
2214 SetEvent(hNoPendingInstalls);
2215 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2216 }
2217 else
2218 {
2219 ResetEvent(hNoPendingInstalls);
2220 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2221 InstallDevice(Params->DeviceIds, showWizard);
2222 }
2223 }
2224
2225 return 0;
2226 }
2227
2228
2229 static DWORD WINAPI
2230 PnpEventThread(LPVOID lpParameter)
2231 {
2232 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2233 ULONG PnpEventSize;
2234 NTSTATUS Status;
2235 RPC_STATUS RpcStatus;
2236
2237 UNREFERENCED_PARAMETER(lpParameter);
2238
2239 PnpEventSize = 0x1000;
2240 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2241 if (PnpEvent == NULL)
2242 return ERROR_OUTOFMEMORY;
2243
2244 for (;;)
2245 {
2246 DPRINT("Calling NtGetPlugPlayEvent()\n");
2247
2248 /* Wait for the next pnp event */
2249 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2250
2251 /* Resize the buffer for the PnP event if it's too small. */
2252 if (Status == STATUS_BUFFER_TOO_SMALL)
2253 {
2254 PnpEventSize += 0x400;
2255 HeapFree(GetProcessHeap(), 0, PnpEvent);
2256 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2257 if (PnpEvent == NULL)
2258 return ERROR_OUTOFMEMORY;
2259 continue;
2260 }
2261
2262 if (!NT_SUCCESS(Status))
2263 {
2264 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2265 break;
2266 }
2267
2268 /* Process the pnp event */
2269 DPRINT("Received PnP Event\n");
2270 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2271 {
2272 DeviceInstallParams* Params;
2273 DWORD len;
2274 DWORD DeviceIdLength;
2275
2276 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
2277
2278 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2279 if (DeviceIdLength)
2280 {
2281 /* Queue device install (will be dequeued by DeviceInstallThread */
2282 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2283 Params = HeapAlloc(GetProcessHeap(), 0, len);
2284 if (Params)
2285 {
2286 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2287 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2288 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2289 #else
2290 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2291 #endif
2292 SetEvent(hDeviceInstallListNotEmpty);
2293 }
2294 }
2295 }
2296 else
2297 {
2298 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2299 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2300 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2301 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2302 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2303 }
2304
2305 /* Dequeue the current pnp event and signal the next one */
2306 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
2307 }
2308
2309 HeapFree(GetProcessHeap(), 0, PnpEvent);
2310
2311 return ERROR_SUCCESS;
2312 }
2313
2314
2315 static VOID CALLBACK
2316 ServiceMain(DWORD argc, LPTSTR *argv)
2317 {
2318 HANDLE hThread;
2319 DWORD dwThreadId;
2320
2321 UNREFERENCED_PARAMETER(argc);
2322 UNREFERENCED_PARAMETER(argv);
2323
2324 DPRINT("ServiceMain() called\n");
2325
2326 hThread = CreateThread(NULL,
2327 0,
2328 PnpEventThread,
2329 NULL,
2330 0,
2331 &dwThreadId);
2332 if (hThread != NULL)
2333 CloseHandle(hThread);
2334
2335 hThread = CreateThread(NULL,
2336 0,
2337 RpcServerThread,
2338 NULL,
2339 0,
2340 &dwThreadId);
2341 if (hThread != NULL)
2342 CloseHandle(hThread);
2343
2344 hThread = CreateThread(NULL,
2345 0,
2346 DeviceInstallThread,
2347 NULL,
2348 0,
2349 &dwThreadId);
2350 if (hThread != NULL)
2351 CloseHandle(hThread);
2352
2353 DPRINT("ServiceMain() done\n");
2354 }
2355
2356
2357 int
2358 wmain(int argc, WCHAR *argv[])
2359 {
2360 BOOLEAN OldValue;
2361 DWORD dwError;
2362
2363 UNREFERENCED_PARAMETER(argc);
2364 UNREFERENCED_PARAMETER(argv);
2365
2366 DPRINT("Umpnpmgr: main() started\n");
2367
2368 /* We need this privilege for using CreateProcessAsUserW */
2369 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
2370
2371 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
2372 if (hInstallEvent == NULL)
2373 {
2374 dwError = GetLastError();
2375 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
2376 return dwError;
2377 }
2378
2379 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
2380 if (hDeviceInstallListNotEmpty == NULL)
2381 {
2382 dwError = GetLastError();
2383 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2384 return dwError;
2385 }
2386
2387 hNoPendingInstalls = CreateEventW(NULL,
2388 TRUE,
2389 FALSE,
2390 L"Global\\PnP_No_Pending_Install_Events");
2391 if (hNoPendingInstalls == NULL)
2392 {
2393 dwError = GetLastError();
2394 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2395 return dwError;
2396 }
2397
2398 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2399 InitializeSListHead(&DeviceInstallListHead);
2400 #else
2401 InitializeListHead(&DeviceInstallListHead);
2402 #endif
2403
2404 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2405 L"System\\CurrentControlSet\\Enum",
2406 0,
2407 KEY_ALL_ACCESS,
2408 &hEnumKey);
2409 if (dwError != ERROR_SUCCESS)
2410 {
2411 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
2412 return dwError;
2413 }
2414
2415 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2416 L"System\\CurrentControlSet\\Control\\Class",
2417 0,
2418 KEY_ALL_ACCESS,
2419 &hClassKey);
2420 if (dwError != ERROR_SUCCESS)
2421 {
2422 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
2423 return dwError;
2424 }
2425
2426 StartServiceCtrlDispatcher(ServiceTable);
2427
2428 DPRINT("Umpnpmgr: main() done\n");
2429
2430 ExitThread(0);
2431
2432 return 0;
2433 }
2434
2435 /* EOF */