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