[umpnpmgr]
[reactos.git] / reactos / 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 DWORD PNP_DeviceInstanceAction(
1090 handle_t hBinding,
1091 DWORD ulMajorAction,
1092 DWORD ulMinorAction,
1093 LPWSTR pszDeviceInstance1,
1094 LPWSTR pszDeviceInstance2)
1095 {
1096 CONFIGRET ret = CR_SUCCESS;
1097 NTSTATUS Status;
1098
1099 UNREFERENCED_PARAMETER(hBinding);
1100 UNREFERENCED_PARAMETER(ulMinorAction);
1101 UNREFERENCED_PARAMETER(pszDeviceInstance2);
1102
1103 DPRINT("PNP_DeviceInstanceAction() called\n");
1104
1105 switch (ulMajorAction)
1106 {
1107 case PNP_DEVINST_SETUP:
1108 DPRINT("Setup device instance\n");
1109 /* FIXME */
1110 ret = CR_CALL_NOT_IMPLEMENTED;
1111 break;
1112
1113 case PNP_DEVINST_ENABLE:
1114 {
1115 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1116 DPRINT("Enable device instance\n");
1117 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance1);
1118 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1119 if (!NT_SUCCESS(Status))
1120 ret = NtStatusToCrError(Status);
1121 break;
1122 }
1123
1124 case PNP_DEVINST_REENUMERATE:
1125 DPRINT("Reenumerate device instance\n");
1126 /* FIXME */
1127 ret = CR_CALL_NOT_IMPLEMENTED;
1128 break;
1129
1130 default:
1131 DPRINT1("Unknown function %lu\n", ulMajorAction);
1132 ret = CR_CALL_NOT_IMPLEMENTED;
1133 }
1134
1135 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1136
1137 return ret;
1138 }
1139
1140
1141 /* Function 30 */
1142 DWORD PNP_GetDeviceStatus(
1143 handle_t hBinding,
1144 LPWSTR pDeviceID,
1145 DWORD *pulStatus,
1146 DWORD *pulProblem,
1147 DWORD ulFlags)
1148 {
1149 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1150 CONFIGRET ret = CR_SUCCESS;
1151 NTSTATUS Status;
1152
1153 UNREFERENCED_PARAMETER(hBinding);
1154 UNREFERENCED_PARAMETER(ulFlags);
1155
1156 DPRINT("PNP_GetDeviceStatus() called\n");
1157
1158 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1159 pDeviceID);
1160 PlugPlayData.Operation = 0; /* Get status */
1161
1162 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1163 (PVOID)&PlugPlayData,
1164 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1165 if (NT_SUCCESS(Status))
1166 {
1167 *pulStatus = PlugPlayData.DeviceStatus;
1168 *pulProblem = PlugPlayData.DeviceProblem;
1169 }
1170 else
1171 {
1172 ret = NtStatusToCrError(Status);
1173 }
1174
1175 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1176
1177 return ret;
1178 }
1179
1180
1181 /* Function 31 */
1182 DWORD PNP_SetDeviceProblem(
1183 handle_t hBinding,
1184 LPWSTR pDeviceID,
1185 DWORD ulProblem,
1186 DWORD ulFlags)
1187 {
1188 UNIMPLEMENTED;
1189 return CR_CALL_NOT_IMPLEMENTED;
1190 }
1191
1192
1193 /* Function 32 */
1194 DWORD PNP_DisableDevInst(
1195 handle_t hBinding,
1196 LPWSTR pDeviceID,
1197 PPNP_VETO_TYPE pVetoType,
1198 LPWSTR pszVetoName,
1199 DWORD ulNameLength,
1200 DWORD ulFlags)
1201 {
1202 UNIMPLEMENTED;
1203 return CR_CALL_NOT_IMPLEMENTED;
1204 }
1205
1206 /* Function 33 */
1207 DWORD PNP_UninstallDevInst(
1208 handle_t hBinding,
1209 LPWSTR pDeviceID,
1210 DWORD ulFlags)
1211 {
1212 UNIMPLEMENTED;
1213 return CR_CALL_NOT_IMPLEMENTED;
1214 }
1215
1216
1217 static BOOL
1218 CheckForDeviceId(LPWSTR lpDeviceIdList,
1219 LPWSTR lpDeviceId)
1220 {
1221 LPWSTR lpPtr;
1222 DWORD dwLength;
1223
1224 lpPtr = lpDeviceIdList;
1225 while (*lpPtr != 0)
1226 {
1227 dwLength = wcslen(lpPtr);
1228 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1229 return TRUE;
1230
1231 lpPtr += (dwLength + 1);
1232 }
1233
1234 return FALSE;
1235 }
1236
1237
1238 static VOID
1239 AppendDeviceId(LPWSTR lpDeviceIdList,
1240 LPDWORD lpDeviceIdListSize,
1241 LPWSTR lpDeviceId)
1242 {
1243 DWORD dwLen;
1244 DWORD dwPos;
1245
1246 dwLen = wcslen(lpDeviceId);
1247 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1248
1249 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1250
1251 dwPos += (dwLen + 1);
1252
1253 lpDeviceIdList[dwPos] = 0;
1254
1255 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1256 }
1257
1258
1259 /* Function 34 */
1260 DWORD PNP_AddID(
1261 handle_t hBinding,
1262 LPWSTR pszDeviceID,
1263 LPWSTR pszID,
1264 DWORD ulFlags)
1265 {
1266 CONFIGRET ret = CR_SUCCESS;
1267 HKEY hDeviceKey;
1268 LPWSTR pszSubKey;
1269 DWORD dwDeviceIdListSize;
1270 DWORD dwNewDeviceIdSize;
1271 WCHAR * pszDeviceIdList = NULL;
1272
1273 UNREFERENCED_PARAMETER(hBinding);
1274
1275 DPRINT("PNP_AddID() called\n");
1276 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1277 DPRINT(" DeviceId: %S\n", pszID);
1278 DPRINT(" Flags: %lx\n", ulFlags);
1279
1280 if (RegOpenKeyExW(hEnumKey,
1281 pszDeviceID,
1282 0,
1283 KEY_QUERY_VALUE | KEY_SET_VALUE,
1284 &hDeviceKey) != ERROR_SUCCESS)
1285 {
1286 DPRINT("Failed to open the device key!\n");
1287 return CR_INVALID_DEVNODE;
1288 }
1289
1290 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1291
1292 if (RegQueryValueExW(hDeviceKey,
1293 pszSubKey,
1294 NULL,
1295 NULL,
1296 NULL,
1297 &dwDeviceIdListSize) != ERROR_SUCCESS)
1298 {
1299 DPRINT("Failed to query the desired ID string!\n");
1300 ret = CR_REGISTRY_ERROR;
1301 goto Done;
1302 }
1303
1304 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1305 if (!dwNewDeviceIdSize)
1306 {
1307 ret = CR_INVALID_POINTER;
1308 goto Done;
1309 }
1310
1311 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1312
1313 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1314 if (!pszDeviceIdList)
1315 {
1316 DPRINT("Failed to allocate memory for the desired ID string!\n");
1317 ret = CR_OUT_OF_MEMORY;
1318 goto Done;
1319 }
1320
1321 if (RegQueryValueExW(hDeviceKey,
1322 pszSubKey,
1323 NULL,
1324 NULL,
1325 (LPBYTE)pszDeviceIdList,
1326 &dwDeviceIdListSize) != ERROR_SUCCESS)
1327 {
1328 DPRINT("Failed to query the desired ID string!\n");
1329 ret = CR_REGISTRY_ERROR;
1330 goto Done;
1331 }
1332
1333 /* Check whether the device ID is already in use */
1334 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1335 {
1336 DPRINT("Device ID was found in the ID string!\n");
1337 ret = CR_SUCCESS;
1338 goto Done;
1339 }
1340
1341 /* Append the Device ID */
1342 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1343
1344 if (RegSetValueExW(hDeviceKey,
1345 pszSubKey,
1346 0,
1347 REG_MULTI_SZ,
1348 (LPBYTE)pszDeviceIdList,
1349 dwDeviceIdListSize) != ERROR_SUCCESS)
1350 {
1351 DPRINT("Failed to set the desired ID string!\n");
1352 ret = CR_REGISTRY_ERROR;
1353 }
1354
1355 Done:
1356 RegCloseKey(hDeviceKey);
1357 if (pszDeviceIdList)
1358 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1359
1360 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1361
1362 return ret;
1363 }
1364
1365
1366 /* Function 35 */
1367 DWORD PNP_RegisterDriver(
1368 handle_t hBinding,
1369 LPWSTR pszDeviceID,
1370 DWORD ulFlags)
1371 {
1372 UNIMPLEMENTED;
1373 return CR_CALL_NOT_IMPLEMENTED;
1374 }
1375
1376
1377 /* Function 36 */
1378 DWORD PNP_QueryRemove(
1379 handle_t hBinding,
1380 LPWSTR pszDeviceID,
1381 PPNP_VETO_TYPE pVetoType,
1382 LPWSTR pszVetoName,
1383 DWORD ulNameLength,
1384 DWORD ulFlags)
1385 {
1386 UNIMPLEMENTED;
1387 return CR_CALL_NOT_IMPLEMENTED;
1388 }
1389
1390
1391 /* Function 37 */
1392 DWORD PNP_RequestDeviceEject(
1393 handle_t hBinding,
1394 LPWSTR pszDeviceID,
1395 PPNP_VETO_TYPE pVetoType,
1396 LPWSTR pszVetoName,
1397 DWORD ulNameLength,
1398 DWORD ulFlags)
1399 {
1400 UNIMPLEMENTED;
1401 return CR_CALL_NOT_IMPLEMENTED;
1402 }
1403
1404 /* Function 38 */
1405 CONFIGRET
1406 PNP_IsDockStationPresent(handle_t hBinding,
1407 BOOL *Present)
1408 {
1409 HKEY hKey;
1410 DWORD dwType;
1411 DWORD dwValue;
1412 DWORD dwSize;
1413 CONFIGRET ret = CR_SUCCESS;
1414
1415 UNREFERENCED_PARAMETER(hBinding);
1416
1417 DPRINT1("PNP_IsDockStationPresent() called\n");
1418
1419 *Present = FALSE;
1420
1421 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1422 L"CurrentDockInfo",
1423 0,
1424 KEY_READ,
1425 &hKey) != ERROR_SUCCESS)
1426 return CR_REGISTRY_ERROR;
1427
1428 dwSize = sizeof(DWORD);
1429 if (RegQueryValueExW(hKey,
1430 L"DockingState",
1431 NULL,
1432 &dwType,
1433 (LPBYTE)&dwValue,
1434 &dwSize) != ERROR_SUCCESS)
1435 ret = CR_REGISTRY_ERROR;
1436
1437 RegCloseKey(hKey);
1438
1439 if (ret == CR_SUCCESS)
1440 {
1441 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1442 {
1443 ret = CR_REGISTRY_ERROR;
1444 }
1445 else if (dwValue != 0)
1446 {
1447 *Present = TRUE;
1448 }
1449 }
1450
1451 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1452
1453 return ret;
1454 }
1455
1456
1457 /* Function 39 */
1458 DWORD PNP_RequestEjectPC(
1459 handle_t hBinding)
1460 {
1461 UNIMPLEMENTED;
1462 return CR_CALL_NOT_IMPLEMENTED;
1463 }
1464
1465
1466 /* Function 40 */
1467 DWORD PNP_HwProfFlags(
1468 handle_t hBinding,
1469 DWORD ulAction,
1470 LPWSTR pDeviceID,
1471 DWORD ulConfig,
1472 DWORD *pulValue,
1473 PPNP_VETO_TYPE pVetoType,
1474 LPWSTR pszVetoName,
1475 DWORD ulNameLength,
1476 DWORD ulFlags)
1477 {
1478 UNIMPLEMENTED;
1479 return CR_CALL_NOT_IMPLEMENTED;
1480 }
1481
1482
1483 /* Function 41 */
1484 DWORD PNP_GetHwProfInfo(
1485 handle_t hBinding,
1486 DWORD ulIndex,
1487 HWPROFILEINFO *pHWProfileInfo,
1488 DWORD ulProfileInfoSize,
1489 DWORD ulFlags)
1490 {
1491 UNIMPLEMENTED;
1492 return CR_CALL_NOT_IMPLEMENTED;
1493 }
1494
1495
1496 /* Function 42 */
1497 DWORD PNP_AddEmptyLogConf(
1498 handle_t hBinding,
1499 LPWSTR pDeviceID,
1500 DWORD ulPriority,
1501 DWORD *pulLogConfTag,
1502 DWORD ulFlags)
1503 {
1504 UNIMPLEMENTED;
1505 return CR_CALL_NOT_IMPLEMENTED;
1506 }
1507
1508
1509 /* Function 43 */
1510 DWORD PNP_FreeLogConf(
1511 handle_t hBinding,
1512 LPWSTR pDeviceID,
1513 DWORD ulLogConfType,
1514 DWORD ulLogConfTag,
1515 DWORD ulFlags)
1516 {
1517 UNIMPLEMENTED;
1518 return CR_CALL_NOT_IMPLEMENTED;
1519 }
1520
1521
1522 /* Function 44 */
1523 DWORD PNP_GetFirstLogConf(
1524 handle_t hBinding,
1525 LPWSTR pDeviceID,
1526 DWORD ulLogConfType,
1527 DWORD *pulLogConfTag,
1528 DWORD ulFlags)
1529 {
1530 UNIMPLEMENTED;
1531 return CR_CALL_NOT_IMPLEMENTED;
1532 }
1533
1534
1535 /* Function 45 */
1536 DWORD PNP_GetNextLogConf(
1537 handle_t hBinding,
1538 LPWSTR pDeviceID,
1539 DWORD ulLogConfType,
1540 DWORD ulCurrentTag,
1541 DWORD *pulNextTag,
1542 DWORD ulFlags)
1543 {
1544 UNIMPLEMENTED;
1545 return CR_CALL_NOT_IMPLEMENTED;
1546 }
1547
1548
1549 /* Function 46 */
1550 DWORD PNP_GetLogConfPriority(
1551 handle_t hBinding,
1552 LPWSTR pDeviceID,
1553 DWORD ulType,
1554 DWORD ulTag,
1555 DWORD *pPriority,
1556 DWORD ulFlags)
1557 {
1558 UNIMPLEMENTED;
1559 return CR_CALL_NOT_IMPLEMENTED;
1560 }
1561
1562
1563 /* Function 47 */
1564 DWORD PNP_AddResDes(
1565 handle_t hBinding,
1566 LPWSTR pDeviceID,
1567 DWORD ulLogConfTag,
1568 DWORD ulLogConfType,
1569 RESOURCEID ResourceID,
1570 DWORD *pulResourceTag,
1571 BYTE *ResourceData,
1572 PNP_RPC_BUFFER_SIZE ResourceLen,
1573 DWORD ulFlags)
1574 {
1575 UNIMPLEMENTED;
1576 return CR_CALL_NOT_IMPLEMENTED;
1577 }
1578
1579
1580 /* Function 48 */
1581 DWORD PNP_FreeResDes(
1582 handle_t hBinding,
1583 LPWSTR pDeviceID,
1584 DWORD ulLogConfTag,
1585 DWORD ulLogConfType,
1586 RESOURCEID ResourceID,
1587 DWORD ulResourceTag,
1588 DWORD *pulPreviousResType,
1589 DWORD *pulPreviousResTag,
1590 DWORD ulFlags)
1591 {
1592 UNIMPLEMENTED;
1593 return CR_CALL_NOT_IMPLEMENTED;
1594 }
1595
1596
1597 /* Function 49 */
1598 DWORD PNP_GetNextResDes(
1599 handle_t hBinding,
1600 LPWSTR pDeviceID,
1601 DWORD ulLogConfTag,
1602 DWORD ulLogConfType,
1603 RESOURCEID ResourceID,
1604 DWORD ulResourceTag,
1605 DWORD *pulNextResType,
1606 DWORD *pulNextResTag,
1607 DWORD ulFlags)
1608 {
1609 UNIMPLEMENTED;
1610 return CR_CALL_NOT_IMPLEMENTED;
1611 }
1612
1613
1614 /* Function 50 */
1615 DWORD PNP_GetResDesData(
1616 handle_t hBinding,
1617 LPWSTR pDeviceID,
1618 DWORD ulLogConfTag,
1619 DWORD ulLogConfType,
1620 RESOURCEID ResourceID,
1621 DWORD ulResourceTag,
1622 BYTE *Buffer,
1623 PNP_RPC_BUFFER_SIZE BufferLen,
1624 DWORD ulFlags)
1625 {
1626 UNIMPLEMENTED;
1627 return CR_CALL_NOT_IMPLEMENTED;
1628 }
1629
1630
1631 /* Function 51 */
1632 DWORD PNP_GetResDesDataSize(
1633 handle_t hBinding,
1634 LPWSTR pDeviceID,
1635 DWORD ulLogConfTag,
1636 DWORD ulLogConfType,
1637 RESOURCEID ResourceID,
1638 DWORD ulResourceTag,
1639 DWORD *pulSize,
1640 DWORD ulFlags)
1641 {
1642 UNIMPLEMENTED;
1643 return CR_CALL_NOT_IMPLEMENTED;
1644 }
1645
1646
1647 /* Function 52 */
1648 DWORD PNP_ModifyResDes(
1649 handle_t hBinding,
1650 LPWSTR pDeviceID,
1651 DWORD ulLogConfTag,
1652 DWORD ulLogConfType,
1653 RESOURCEID CurrentResourceID,
1654 RESOURCEID NewResourceID,
1655 DWORD ulResourceTag,
1656 BYTE *ResourceData,
1657 PNP_RPC_BUFFER_SIZE ResourceLen,
1658 DWORD ulFlags)
1659 {
1660 UNIMPLEMENTED;
1661 return CR_CALL_NOT_IMPLEMENTED;
1662 }
1663
1664
1665 /* Function 53 */
1666 DWORD PNP_DetectResourceConflict(
1667 handle_t hBinding,
1668 LPWSTR pDeviceID,
1669 RESOURCEID ResourceID,
1670 BYTE *ResourceData,
1671 PNP_RPC_BUFFER_SIZE ResourceLen,
1672 BOOL *pbConflictDetected,
1673 DWORD ulFlags)
1674 {
1675 UNIMPLEMENTED;
1676 return CR_CALL_NOT_IMPLEMENTED;
1677 }
1678
1679
1680 /* Function 54 */
1681 DWORD PNP_QueryResConfList(
1682 handle_t hBinding,
1683 LPWSTR pDeviceID,
1684 RESOURCEID ResourceID,
1685 BYTE *ResourceData,
1686 PNP_RPC_BUFFER_SIZE ResourceLen,
1687 BYTE *Buffer,
1688 PNP_RPC_BUFFER_SIZE BufferLen,
1689 DWORD ulFlags)
1690 {
1691 UNIMPLEMENTED;
1692 return CR_CALL_NOT_IMPLEMENTED;
1693 }
1694
1695
1696 /* Function 55 */
1697 DWORD PNP_SetHwProf(
1698 handle_t hBinding)
1699 {
1700 UNIMPLEMENTED;
1701 return CR_CALL_NOT_IMPLEMENTED;
1702 }
1703
1704
1705 /* Function 56 */
1706 DWORD PNP_QueryArbitratorFreeData(
1707 handle_t hBinding)
1708 {
1709 UNIMPLEMENTED;
1710 return CR_CALL_NOT_IMPLEMENTED;
1711 }
1712
1713
1714 /* Function 57 */
1715 DWORD PNP_QueryArbitratorFreeSize(
1716 handle_t hBinding)
1717 {
1718 UNIMPLEMENTED;
1719 return CR_CALL_NOT_IMPLEMENTED;
1720 }
1721
1722
1723 /* Function 58 */
1724 CONFIGRET
1725 PNP_RunDetection(
1726 handle_t hBinding,
1727 DWORD ulFlags)
1728 {
1729 UNIMPLEMENTED;
1730 return CR_CALL_NOT_IMPLEMENTED;
1731 }
1732
1733
1734 /* Function 59 */
1735 DWORD PNP_RegisterNotification(
1736 handle_t hBinding)
1737 {
1738 UNIMPLEMENTED;
1739 return CR_CALL_NOT_IMPLEMENTED;
1740 }
1741
1742
1743 /* Function 60 */
1744 DWORD PNP_UnregisterNotification(
1745 handle_t hBinding)
1746 {
1747 UNIMPLEMENTED;
1748 return CR_CALL_NOT_IMPLEMENTED;
1749 }
1750
1751
1752 /* Function 61 */
1753 DWORD PNP_GetCustomDevProp(
1754 handle_t hBinding,
1755 LPWSTR pDeviceID,
1756 LPWSTR CustomPropName,
1757 DWORD *pulRegDataType,
1758 BYTE *Buffer,
1759 PNP_RPC_STRING_LEN *pulTransferLen,
1760 PNP_RPC_STRING_LEN *pulLength,
1761 DWORD ulFlags)
1762 {
1763 UNIMPLEMENTED;
1764 return CR_CALL_NOT_IMPLEMENTED;
1765 }
1766
1767
1768 /* Function 62 */
1769 DWORD PNP_GetVersionInternal(
1770 handle_t hBinding,
1771 WORD *pwVersion)
1772 {
1773 UNIMPLEMENTED;
1774 return CR_CALL_NOT_IMPLEMENTED;
1775 }
1776
1777
1778 /* Function 63 */
1779 DWORD PNP_GetBlockedDriverInfo(
1780 handle_t hBinding,
1781 BYTE *Buffer,
1782 PNP_RPC_BUFFER_SIZE *pulTransferLen,
1783 PNP_RPC_BUFFER_SIZE *pulLength,
1784 DWORD ulFlags)
1785 {
1786 UNIMPLEMENTED;
1787 return CR_CALL_NOT_IMPLEMENTED;
1788 }
1789
1790
1791 /* Function 64 */
1792 DWORD PNP_GetServerSideDeviceInstallFlags(
1793 handle_t hBinding,
1794 DWORD *pulSSDIFlags,
1795 DWORD ulFlags)
1796 {
1797 UNIMPLEMENTED;
1798 return CR_CALL_NOT_IMPLEMENTED;
1799 }
1800
1801
1802 /* Function 65 */
1803 DWORD PNP_GetObjectPropKeys(
1804 handle_t hBinding,
1805 LPWSTR ObjectName,
1806 DWORD ObjectType,
1807 LPWSTR PropertyCultureName,
1808 PNP_PROP_COUNT *PropertyCount,
1809 PNP_PROP_COUNT *TransferLen,
1810 DEVPROPKEY *PropertyKeys,
1811 DWORD Flags)
1812 {
1813 UNIMPLEMENTED;
1814 return CR_CALL_NOT_IMPLEMENTED;
1815 }
1816
1817
1818 /* Function 66 */
1819 DWORD PNP_GetObjectProp(
1820 handle_t hBinding,
1821 LPWSTR ObjectName,
1822 DWORD ObjectType,
1823 LPWSTR PropertyCultureName,
1824 const DEVPROPKEY *PropertyKey,
1825 DEVPROPTYPE *PropertyType,
1826 PNP_PROP_SIZE *PropertySize,
1827 PNP_PROP_SIZE *TransferLen,
1828 BYTE *PropertyBuffer,
1829 DWORD Flags)
1830 {
1831 UNIMPLEMENTED;
1832 return CR_CALL_NOT_IMPLEMENTED;
1833 }
1834
1835
1836 /* Function 67 */
1837 DWORD PNP_SetObjectProp(
1838 handle_t hBinding,
1839 LPWSTR ObjectName,
1840 DWORD ObjectType,
1841 LPWSTR PropertyCultureName,
1842 const DEVPROPKEY *PropertyKey,
1843 DEVPROPTYPE PropertyType,
1844 PNP_PROP_SIZE PropertySize,
1845 BYTE *PropertyBuffer,
1846 DWORD Flags)
1847 {
1848 UNIMPLEMENTED;
1849 return CR_CALL_NOT_IMPLEMENTED;
1850 }
1851
1852
1853 /* Function 68 */
1854 DWORD PNP_InstallDevInst(
1855 handle_t hBinding)
1856 {
1857 UNIMPLEMENTED;
1858 return CR_CALL_NOT_IMPLEMENTED;
1859 }
1860
1861
1862 /* Function 69 */
1863 DWORD PNP_ApplyPowerSettings(
1864 handle_t hBinding)
1865 {
1866 UNIMPLEMENTED;
1867 return CR_CALL_NOT_IMPLEMENTED;
1868 }
1869
1870
1871 /* Function 70 */
1872 DWORD PNP_DriverStoreAddDriverPackage(
1873 handle_t hBinding)
1874 {
1875 UNIMPLEMENTED;
1876 return CR_CALL_NOT_IMPLEMENTED;
1877 }
1878
1879
1880 /* Function 71 */
1881 DWORD PNP_DriverStoreDeleteDriverPackage(
1882 handle_t hBinding)
1883 {
1884 UNIMPLEMENTED;
1885 return CR_CALL_NOT_IMPLEMENTED;
1886 }
1887
1888
1889 /* Function 72 */
1890 DWORD PNP_RegisterServiceNotification(
1891 handle_t hBinding)
1892 {
1893 UNIMPLEMENTED;
1894 return CR_CALL_NOT_IMPLEMENTED;
1895 }
1896
1897
1898 /* Function 73 */
1899 DWORD PNP_SetActiveService(
1900 handle_t hBinding)
1901 {
1902 UNIMPLEMENTED;
1903 return CR_CALL_NOT_IMPLEMENTED;
1904 }
1905
1906
1907 /* Function 74 */
1908 DWORD PNP_DeleteServiceDevices(
1909 handle_t hBinding)
1910 {
1911 UNIMPLEMENTED;
1912 return CR_CALL_NOT_IMPLEMENTED;
1913 }
1914
1915
1916 static BOOL
1917 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
1918 {
1919 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1920 NTSTATUS Status;
1921 BOOL DeviceInstalled = FALSE;
1922 DWORD BytesWritten;
1923 DWORD Value;
1924 HANDLE hPipe = INVALID_HANDLE_VALUE;
1925 LPVOID Environment = NULL;
1926 PROCESS_INFORMATION ProcessInfo;
1927 STARTUPINFOW StartupInfo;
1928 UUID RandomUuid;
1929
1930 /* The following lengths are constant (see below), they cannot overflow */
1931 WCHAR CommandLine[116];
1932 WCHAR InstallEventName[73];
1933 WCHAR PipeName[74];
1934 WCHAR UuidString[39];
1935
1936 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
1937
1938 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
1939
1940 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1941 DeviceInstance);
1942 PlugPlayData.Operation = 0; /* Get status */
1943
1944 /* Get device status */
1945 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1946 (PVOID)&PlugPlayData,
1947 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1948 if (!NT_SUCCESS(Status))
1949 {
1950 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status);
1951 return FALSE;
1952 }
1953
1954 if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
1955 {
1956 /* Device is already started, or disabled due to some problem. Don't install it */
1957 DPRINT("No need to install '%S'\n", DeviceInstance);
1958 return TRUE;
1959 }
1960
1961 /* Create a random UUID for the named pipe */
1962 UuidCreate(&RandomUuid);
1963 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
1964 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
1965 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
1966 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
1967 RandomUuid.Data4[6], RandomUuid.Data4[7]);
1968
1969 /* Create the named pipe */
1970 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
1971 wcscat(PipeName, UuidString);
1972 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
1973
1974 if(hPipe == INVALID_HANDLE_VALUE)
1975 {
1976 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
1977 goto cleanup;
1978 }
1979
1980 /* Launch rundll32 to call ClientSideInstallW */
1981 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
1982 wcscat(CommandLine, PipeName);
1983
1984 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
1985 StartupInfo.cb = sizeof(StartupInfo);
1986
1987 if(hUserToken)
1988 {
1989 /* newdev has to run under the environment of the current user */
1990 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
1991 {
1992 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
1993 goto cleanup;
1994 }
1995
1996 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
1997 {
1998 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
1999 goto cleanup;
2000 }
2001 }
2002 else
2003 {
2004 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2005
2006 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2007 (ShowWizard is only set to FALSE for these two modes) */
2008 ASSERT(!ShowWizard);
2009
2010 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2011 {
2012 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2013 goto cleanup;
2014 }
2015 }
2016
2017 /* Wait for the function to connect to our pipe */
2018 if(!ConnectNamedPipe(hPipe, NULL))
2019 {
2020 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2021 goto cleanup;
2022 }
2023
2024 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2025 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2026 wcscat(InstallEventName, UuidString);
2027
2028 Value = sizeof(InstallEventName);
2029 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2030 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2031
2032 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2033 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2034 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2035
2036 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2037 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2038 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2039
2040 /* Wait for newdev.dll to finish processing */
2041 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2042
2043 /* The following check for success is probably not compatible to Windows, but should do its job */
2044 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2045 {
2046 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2047 goto cleanup;
2048 }
2049
2050 DeviceInstalled = Value;
2051
2052 cleanup:
2053 if(hPipe != INVALID_HANDLE_VALUE)
2054 CloseHandle(hPipe);
2055
2056 if(Environment)
2057 DestroyEnvironmentBlock(Environment);
2058
2059 if(ProcessInfo.hProcess)
2060 CloseHandle(ProcessInfo.hProcess);
2061
2062 if(ProcessInfo.hThread)
2063 CloseHandle(ProcessInfo.hThread);
2064
2065 return DeviceInstalled;
2066 }
2067
2068
2069 static LONG
2070 ReadRegSzKey(
2071 IN HKEY hKey,
2072 IN LPCWSTR pszKey,
2073 OUT LPWSTR* pValue)
2074 {
2075 LONG rc;
2076 DWORD dwType;
2077 DWORD cbData = 0;
2078 LPWSTR Value;
2079
2080 if (!pValue)
2081 return ERROR_INVALID_PARAMETER;
2082
2083 *pValue = NULL;
2084 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2085 if (rc != ERROR_SUCCESS)
2086 return rc;
2087 if (dwType != REG_SZ)
2088 return ERROR_FILE_NOT_FOUND;
2089 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2090 if (!Value)
2091 return ERROR_NOT_ENOUGH_MEMORY;
2092 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2093 if (rc != ERROR_SUCCESS)
2094 {
2095 HeapFree(GetProcessHeap(), 0, Value);
2096 return rc;
2097 }
2098 /* NULL-terminate the string */
2099 Value[cbData / sizeof(WCHAR)] = '\0';
2100
2101 *pValue = Value;
2102 return ERROR_SUCCESS;
2103 }
2104
2105
2106 static BOOL
2107 SetupIsActive(VOID)
2108 {
2109 HKEY hKey = NULL;
2110 DWORD regType, active, size;
2111 LONG rc;
2112 BOOL ret = FALSE;
2113
2114 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2115 if (rc != ERROR_SUCCESS)
2116 goto cleanup;
2117
2118 size = sizeof(DWORD);
2119 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2120 if (rc != ERROR_SUCCESS)
2121 goto cleanup;
2122 if (regType != REG_DWORD || size != sizeof(DWORD))
2123 goto cleanup;
2124
2125 ret = (active != 0);
2126
2127 cleanup:
2128 if (hKey != NULL)
2129 RegCloseKey(hKey);
2130
2131 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2132
2133 return ret;
2134 }
2135
2136
2137 static BOOL
2138 IsConsoleBoot(VOID)
2139 {
2140 HKEY ControlKey = NULL;
2141 LPWSTR SystemStartOptions = NULL;
2142 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2143 BOOL ConsoleBoot = FALSE;
2144 LONG rc;
2145
2146 rc = RegOpenKeyExW(
2147 HKEY_LOCAL_MACHINE,
2148 L"SYSTEM\\CurrentControlSet\\Control",
2149 0,
2150 KEY_QUERY_VALUE,
2151 &ControlKey);
2152
2153 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2154 if (rc != ERROR_SUCCESS)
2155 goto cleanup;
2156
2157 /* Check for CMDCONS in SystemStartOptions */
2158 CurrentOption = SystemStartOptions;
2159 while (CurrentOption)
2160 {
2161 NextOption = wcschr(CurrentOption, L' ');
2162 if (NextOption)
2163 *NextOption = L'\0';
2164 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2165 {
2166 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2167 ConsoleBoot = TRUE;
2168 goto cleanup;
2169 }
2170 CurrentOption = NextOption ? NextOption + 1 : NULL;
2171 }
2172
2173 cleanup:
2174 if (ControlKey != NULL)
2175 RegCloseKey(ControlKey);
2176 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2177 return ConsoleBoot;
2178 }
2179
2180
2181 /* Loop to install all queued devices installations */
2182 static DWORD WINAPI
2183 DeviceInstallThread(LPVOID lpParameter)
2184 {
2185 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2186 PSLIST_ENTRY ListEntry;
2187 #else
2188 PLIST_ENTRY ListEntry;
2189 #endif
2190 DeviceInstallParams* Params;
2191 BOOL showWizard;
2192
2193 UNREFERENCED_PARAMETER(lpParameter);
2194
2195 WaitForSingleObject(hInstallEvent, INFINITE);
2196
2197 showWizard = !SetupIsActive() && !IsConsoleBoot();
2198
2199 while (TRUE)
2200 {
2201 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2202 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2203 #else
2204 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2205 ListEntry = NULL;
2206 else
2207 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2208 #endif
2209 if (ListEntry == NULL)
2210 {
2211 SetEvent(hNoPendingInstalls);
2212 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2213 }
2214 else
2215 {
2216 ResetEvent(hNoPendingInstalls);
2217 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2218 InstallDevice(Params->DeviceIds, showWizard);
2219 }
2220 }
2221
2222 return 0;
2223 }
2224
2225
2226 static DWORD WINAPI
2227 PnpEventThread(LPVOID lpParameter)
2228 {
2229 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2230 ULONG PnpEventSize;
2231 NTSTATUS Status;
2232 RPC_STATUS RpcStatus;
2233
2234 UNREFERENCED_PARAMETER(lpParameter);
2235
2236 PnpEventSize = 0x1000;
2237 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2238 if (PnpEvent == NULL)
2239 return ERROR_OUTOFMEMORY;
2240
2241 for (;;)
2242 {
2243 DPRINT("Calling NtGetPlugPlayEvent()\n");
2244
2245 /* Wait for the next pnp event */
2246 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2247
2248 /* Resize the buffer for the PnP event if it's too small. */
2249 if (Status == STATUS_BUFFER_TOO_SMALL)
2250 {
2251 PnpEventSize += 0x400;
2252 HeapFree(GetProcessHeap(), 0, PnpEvent);
2253 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2254 if (PnpEvent == NULL)
2255 return ERROR_OUTOFMEMORY;
2256 continue;
2257 }
2258
2259 if (!NT_SUCCESS(Status))
2260 {
2261 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2262 break;
2263 }
2264
2265 /* Process the pnp event */
2266 DPRINT("Received PnP Event\n");
2267 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2268 {
2269 DeviceInstallParams* Params;
2270 DWORD len;
2271 DWORD DeviceIdLength;
2272
2273 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
2274
2275 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2276 if (DeviceIdLength)
2277 {
2278 /* Queue device install (will be dequeued by DeviceInstallThread */
2279 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2280 Params = HeapAlloc(GetProcessHeap(), 0, len);
2281 if (Params)
2282 {
2283 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2284 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2285 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2286 #else
2287 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2288 #endif
2289 SetEvent(hDeviceInstallListNotEmpty);
2290 }
2291 }
2292 }
2293 else
2294 {
2295 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2296 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2297 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2298 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2299 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2300 }
2301
2302 /* Dequeue the current pnp event and signal the next one */
2303 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
2304 }
2305
2306 HeapFree(GetProcessHeap(), 0, PnpEvent);
2307
2308 return ERROR_SUCCESS;
2309 }
2310
2311
2312 static VOID CALLBACK
2313 ServiceMain(DWORD argc, LPTSTR *argv)
2314 {
2315 HANDLE hThread;
2316 DWORD dwThreadId;
2317
2318 UNREFERENCED_PARAMETER(argc);
2319 UNREFERENCED_PARAMETER(argv);
2320
2321 DPRINT("ServiceMain() called\n");
2322
2323 hThread = CreateThread(NULL,
2324 0,
2325 PnpEventThread,
2326 NULL,
2327 0,
2328 &dwThreadId);
2329 if (hThread != NULL)
2330 CloseHandle(hThread);
2331
2332 hThread = CreateThread(NULL,
2333 0,
2334 RpcServerThread,
2335 NULL,
2336 0,
2337 &dwThreadId);
2338 if (hThread != NULL)
2339 CloseHandle(hThread);
2340
2341 hThread = CreateThread(NULL,
2342 0,
2343 DeviceInstallThread,
2344 NULL,
2345 0,
2346 &dwThreadId);
2347 if (hThread != NULL)
2348 CloseHandle(hThread);
2349
2350 DPRINT("ServiceMain() done\n");
2351 }
2352
2353
2354 int
2355 wmain(int argc, WCHAR *argv[])
2356 {
2357 BOOLEAN OldValue;
2358 DWORD dwError;
2359
2360 UNREFERENCED_PARAMETER(argc);
2361 UNREFERENCED_PARAMETER(argv);
2362
2363 DPRINT("Umpnpmgr: main() started\n");
2364
2365 /* We need this privilege for using CreateProcessAsUserW */
2366 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
2367
2368 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
2369 if (hInstallEvent == NULL)
2370 {
2371 dwError = GetLastError();
2372 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
2373 return dwError;
2374 }
2375
2376 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
2377 if (hDeviceInstallListNotEmpty == NULL)
2378 {
2379 dwError = GetLastError();
2380 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2381 return dwError;
2382 }
2383
2384 hNoPendingInstalls = CreateEventW(NULL,
2385 TRUE,
2386 FALSE,
2387 L"Global\\PnP_No_Pending_Install_Events");
2388 if (hNoPendingInstalls == NULL)
2389 {
2390 dwError = GetLastError();
2391 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2392 return dwError;
2393 }
2394
2395 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2396 InitializeSListHead(&DeviceInstallListHead);
2397 #else
2398 InitializeListHead(&DeviceInstallListHead);
2399 #endif
2400
2401 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2402 L"System\\CurrentControlSet\\Enum",
2403 0,
2404 KEY_ALL_ACCESS,
2405 &hEnumKey);
2406 if (dwError != ERROR_SUCCESS)
2407 {
2408 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
2409 return dwError;
2410 }
2411
2412 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2413 L"System\\CurrentControlSet\\Control\\Class",
2414 0,
2415 KEY_ALL_ACCESS,
2416 &hClassKey);
2417 if (dwError != ERROR_SUCCESS)
2418 {
2419 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
2420 return dwError;
2421 }
2422
2423 StartServiceCtrlDispatcher(ServiceTable);
2424
2425 DPRINT("Umpnpmgr: main() done\n");
2426
2427 ExitThread(0);
2428
2429 return 0;
2430 }
2431
2432 /* EOF */