* Sync with recent trunk (r52637).
[reactos.git] / base / services / umpnpmgr / umpnpmgr.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2005 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: services/umpnpmgr/umpnpmgr.c
23 * PURPOSE: User-mode Plug and Play manager
24 * PROGRAMMER: Eric Kohl
25 * Hervé Poussineau (hpoussin@reactos.org)
26 * Colin Finck (colin@reactos.org)
27 */
28
29 /* INCLUDES *****************************************************************/
30 //#define HAVE_SLIST_ENTRY_IMPLEMENTED
31 #define WIN32_NO_STATUS
32 #include <windows.h>
33 #include <stdio.h>
34 #include <cmtypes.h>
35 #include <cmfuncs.h>
36 #include <rtlfuncs.h>
37 #include <setypes.h>
38 #include <umpnpmgr/sysguid.h>
39 #include <wdmguid.h>
40 #include <cfgmgr32.h>
41 #include <regstr.h>
42 #include <userenv.h>
43
44 #include <rpc.h>
45 #include <rpcdce.h>
46
47 #include "pnp_s.h"
48
49 #define NDEBUG
50 #include <debug.h>
51
52 /* GLOBALS ******************************************************************/
53
54 static VOID CALLBACK 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_SUCCESS)
734 {
735 if (lError == ERROR_MORE_DATA)
736 {
737 ret = CR_BUFFER_SMALL;
738 }
739 else
740 {
741 *pulLength = 0;
742 ret = CR_NO_SUCH_VALUE;
743 }
744 }
745 }
746 else
747 {
748 /* Retrieve information from the Device Node */
749 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
750 pDeviceID);
751 PlugPlayData.Buffer = Buffer;
752 PlugPlayData.BufferSize = *pulTransferLen;
753
754 switch (ulProperty)
755 {
756 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
757 PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName;
758 break;
759
760 case CM_DRP_UI_NUMBER:
761 PlugPlayData.Property = 0x11; // DevicePropertyUINumber;
762 break;
763
764 case CM_DRP_BUSTYPEGUID:
765 PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid;
766 break;
767
768 case CM_DRP_LEGACYBUSTYPE:
769 PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType;
770 break;
771
772 case CM_DRP_BUSNUMBER:
773 PlugPlayData.Property = 0xe; // DevicePropertyBusNumber;
774 break;
775
776 case CM_DRP_ENUMERATOR_NAME:
777 PlugPlayData.Property = 0xf; // DevicePropertyEnumeratorName;
778 break;
779
780 case CM_DRP_ADDRESS:
781 PlugPlayData.Property = 0x10; // DevicePropertyAddress;
782 break;
783
784 #if 0
785 /* FIXME: This property is not supported by IoGetDeviceProperty */
786 case CM_DRP_DEVICE_POWER_DATA:
787 #endif
788
789 case CM_DRP_REMOVAL_POLICY:
790 PlugPlayData.Property = 0x12; // DevicePropertyRemovalPolicy
791 break;
792
793 #if 0
794 /* FIXME: This property is not supported by IoGetDeviceProperty */
795 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
796 #endif
797
798 case CM_DRP_INSTALL_STATE:
799 PlugPlayData.Property = 0x12; // DevicePropertyInstallState;
800 break;
801
802 #if 0
803 /* FIXME: This property is not supported by IoGetDeviceProperty */
804 #if (WINVER >= _WIN32_WINNT_WS03)
805 case CM_DRP_LOCATION_PATHS:
806 #endif
807 #endif
808
809 #if (WINVER >= _WIN32_WINNT_WIN7)
810 case CM_DRP_BASE_CONTAINERID:
811 PlugPlayData.Property = 0x16; // DevicePropertyContainerID;
812 break;
813 #endif
814
815 default:
816 return CR_INVALID_PROPERTY;
817 }
818
819 Status = NtPlugPlayControl(PlugPlayControlProperty,
820 (PVOID)&PlugPlayData,
821 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
822 if (NT_SUCCESS(Status))
823 {
824 *pulLength = PlugPlayData.BufferSize;
825 }
826 else
827 {
828 ret = NtStatusToCrError(Status);
829 }
830 }
831
832 done:;
833 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
834
835 if (hKey != NULL)
836 RegCloseKey(hKey);
837
838 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
839
840 return ret;
841 }
842
843
844 /* Function 14 */
845 DWORD PNP_SetDeviceRegProp(
846 handle_t hBinding,
847 LPWSTR pDeviceId,
848 DWORD ulProperty,
849 DWORD ulDataType,
850 BYTE *Buffer,
851 PNP_PROP_SIZE ulLength,
852 DWORD ulFlags)
853 {
854 CONFIGRET ret = CR_SUCCESS;
855 LPWSTR lpValueName = NULL;
856 HKEY hKey = 0;
857
858 UNREFERENCED_PARAMETER(hBinding);
859 UNREFERENCED_PARAMETER(ulFlags);
860
861 DPRINT("PNP_SetDeviceRegProp() called\n");
862
863 DPRINT("DeviceId: %S\n", pDeviceId);
864 DPRINT("Property: %lu\n", ulProperty);
865 DPRINT("DataType: %lu\n", ulDataType);
866 DPRINT("Length: %lu\n", ulLength);
867
868 switch (ulProperty)
869 {
870 case CM_DRP_DEVICEDESC:
871 lpValueName = L"DeviceDesc";
872 break;
873
874 case CM_DRP_HARDWAREID:
875 lpValueName = L"HardwareID";
876 break;
877
878 case CM_DRP_COMPATIBLEIDS:
879 lpValueName = L"CompatibleIDs";
880 break;
881
882 case CM_DRP_SERVICE:
883 lpValueName = L"Service";
884 break;
885
886 case CM_DRP_CLASS:
887 lpValueName = L"Class";
888 break;
889
890 case CM_DRP_CLASSGUID:
891 lpValueName = L"ClassGUID";
892 break;
893
894 case CM_DRP_DRIVER:
895 lpValueName = L"Driver";
896 break;
897
898 case CM_DRP_CONFIGFLAGS:
899 lpValueName = L"ConfigFlags";
900 break;
901
902 case CM_DRP_MFG:
903 lpValueName = L"Mfg";
904 break;
905
906 case CM_DRP_FRIENDLYNAME:
907 lpValueName = L"FriendlyName";
908 break;
909
910 case CM_DRP_LOCATION_INFORMATION:
911 lpValueName = L"LocationInformation";
912 break;
913
914 case CM_DRP_UPPERFILTERS:
915 lpValueName = L"UpperFilters";
916 break;
917
918 case CM_DRP_LOWERFILTERS:
919 lpValueName = L"LowerFilters";
920 break;
921
922 case CM_DRP_SECURITY:
923 lpValueName = L"Security";
924 break;
925
926 case CM_DRP_DEVTYPE:
927 lpValueName = L"DeviceType";
928 break;
929
930 case CM_DRP_EXCLUSIVE:
931 lpValueName = L"Exclusive";
932 break;
933
934 case CM_DRP_CHARACTERISTICS:
935 lpValueName = L"DeviceCharacteristics";
936 break;
937
938 case CM_DRP_UI_NUMBER_DESC_FORMAT:
939 lpValueName = L"UINumberDescFormat";
940 break;
941
942 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
943 lpValueName = L"RemovalPolicy";
944 break;
945
946 default:
947 return CR_INVALID_PROPERTY;
948 }
949
950 DPRINT("Value name: %S\n", lpValueName);
951
952 if (RegOpenKeyExW(hEnumKey,
953 pDeviceId,
954 0,
955 KEY_SET_VALUE,
956 &hKey))
957 return CR_INVALID_DEVNODE;
958
959 if (ulLength == 0)
960 {
961 if (RegDeleteValueW(hKey,
962 lpValueName))
963 ret = CR_REGISTRY_ERROR;
964 }
965 else
966 {
967 if (RegSetValueExW(hKey,
968 lpValueName,
969 0,
970 ulDataType,
971 Buffer,
972 ulLength))
973 ret = CR_REGISTRY_ERROR;
974 }
975
976 RegCloseKey(hKey);
977
978 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
979
980 return ret;
981 }
982
983
984 /* Function 15 */
985 DWORD PNP_GetClassInstance(
986 handle_t hBinding,
987 LPWSTR pDeviceId,
988 LPWSTR pszClassInstance,
989 PNP_RPC_STRING_LEN ulLength)
990 {
991 UNIMPLEMENTED;
992 return CR_CALL_NOT_IMPLEMENTED;
993 }
994
995
996 /* Function 16 */
997 DWORD PNP_CreateKey(
998 handle_t hBinding,
999 LPWSTR pszSubKey,
1000 DWORD samDesired,
1001 DWORD ulFlags)
1002 {
1003 HKEY hKey = 0;
1004
1005 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1006 pszSubKey,
1007 0,
1008 NULL,
1009 0,
1010 KEY_ALL_ACCESS,
1011 NULL,
1012 &hKey,
1013 NULL))
1014 return CR_REGISTRY_ERROR;
1015
1016 /* FIXME: Set security key */
1017
1018 RegCloseKey(hKey);
1019
1020 return CR_SUCCESS;
1021 }
1022
1023
1024 /* Function 17 */
1025 DWORD PNP_DeleteRegistryKey(
1026 handle_t hBinding,
1027 LPWSTR pszDeviceID,
1028 LPWSTR pszParentKey,
1029 LPWSTR pszChildKey,
1030 DWORD ulFlags)
1031 {
1032 UNIMPLEMENTED;
1033 return CR_CALL_NOT_IMPLEMENTED;
1034 }
1035
1036
1037 /* Function 18 */
1038 DWORD PNP_GetClassCount(
1039 handle_t hBinding,
1040 DWORD *pulClassCount,
1041 DWORD ulFlags)
1042 {
1043 HKEY hKey;
1044 DWORD dwError;
1045
1046 UNREFERENCED_PARAMETER(hBinding);
1047 UNREFERENCED_PARAMETER(ulFlags);
1048
1049 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1050 REGSTR_PATH_CLASS,
1051 0,
1052 KEY_QUERY_VALUE,
1053 &hKey);
1054 if (dwError != ERROR_SUCCESS)
1055 return CR_INVALID_DATA;
1056
1057 dwError = RegQueryInfoKeyW(hKey,
1058 NULL,
1059 NULL,
1060 NULL,
1061 pulClassCount,
1062 NULL,
1063 NULL,
1064 NULL,
1065 NULL,
1066 NULL,
1067 NULL,
1068 NULL);
1069 RegCloseKey(hKey);
1070 if (dwError != ERROR_SUCCESS)
1071 return CR_INVALID_DATA;
1072
1073 return CR_SUCCESS;
1074 }
1075
1076
1077 /* Function 19 */
1078 DWORD PNP_GetClassName(
1079 handle_t hBinding,
1080 LPWSTR pszClassGuid,
1081 LPWSTR Buffer,
1082 PNP_RPC_STRING_LEN *pulLength,
1083 DWORD ulFlags)
1084 {
1085 WCHAR szKeyName[MAX_PATH];
1086 CONFIGRET ret = CR_SUCCESS;
1087 HKEY hKey;
1088 DWORD dwSize;
1089
1090 UNREFERENCED_PARAMETER(hBinding);
1091 UNREFERENCED_PARAMETER(ulFlags);
1092
1093 DPRINT("PNP_GetClassName() called\n");
1094
1095 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
1096 if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
1097 lstrcatW(szKeyName, pszClassGuid);
1098 else return CR_INVALID_DATA;
1099
1100 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1101 szKeyName,
1102 0,
1103 KEY_QUERY_VALUE,
1104 &hKey))
1105 return CR_REGISTRY_ERROR;
1106
1107 dwSize = *pulLength * sizeof(WCHAR);
1108 if (RegQueryValueExW(hKey,
1109 L"Class",
1110 NULL,
1111 NULL,
1112 (LPBYTE)Buffer,
1113 &dwSize))
1114 {
1115 *pulLength = 0;
1116 ret = CR_REGISTRY_ERROR;
1117 }
1118 else
1119 {
1120 *pulLength = dwSize / sizeof(WCHAR);
1121 }
1122
1123 RegCloseKey(hKey);
1124
1125 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
1126
1127 return ret;
1128 }
1129
1130
1131 /* Function 20 */
1132 DWORD PNP_DeleteClassKey(
1133 handle_t hBinding,
1134 LPWSTR pszClassGuid,
1135 DWORD ulFlags)
1136 {
1137 CONFIGRET ret = CR_SUCCESS;
1138
1139 UNREFERENCED_PARAMETER(hBinding);
1140
1141 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
1142
1143 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
1144 {
1145 if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
1146 ret = CR_REGISTRY_ERROR;
1147 }
1148 else
1149 {
1150 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
1151 ret = CR_REGISTRY_ERROR;
1152 }
1153
1154 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
1155
1156 return ret;
1157 }
1158
1159
1160 /* Function 21 */
1161 DWORD PNP_GetInterfaceDeviceAlias(
1162 handle_t hBinding,
1163 LPWSTR pszInterfaceDevice,
1164 GUID *AliasInterfaceGuid,
1165 LPWSTR pszAliasInterfaceDevice,
1166 PNP_RPC_STRING_LEN *pulLength,
1167 PNP_RPC_STRING_LEN *pulTransferLen,
1168 DWORD ulFlags)
1169 {
1170 UNIMPLEMENTED;
1171 return CR_CALL_NOT_IMPLEMENTED;
1172 }
1173
1174
1175 /* Function 22 */
1176 DWORD PNP_GetInterfaceDeviceList(
1177 handle_t hBinding,
1178 GUID *InterfaceGuid,
1179 LPWSTR pszDeviceID,
1180 BYTE *Buffer,
1181 PNP_RPC_BUFFER_SIZE *pulLength,
1182 DWORD ulFlags)
1183 {
1184 UNIMPLEMENTED;
1185 return CR_CALL_NOT_IMPLEMENTED;
1186 }
1187
1188
1189 /* Function 23 */
1190 DWORD PNP_GetInterfaceDeviceListSize(
1191 handle_t hBinding,
1192 PNP_RPC_BUFFER_SIZE *pulLen,
1193 GUID *InterfaceGuid,
1194 LPWSTR pszDeviceID,
1195 DWORD ulFlags)
1196 {
1197 UNIMPLEMENTED;
1198 return CR_CALL_NOT_IMPLEMENTED;
1199 }
1200
1201
1202 /* Function 24 */
1203 DWORD PNP_RegisterDeviceClassAssociation(
1204 handle_t hBinding,
1205 LPWSTR pszDeviceID,
1206 GUID *InterfaceGuid,
1207 LPWSTR pszReference,
1208 LPWSTR pszSymLink,
1209 PNP_RPC_STRING_LEN *pulLength,
1210 PNP_RPC_STRING_LEN *pulTransferLen,
1211 DWORD ulFlags)
1212 {
1213 UNIMPLEMENTED;
1214 return CR_CALL_NOT_IMPLEMENTED;
1215 }
1216
1217
1218 /* Function 25 */
1219 DWORD PNP_UnregisterDeviceClassAssociation(
1220 handle_t hBinding,
1221 LPWSTR pszInterfaceDevice,
1222 DWORD ulFlags)
1223 {
1224 UNIMPLEMENTED;
1225 return CR_CALL_NOT_IMPLEMENTED;
1226 }
1227
1228
1229 /* Function 26 */
1230 DWORD PNP_GetClassRegProp(
1231 handle_t hBinding,
1232 LPWSTR pszClassGuid,
1233 DWORD ulProperty,
1234 DWORD *pulRegDataType,
1235 BYTE *Buffer,
1236 PNP_RPC_STRING_LEN *pulTransferLen,
1237 PNP_RPC_STRING_LEN *pulLength,
1238 DWORD ulFlags)
1239 {
1240 CONFIGRET ret = CR_SUCCESS;
1241 LPWSTR lpValueName = NULL;
1242 HKEY hInstKey = NULL;
1243 HKEY hPropKey = NULL;
1244 LONG lError;
1245
1246 UNREFERENCED_PARAMETER(hBinding);
1247
1248 DPRINT("PNP_GetClassRegProp() called\n");
1249
1250 if (pulTransferLen == NULL || pulLength == NULL)
1251 {
1252 ret = CR_INVALID_POINTER;
1253 goto done;
1254 }
1255
1256 if (ulFlags != 0)
1257 {
1258 ret = CR_INVALID_FLAG;
1259 goto done;
1260 }
1261
1262 if (*pulLength < *pulTransferLen)
1263 *pulLength = *pulTransferLen;
1264
1265 *pulTransferLen = 0;
1266
1267 switch (ulProperty)
1268 {
1269 case CM_CRP_SECURITY:
1270 lpValueName = L"Security";
1271 break;
1272
1273 case CM_CRP_DEVTYPE:
1274 lpValueName = L"DeviceType";
1275 break;
1276
1277 case CM_CRP_EXCLUSIVE:
1278 lpValueName = L"Exclusive";
1279 break;
1280
1281 case CM_CRP_CHARACTERISTICS:
1282 lpValueName = L"DeviceCharacteristics";
1283 break;
1284
1285 default:
1286 ret = CR_INVALID_PROPERTY;
1287 goto done;
1288 }
1289
1290 DPRINT("Value name: %S\n", lpValueName);
1291
1292 lError = RegOpenKeyExW(hClassKey,
1293 pszClassGuid,
1294 0,
1295 KEY_READ,
1296 &hInstKey);
1297 if (lError != ERROR_SUCCESS)
1298 {
1299 *pulLength = 0;
1300 ret = CR_NO_SUCH_REGISTRY_KEY;
1301 goto done;
1302 }
1303
1304 lError = RegOpenKeyExW(hInstKey,
1305 L"Properties",
1306 0,
1307 KEY_READ,
1308 &hPropKey);
1309 if (lError != ERROR_SUCCESS)
1310 {
1311 *pulLength = 0;
1312 ret = CR_NO_SUCH_REGISTRY_KEY;
1313 goto done;
1314 }
1315
1316 lError = RegQueryValueExW(hPropKey,
1317 lpValueName,
1318 NULL,
1319 pulRegDataType,
1320 Buffer,
1321 pulLength);
1322 if (lError != ERROR_SUCCESS)
1323 {
1324 if (lError == ERROR_MORE_DATA)
1325 {
1326 ret = CR_BUFFER_SMALL;
1327 }
1328 else
1329 {
1330 *pulLength = 0;
1331 ret = CR_NO_SUCH_VALUE;
1332 }
1333 }
1334
1335 done:;
1336 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
1337
1338 if (hPropKey != NULL)
1339 RegCloseKey(hPropKey);
1340
1341 if (hInstKey != NULL)
1342 RegCloseKey(hInstKey);
1343
1344 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
1345
1346 return ret;
1347 }
1348
1349
1350 /* Function 27 */
1351 DWORD PNP_SetClassRegProp(
1352 handle_t hBinding,
1353 LPWSTR pszClassGuid,
1354 DWORD ulProperty,
1355 DWORD ulDataType,
1356 BYTE *Buffer,
1357 PNP_PROP_SIZE ulLength,
1358 DWORD ulFlags)
1359 {
1360 CONFIGRET ret = CR_SUCCESS;
1361 LPWSTR lpValueName = NULL;
1362 HKEY hInstKey = 0;
1363 HKEY hPropKey = 0;
1364 LONG lError;
1365
1366 UNREFERENCED_PARAMETER(hBinding);
1367
1368 DPRINT("PNP_SetClassRegProp() called\n");
1369
1370 if (ulFlags != 0)
1371 return CR_INVALID_FLAG;
1372
1373 switch (ulProperty)
1374 {
1375 case CM_CRP_SECURITY:
1376 lpValueName = L"Security";
1377 break;
1378
1379 case CM_CRP_DEVTYPE:
1380 lpValueName = L"DeviceType";
1381 break;
1382
1383 case CM_CRP_EXCLUSIVE:
1384 lpValueName = L"Exclusive";
1385 break;
1386
1387 case CM_CRP_CHARACTERISTICS:
1388 lpValueName = L"DeviceCharacteristics";
1389 break;
1390
1391 default:
1392 return CR_INVALID_PROPERTY;
1393 }
1394
1395 lError = RegOpenKeyExW(hClassKey,
1396 pszClassGuid,
1397 0,
1398 KEY_WRITE,
1399 &hInstKey);
1400 if (lError != ERROR_SUCCESS)
1401 {
1402 ret = CR_NO_SUCH_REGISTRY_KEY;
1403 goto done;
1404 }
1405
1406 /* FIXME: Set security descriptor */
1407 lError = RegCreateKeyExW(hInstKey,
1408 L"Properties",
1409 0,
1410 NULL,
1411 REG_OPTION_NON_VOLATILE,
1412 KEY_ALL_ACCESS,
1413 NULL,
1414 &hPropKey,
1415 NULL);
1416 if (lError != ERROR_SUCCESS)
1417 {
1418 ret = CR_REGISTRY_ERROR;
1419 goto done;
1420 }
1421
1422 if (ulLength == 0)
1423 {
1424 if (RegDeleteValueW(hPropKey,
1425 lpValueName))
1426 ret = CR_REGISTRY_ERROR;
1427 }
1428 else
1429 {
1430 if (RegSetValueExW(hPropKey,
1431 lpValueName,
1432 0,
1433 ulDataType,
1434 Buffer,
1435 ulLength))
1436 ret = CR_REGISTRY_ERROR;
1437 }
1438
1439 done:;
1440 if (hPropKey != NULL)
1441 RegCloseKey(hPropKey);
1442
1443 if (hInstKey != NULL)
1444 RegCloseKey(hInstKey);
1445
1446 return ret;
1447 }
1448
1449
1450 static VOID
1451 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
1452 OUT LPWSTR pszEnumerator,
1453 OUT LPWSTR pszDevice,
1454 OUT LPWSTR pszInstance)
1455 {
1456 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
1457 LPWSTR lpEnumerator = NULL;
1458 LPWSTR lpDevice = NULL;
1459 LPWSTR lpInstance = NULL;
1460 LPWSTR ptr;
1461
1462 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
1463
1464 *pszEnumerator = 0;
1465 *pszDevice = 0;
1466 *pszInstance = 0;
1467
1468 lpEnumerator = szLocalDeviceInstanceID;
1469
1470 ptr = wcschr(lpEnumerator, L'\\');
1471 if (ptr != NULL)
1472 {
1473 *ptr = 0;
1474 lpDevice = ++ptr;
1475
1476 ptr = wcschr(lpDevice, L'\\');
1477 if (ptr != NULL)
1478 {
1479 *ptr = 0;
1480 lpInstance = ++ptr;
1481 }
1482 }
1483
1484 if (lpEnumerator != NULL)
1485 wcscpy(pszEnumerator, lpEnumerator);
1486
1487 if (lpDevice != NULL)
1488 wcscpy(pszDevice, lpDevice);
1489
1490 if (lpInstance != NULL)
1491 wcscpy(pszInstance, lpInstance);
1492 }
1493
1494
1495 static CONFIGRET
1496 CreateDeviceInstance(LPWSTR pszDeviceID)
1497 {
1498 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1499 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1500 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1501 HKEY hKeyEnumerator;
1502 HKEY hKeyDevice;
1503 HKEY hKeyInstance;
1504 HKEY hKeyControl;
1505 LONG lError;
1506
1507 /* Split the instance ID */
1508 SplitDeviceInstanceID(pszDeviceID,
1509 szEnumerator,
1510 szDevice,
1511 szInstance);
1512
1513 /* Open or create the enumerator key */
1514 lError = RegCreateKeyExW(hEnumKey,
1515 szEnumerator,
1516 0,
1517 NULL,
1518 REG_OPTION_NON_VOLATILE,
1519 KEY_ALL_ACCESS,
1520 NULL,
1521 &hKeyEnumerator,
1522 NULL);
1523 if (lError != ERROR_SUCCESS)
1524 {
1525 return CR_REGISTRY_ERROR;
1526 }
1527
1528 /* Open or create the device key */
1529 lError = RegCreateKeyExW(hKeyEnumerator,
1530 szDevice,
1531 0,
1532 NULL,
1533 REG_OPTION_NON_VOLATILE,
1534 KEY_ALL_ACCESS,
1535 NULL,
1536 &hKeyDevice,
1537 NULL);
1538
1539 /* Close the enumerator key */
1540 RegCloseKey(hKeyEnumerator);
1541
1542 if (lError != ERROR_SUCCESS)
1543 {
1544 return CR_REGISTRY_ERROR;
1545 }
1546
1547 /* Try to open the instance key and fail if it exists */
1548 lError = RegOpenKeyExW(hKeyDevice,
1549 szInstance,
1550 0,
1551 KEY_SET_VALUE,
1552 &hKeyInstance);
1553 if (lError == ERROR_SUCCESS)
1554 {
1555 DPRINT1("Instance %S already exists!\n", szInstance);
1556 RegCloseKey(hKeyInstance);
1557 RegCloseKey(hKeyDevice);
1558 return CR_ALREADY_SUCH_DEVINST;
1559 }
1560
1561 /* Create a new instance key */
1562 lError = RegCreateKeyExW(hKeyDevice,
1563 szInstance,
1564 0,
1565 NULL,
1566 REG_OPTION_NON_VOLATILE,
1567 KEY_ALL_ACCESS,
1568 NULL,
1569 &hKeyInstance,
1570 NULL);
1571
1572 /* Close the device key */
1573 RegCloseKey(hKeyDevice);
1574
1575 if (lError != ERROR_SUCCESS)
1576 {
1577 return CR_REGISTRY_ERROR;
1578 }
1579
1580 /* Create the 'Control' sub key */
1581 lError = RegCreateKeyExW(hKeyInstance,
1582 L"Control",
1583 0,
1584 NULL,
1585 REG_OPTION_NON_VOLATILE,
1586 KEY_ALL_ACCESS,
1587 NULL,
1588 &hKeyControl,
1589 NULL);
1590 if (lError == ERROR_SUCCESS)
1591 {
1592 RegCloseKey(hKeyControl);
1593 }
1594
1595 RegCloseKey(hKeyInstance);
1596
1597 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
1598 }
1599
1600
1601 /* Function 28 */
1602 DWORD PNP_CreateDevInst(
1603 handle_t hBinding,
1604 LPWSTR pszDeviceID,
1605 LPWSTR pszParentDeviceID,
1606 PNP_RPC_STRING_LEN ulLength,
1607 DWORD ulFlags)
1608 {
1609 CONFIGRET ret = CR_SUCCESS;
1610
1611 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
1612
1613 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
1614 {
1615 /* FIXME */
1616 DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret);
1617 ret = CR_CALL_NOT_IMPLEMENTED;
1618 goto done;
1619 }
1620
1621 /* Create the device instance */
1622 ret = CreateDeviceInstance(pszDeviceID);
1623
1624 done:;
1625 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
1626
1627 return ret;
1628 }
1629
1630
1631 static CONFIGRET
1632 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
1633 LPWSTR pszDeviceInstanceSource)
1634 {
1635 DPRINT("MoveDeviceInstance: not implemented\n");
1636 /* FIXME */
1637 return CR_CALL_NOT_IMPLEMENTED;
1638 }
1639
1640
1641 static CONFIGRET
1642 SetupDeviceInstance(LPWSTR pszDeviceInstance,
1643 DWORD ulFlags)
1644 {
1645 DPRINT("SetupDeviceInstance: not implemented\n");
1646 /* FIXME */
1647 return CR_CALL_NOT_IMPLEMENTED;
1648 }
1649
1650
1651 static CONFIGRET
1652 EnableDeviceInstance(LPWSTR pszDeviceInstance)
1653 {
1654 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1655 CONFIGRET ret = CR_SUCCESS;
1656 NTSTATUS Status;
1657
1658 DPRINT("Enable device instance\n");
1659
1660 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
1661 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1662 if (!NT_SUCCESS(Status))
1663 ret = NtStatusToCrError(Status);
1664
1665 return ret;
1666 }
1667
1668
1669 static CONFIGRET
1670 DisableDeviceInstance(LPWSTR pszDeviceInstance)
1671 {
1672 DPRINT("DisableDeviceInstance: not implemented\n");
1673 /* FIXME */
1674 return CR_CALL_NOT_IMPLEMENTED;
1675 }
1676
1677
1678 static CONFIGRET
1679 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
1680 {
1681 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1682 /* FIXME */
1683 return CR_CALL_NOT_IMPLEMENTED;
1684 }
1685
1686
1687 /* Function 29 */
1688 DWORD PNP_DeviceInstanceAction(
1689 handle_t hBinding,
1690 DWORD ulAction,
1691 DWORD ulFlags,
1692 LPWSTR pszDeviceInstance1,
1693 LPWSTR pszDeviceInstance2)
1694 {
1695 CONFIGRET ret = CR_SUCCESS;
1696
1697 UNREFERENCED_PARAMETER(hBinding);
1698
1699 DPRINT("PNP_DeviceInstanceAction() called\n");
1700
1701 switch (ulAction)
1702 {
1703 case PNP_DEVINST_MOVE:
1704 ret = MoveDeviceInstance(pszDeviceInstance1,
1705 pszDeviceInstance2);
1706 break;
1707
1708 case PNP_DEVINST_SETUP:
1709 ret = SetupDeviceInstance(pszDeviceInstance1,
1710 ulFlags);
1711 break;
1712
1713 case PNP_DEVINST_ENABLE:
1714 ret = EnableDeviceInstance(pszDeviceInstance1);
1715 break;
1716
1717 case PNP_DEVINST_DISABLE:
1718 ret = DisableDeviceInstance(pszDeviceInstance1);
1719 break;
1720
1721 case PNP_DEVINST_REENUMERATE:
1722 ret = ReenumerateDeviceInstance(pszDeviceInstance1);
1723 break;
1724
1725 default:
1726 DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
1727 ret = CR_CALL_NOT_IMPLEMENTED;
1728 }
1729
1730 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1731
1732 return ret;
1733 }
1734
1735
1736 /* Function 30 */
1737 DWORD PNP_GetDeviceStatus(
1738 handle_t hBinding,
1739 LPWSTR pDeviceID,
1740 DWORD *pulStatus,
1741 DWORD *pulProblem,
1742 DWORD ulFlags)
1743 {
1744 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1745 CONFIGRET ret = CR_SUCCESS;
1746 NTSTATUS Status;
1747
1748 UNREFERENCED_PARAMETER(hBinding);
1749 UNREFERENCED_PARAMETER(ulFlags);
1750
1751 DPRINT("PNP_GetDeviceStatus() called\n");
1752
1753 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1754 pDeviceID);
1755 PlugPlayData.Operation = 0; /* Get status */
1756
1757 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1758 (PVOID)&PlugPlayData,
1759 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1760 if (NT_SUCCESS(Status))
1761 {
1762 *pulStatus = PlugPlayData.DeviceStatus;
1763 *pulProblem = PlugPlayData.DeviceProblem;
1764 }
1765 else
1766 {
1767 ret = NtStatusToCrError(Status);
1768 }
1769
1770 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1771
1772 return ret;
1773 }
1774
1775
1776 /* Function 31 */
1777 DWORD PNP_SetDeviceProblem(
1778 handle_t hBinding,
1779 LPWSTR pDeviceID,
1780 DWORD ulProblem,
1781 DWORD ulFlags)
1782 {
1783 UNIMPLEMENTED;
1784 return CR_CALL_NOT_IMPLEMENTED;
1785 }
1786
1787
1788 /* Function 32 */
1789 DWORD PNP_DisableDevInst(
1790 handle_t hBinding,
1791 LPWSTR pDeviceID,
1792 PPNP_VETO_TYPE pVetoType,
1793 LPWSTR pszVetoName,
1794 DWORD ulNameLength,
1795 DWORD ulFlags)
1796 {
1797 UNIMPLEMENTED;
1798 return CR_CALL_NOT_IMPLEMENTED;
1799 }
1800
1801 /* Function 33 */
1802 DWORD PNP_UninstallDevInst(
1803 handle_t hBinding,
1804 LPWSTR pDeviceID,
1805 DWORD ulFlags)
1806 {
1807 UNIMPLEMENTED;
1808 return CR_CALL_NOT_IMPLEMENTED;
1809 }
1810
1811
1812 static BOOL
1813 CheckForDeviceId(LPWSTR lpDeviceIdList,
1814 LPWSTR lpDeviceId)
1815 {
1816 LPWSTR lpPtr;
1817 DWORD dwLength;
1818
1819 lpPtr = lpDeviceIdList;
1820 while (*lpPtr != 0)
1821 {
1822 dwLength = wcslen(lpPtr);
1823 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1824 return TRUE;
1825
1826 lpPtr += (dwLength + 1);
1827 }
1828
1829 return FALSE;
1830 }
1831
1832
1833 static VOID
1834 AppendDeviceId(LPWSTR lpDeviceIdList,
1835 LPDWORD lpDeviceIdListSize,
1836 LPWSTR lpDeviceId)
1837 {
1838 DWORD dwLen;
1839 DWORD dwPos;
1840
1841 dwLen = wcslen(lpDeviceId);
1842 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1843
1844 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1845
1846 dwPos += (dwLen + 1);
1847
1848 lpDeviceIdList[dwPos] = 0;
1849
1850 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1851 }
1852
1853
1854 /* Function 34 */
1855 DWORD PNP_AddID(
1856 handle_t hBinding,
1857 LPWSTR pszDeviceID,
1858 LPWSTR pszID,
1859 DWORD ulFlags)
1860 {
1861 CONFIGRET ret = CR_SUCCESS;
1862 HKEY hDeviceKey;
1863 LPWSTR pszSubKey;
1864 DWORD dwDeviceIdListSize;
1865 DWORD dwNewDeviceIdSize;
1866 WCHAR * pszDeviceIdList = NULL;
1867
1868 UNREFERENCED_PARAMETER(hBinding);
1869
1870 DPRINT("PNP_AddID() called\n");
1871 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1872 DPRINT(" DeviceId: %S\n", pszID);
1873 DPRINT(" Flags: %lx\n", ulFlags);
1874
1875 if (RegOpenKeyExW(hEnumKey,
1876 pszDeviceID,
1877 0,
1878 KEY_QUERY_VALUE | KEY_SET_VALUE,
1879 &hDeviceKey) != ERROR_SUCCESS)
1880 {
1881 DPRINT("Failed to open the device key!\n");
1882 return CR_INVALID_DEVNODE;
1883 }
1884
1885 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1886
1887 if (RegQueryValueExW(hDeviceKey,
1888 pszSubKey,
1889 NULL,
1890 NULL,
1891 NULL,
1892 &dwDeviceIdListSize) != ERROR_SUCCESS)
1893 {
1894 DPRINT("Failed to query the desired ID string!\n");
1895 ret = CR_REGISTRY_ERROR;
1896 goto Done;
1897 }
1898
1899 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1900 if (!dwNewDeviceIdSize)
1901 {
1902 ret = CR_INVALID_POINTER;
1903 goto Done;
1904 }
1905
1906 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1907
1908 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1909 if (!pszDeviceIdList)
1910 {
1911 DPRINT("Failed to allocate memory for the desired ID string!\n");
1912 ret = CR_OUT_OF_MEMORY;
1913 goto Done;
1914 }
1915
1916 if (RegQueryValueExW(hDeviceKey,
1917 pszSubKey,
1918 NULL,
1919 NULL,
1920 (LPBYTE)pszDeviceIdList,
1921 &dwDeviceIdListSize) != ERROR_SUCCESS)
1922 {
1923 DPRINT("Failed to query the desired ID string!\n");
1924 ret = CR_REGISTRY_ERROR;
1925 goto Done;
1926 }
1927
1928 /* Check whether the device ID is already in use */
1929 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1930 {
1931 DPRINT("Device ID was found in the ID string!\n");
1932 ret = CR_SUCCESS;
1933 goto Done;
1934 }
1935
1936 /* Append the Device ID */
1937 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1938
1939 if (RegSetValueExW(hDeviceKey,
1940 pszSubKey,
1941 0,
1942 REG_MULTI_SZ,
1943 (LPBYTE)pszDeviceIdList,
1944 dwDeviceIdListSize) != ERROR_SUCCESS)
1945 {
1946 DPRINT("Failed to set the desired ID string!\n");
1947 ret = CR_REGISTRY_ERROR;
1948 }
1949
1950 Done:
1951 RegCloseKey(hDeviceKey);
1952 if (pszDeviceIdList)
1953 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1954
1955 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1956
1957 return ret;
1958 }
1959
1960
1961 /* Function 35 */
1962 DWORD PNP_RegisterDriver(
1963 handle_t hBinding,
1964 LPWSTR pszDeviceID,
1965 DWORD ulFlags)
1966 {
1967 UNIMPLEMENTED;
1968 return CR_CALL_NOT_IMPLEMENTED;
1969 }
1970
1971
1972 /* Function 36 */
1973 DWORD PNP_QueryRemove(
1974 handle_t hBinding,
1975 LPWSTR pszDeviceID,
1976 PPNP_VETO_TYPE pVetoType,
1977 LPWSTR pszVetoName,
1978 DWORD ulNameLength,
1979 DWORD ulFlags)
1980 {
1981 UNIMPLEMENTED;
1982 return CR_CALL_NOT_IMPLEMENTED;
1983 }
1984
1985
1986 /* Function 37 */
1987 DWORD PNP_RequestDeviceEject(
1988 handle_t hBinding,
1989 LPWSTR pszDeviceID,
1990 PPNP_VETO_TYPE pVetoType,
1991 LPWSTR pszVetoName,
1992 DWORD ulNameLength,
1993 DWORD ulFlags)
1994 {
1995 UNIMPLEMENTED;
1996 return CR_CALL_NOT_IMPLEMENTED;
1997 }
1998
1999 /* Function 38 */
2000 CONFIGRET
2001 PNP_IsDockStationPresent(handle_t hBinding,
2002 BOOL *Present)
2003 {
2004 HKEY hKey;
2005 DWORD dwType;
2006 DWORD dwValue;
2007 DWORD dwSize;
2008 CONFIGRET ret = CR_SUCCESS;
2009
2010 UNREFERENCED_PARAMETER(hBinding);
2011
2012 DPRINT1("PNP_IsDockStationPresent() called\n");
2013
2014 *Present = FALSE;
2015
2016 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
2017 L"CurrentDockInfo",
2018 0,
2019 KEY_READ,
2020 &hKey) != ERROR_SUCCESS)
2021 return CR_REGISTRY_ERROR;
2022
2023 dwSize = sizeof(DWORD);
2024 if (RegQueryValueExW(hKey,
2025 L"DockingState",
2026 NULL,
2027 &dwType,
2028 (LPBYTE)&dwValue,
2029 &dwSize) != ERROR_SUCCESS)
2030 ret = CR_REGISTRY_ERROR;
2031
2032 RegCloseKey(hKey);
2033
2034 if (ret == CR_SUCCESS)
2035 {
2036 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
2037 {
2038 ret = CR_REGISTRY_ERROR;
2039 }
2040 else if (dwValue != 0)
2041 {
2042 *Present = TRUE;
2043 }
2044 }
2045
2046 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
2047
2048 return ret;
2049 }
2050
2051
2052 /* Function 39 */
2053 DWORD PNP_RequestEjectPC(
2054 handle_t hBinding)
2055 {
2056 UNIMPLEMENTED;
2057 return CR_CALL_NOT_IMPLEMENTED;
2058 }
2059
2060
2061 /* Function 40 */
2062 DWORD PNP_HwProfFlags(
2063 handle_t hBinding,
2064 DWORD ulAction,
2065 LPWSTR pDeviceID,
2066 DWORD ulConfig,
2067 DWORD *pulValue,
2068 PPNP_VETO_TYPE pVetoType,
2069 LPWSTR pszVetoName,
2070 DWORD ulNameLength,
2071 DWORD ulFlags)
2072 {
2073 CONFIGRET ret = CR_SUCCESS;
2074 WCHAR szKeyName[MAX_PATH];
2075 HKEY hKey;
2076 HKEY hDeviceKey;
2077 DWORD dwSize;
2078
2079 UNREFERENCED_PARAMETER(hBinding);
2080
2081 DPRINT("PNP_HwProfFlags() called\n");
2082
2083 if (ulConfig == 0)
2084 {
2085 wcscpy(szKeyName,
2086 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
2087 }
2088 else
2089 {
2090 swprintf(szKeyName,
2091 L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
2092 ulConfig);
2093 }
2094
2095 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2096 szKeyName,
2097 0,
2098 KEY_QUERY_VALUE,
2099 &hKey) != ERROR_SUCCESS)
2100 return CR_REGISTRY_ERROR;
2101
2102 if (ulAction == PNP_GET_HWPROFFLAGS)
2103 {
2104 if (RegOpenKeyExW(hKey,
2105 pDeviceID,
2106 0,
2107 KEY_QUERY_VALUE,
2108 &hDeviceKey) != ERROR_SUCCESS)
2109 {
2110 *pulValue = 0;
2111 }
2112 else
2113 {
2114 dwSize = sizeof(DWORD);
2115 if (!RegQueryValueExW(hDeviceKey,
2116 L"CSConfigFlags",
2117 NULL,
2118 NULL,
2119 (LPBYTE)pulValue,
2120 &dwSize) != ERROR_SUCCESS)
2121 {
2122 *pulValue = 0;
2123 }
2124
2125 RegCloseKey(hDeviceKey);
2126 }
2127 }
2128 else if (ulAction == PNP_SET_HWPROFFLAGS)
2129 {
2130 /* FIXME: not implemented yet */
2131 ret = CR_CALL_NOT_IMPLEMENTED;
2132 }
2133
2134 RegCloseKey(hKey);
2135
2136 return ret;
2137 }
2138
2139
2140 /* Function 41 */
2141 DWORD PNP_GetHwProfInfo(
2142 handle_t hBinding,
2143 DWORD ulIndex,
2144 HWPROFILEINFO *pHWProfileInfo,
2145 DWORD ulProfileInfoSize,
2146 DWORD ulFlags)
2147 {
2148 UNIMPLEMENTED;
2149 return CR_CALL_NOT_IMPLEMENTED;
2150 }
2151
2152
2153 /* Function 42 */
2154 DWORD PNP_AddEmptyLogConf(
2155 handle_t hBinding,
2156 LPWSTR pDeviceID,
2157 DWORD ulPriority,
2158 DWORD *pulLogConfTag,
2159 DWORD ulFlags)
2160 {
2161 UNIMPLEMENTED;
2162 return CR_CALL_NOT_IMPLEMENTED;
2163 }
2164
2165
2166 /* Function 43 */
2167 DWORD PNP_FreeLogConf(
2168 handle_t hBinding,
2169 LPWSTR pDeviceID,
2170 DWORD ulLogConfType,
2171 DWORD ulLogConfTag,
2172 DWORD ulFlags)
2173 {
2174 UNIMPLEMENTED;
2175 return CR_CALL_NOT_IMPLEMENTED;
2176 }
2177
2178
2179 /* Function 44 */
2180 DWORD PNP_GetFirstLogConf(
2181 handle_t hBinding,
2182 LPWSTR pDeviceID,
2183 DWORD ulLogConfType,
2184 DWORD *pulLogConfTag,
2185 DWORD ulFlags)
2186 {
2187 UNIMPLEMENTED;
2188 return CR_CALL_NOT_IMPLEMENTED;
2189 }
2190
2191
2192 /* Function 45 */
2193 DWORD PNP_GetNextLogConf(
2194 handle_t hBinding,
2195 LPWSTR pDeviceID,
2196 DWORD ulLogConfType,
2197 DWORD ulCurrentTag,
2198 DWORD *pulNextTag,
2199 DWORD ulFlags)
2200 {
2201 UNIMPLEMENTED;
2202 return CR_CALL_NOT_IMPLEMENTED;
2203 }
2204
2205
2206 /* Function 46 */
2207 DWORD PNP_GetLogConfPriority(
2208 handle_t hBinding,
2209 LPWSTR pDeviceID,
2210 DWORD ulType,
2211 DWORD ulTag,
2212 DWORD *pPriority,
2213 DWORD ulFlags)
2214 {
2215 UNIMPLEMENTED;
2216 return CR_CALL_NOT_IMPLEMENTED;
2217 }
2218
2219
2220 /* Function 47 */
2221 DWORD PNP_AddResDes(
2222 handle_t hBinding,
2223 LPWSTR pDeviceID,
2224 DWORD ulLogConfTag,
2225 DWORD ulLogConfType,
2226 RESOURCEID ResourceID,
2227 DWORD *pulResourceTag,
2228 BYTE *ResourceData,
2229 PNP_RPC_BUFFER_SIZE ResourceLen,
2230 DWORD ulFlags)
2231 {
2232 UNIMPLEMENTED;
2233 return CR_CALL_NOT_IMPLEMENTED;
2234 }
2235
2236
2237 /* Function 48 */
2238 DWORD PNP_FreeResDes(
2239 handle_t hBinding,
2240 LPWSTR pDeviceID,
2241 DWORD ulLogConfTag,
2242 DWORD ulLogConfType,
2243 RESOURCEID ResourceID,
2244 DWORD ulResourceTag,
2245 DWORD *pulPreviousResType,
2246 DWORD *pulPreviousResTag,
2247 DWORD ulFlags)
2248 {
2249 UNIMPLEMENTED;
2250 return CR_CALL_NOT_IMPLEMENTED;
2251 }
2252
2253
2254 /* Function 49 */
2255 DWORD PNP_GetNextResDes(
2256 handle_t hBinding,
2257 LPWSTR pDeviceID,
2258 DWORD ulLogConfTag,
2259 DWORD ulLogConfType,
2260 RESOURCEID ResourceID,
2261 DWORD ulResourceTag,
2262 DWORD *pulNextResType,
2263 DWORD *pulNextResTag,
2264 DWORD ulFlags)
2265 {
2266 UNIMPLEMENTED;
2267 return CR_CALL_NOT_IMPLEMENTED;
2268 }
2269
2270
2271 /* Function 50 */
2272 DWORD PNP_GetResDesData(
2273 handle_t hBinding,
2274 LPWSTR pDeviceID,
2275 DWORD ulLogConfTag,
2276 DWORD ulLogConfType,
2277 RESOURCEID ResourceID,
2278 DWORD ulResourceTag,
2279 BYTE *Buffer,
2280 PNP_RPC_BUFFER_SIZE BufferLen,
2281 DWORD ulFlags)
2282 {
2283 UNIMPLEMENTED;
2284 return CR_CALL_NOT_IMPLEMENTED;
2285 }
2286
2287
2288 /* Function 51 */
2289 DWORD PNP_GetResDesDataSize(
2290 handle_t hBinding,
2291 LPWSTR pDeviceID,
2292 DWORD ulLogConfTag,
2293 DWORD ulLogConfType,
2294 RESOURCEID ResourceID,
2295 DWORD ulResourceTag,
2296 DWORD *pulSize,
2297 DWORD ulFlags)
2298 {
2299 UNIMPLEMENTED;
2300 return CR_CALL_NOT_IMPLEMENTED;
2301 }
2302
2303
2304 /* Function 52 */
2305 DWORD PNP_ModifyResDes(
2306 handle_t hBinding,
2307 LPWSTR pDeviceID,
2308 DWORD ulLogConfTag,
2309 DWORD ulLogConfType,
2310 RESOURCEID CurrentResourceID,
2311 RESOURCEID NewResourceID,
2312 DWORD ulResourceTag,
2313 BYTE *ResourceData,
2314 PNP_RPC_BUFFER_SIZE ResourceLen,
2315 DWORD ulFlags)
2316 {
2317 UNIMPLEMENTED;
2318 return CR_CALL_NOT_IMPLEMENTED;
2319 }
2320
2321
2322 /* Function 53 */
2323 DWORD PNP_DetectResourceConflict(
2324 handle_t hBinding,
2325 LPWSTR pDeviceID,
2326 RESOURCEID ResourceID,
2327 BYTE *ResourceData,
2328 PNP_RPC_BUFFER_SIZE ResourceLen,
2329 BOOL *pbConflictDetected,
2330 DWORD ulFlags)
2331 {
2332 UNIMPLEMENTED;
2333 return CR_CALL_NOT_IMPLEMENTED;
2334 }
2335
2336
2337 /* Function 54 */
2338 DWORD PNP_QueryResConfList(
2339 handle_t hBinding,
2340 LPWSTR pDeviceID,
2341 RESOURCEID ResourceID,
2342 BYTE *ResourceData,
2343 PNP_RPC_BUFFER_SIZE ResourceLen,
2344 BYTE *Buffer,
2345 PNP_RPC_BUFFER_SIZE BufferLen,
2346 DWORD ulFlags)
2347 {
2348 UNIMPLEMENTED;
2349 return CR_CALL_NOT_IMPLEMENTED;
2350 }
2351
2352
2353 /* Function 55 */
2354 DWORD PNP_SetHwProf(
2355 handle_t hBinding,
2356 DWORD ulHardwareProfile,
2357 DWORD ulFlags)
2358 {
2359 UNIMPLEMENTED;
2360 return CR_CALL_NOT_IMPLEMENTED;
2361 }
2362
2363
2364 /* Function 56 */
2365 DWORD PNP_QueryArbitratorFreeData(
2366 handle_t hBinding,
2367 BYTE *pData,
2368 DWORD DataLen,
2369 LPWSTR pDeviceID,
2370 RESOURCEID ResourceID,
2371 DWORD ulFlags)
2372 {
2373 UNIMPLEMENTED;
2374 return CR_CALL_NOT_IMPLEMENTED;
2375 }
2376
2377
2378 /* Function 57 */
2379 DWORD PNP_QueryArbitratorFreeSize(
2380 handle_t hBinding,
2381 DWORD *pulSize,
2382 LPWSTR pDeviceID,
2383 RESOURCEID ResourceID,
2384 DWORD ulFlags)
2385 {
2386 UNIMPLEMENTED;
2387 return CR_CALL_NOT_IMPLEMENTED;
2388 }
2389
2390
2391 /* Function 58 */
2392 CONFIGRET
2393 PNP_RunDetection(
2394 handle_t hBinding,
2395 DWORD ulFlags)
2396 {
2397 return CR_CALL_NOT_IMPLEMENTED;
2398 }
2399
2400
2401 /* Function 59 */
2402 DWORD PNP_RegisterNotification(
2403 handle_t hBinding)
2404 {
2405 UNIMPLEMENTED;
2406 return CR_CALL_NOT_IMPLEMENTED;
2407 }
2408
2409
2410 /* Function 60 */
2411 DWORD PNP_UnregisterNotification(
2412 handle_t hBinding)
2413 {
2414 UNIMPLEMENTED;
2415 return CR_CALL_NOT_IMPLEMENTED;
2416 }
2417
2418
2419 /* Function 61 */
2420 DWORD PNP_GetCustomDevProp(
2421 handle_t hBinding,
2422 LPWSTR pDeviceID,
2423 LPWSTR CustomPropName,
2424 DWORD *pulRegDataType,
2425 BYTE *Buffer,
2426 PNP_RPC_STRING_LEN *pulTransferLen,
2427 PNP_RPC_STRING_LEN *pulLength,
2428 DWORD ulFlags)
2429 {
2430 UNIMPLEMENTED;
2431 return CR_CALL_NOT_IMPLEMENTED;
2432 }
2433
2434
2435 /* Function 62 */
2436 DWORD PNP_GetVersionInternal(
2437 handle_t hBinding,
2438 WORD *pwVersion)
2439 {
2440 UNIMPLEMENTED;
2441 return CR_CALL_NOT_IMPLEMENTED;
2442 }
2443
2444
2445 /* Function 63 */
2446 DWORD PNP_GetBlockedDriverInfo(
2447 handle_t hBinding,
2448 BYTE *Buffer,
2449 PNP_RPC_BUFFER_SIZE *pulTransferLen,
2450 PNP_RPC_BUFFER_SIZE *pulLength,
2451 DWORD ulFlags)
2452 {
2453 UNIMPLEMENTED;
2454 return CR_CALL_NOT_IMPLEMENTED;
2455 }
2456
2457
2458 /* Function 64 */
2459 DWORD PNP_GetServerSideDeviceInstallFlags(
2460 handle_t hBinding,
2461 DWORD *pulSSDIFlags,
2462 DWORD ulFlags)
2463 {
2464 UNIMPLEMENTED;
2465 return CR_CALL_NOT_IMPLEMENTED;
2466 }
2467
2468
2469 /* Function 65 */
2470 DWORD PNP_GetObjectPropKeys(
2471 handle_t hBinding,
2472 LPWSTR ObjectName,
2473 DWORD ObjectType,
2474 LPWSTR PropertyCultureName,
2475 PNP_PROP_COUNT *PropertyCount,
2476 PNP_PROP_COUNT *TransferLen,
2477 DEVPROPKEY *PropertyKeys,
2478 DWORD Flags)
2479 {
2480 UNIMPLEMENTED;
2481 return CR_CALL_NOT_IMPLEMENTED;
2482 }
2483
2484
2485 /* Function 66 */
2486 DWORD PNP_GetObjectProp(
2487 handle_t hBinding,
2488 LPWSTR ObjectName,
2489 DWORD ObjectType,
2490 LPWSTR PropertyCultureName,
2491 const DEVPROPKEY *PropertyKey,
2492 DEVPROPTYPE *PropertyType,
2493 PNP_PROP_SIZE *PropertySize,
2494 PNP_PROP_SIZE *TransferLen,
2495 BYTE *PropertyBuffer,
2496 DWORD Flags)
2497 {
2498 UNIMPLEMENTED;
2499 return CR_CALL_NOT_IMPLEMENTED;
2500 }
2501
2502
2503 /* Function 67 */
2504 DWORD PNP_SetObjectProp(
2505 handle_t hBinding,
2506 LPWSTR ObjectName,
2507 DWORD ObjectType,
2508 LPWSTR PropertyCultureName,
2509 const DEVPROPKEY *PropertyKey,
2510 DEVPROPTYPE PropertyType,
2511 PNP_PROP_SIZE PropertySize,
2512 BYTE *PropertyBuffer,
2513 DWORD Flags)
2514 {
2515 UNIMPLEMENTED;
2516 return CR_CALL_NOT_IMPLEMENTED;
2517 }
2518
2519
2520 /* Function 68 */
2521 DWORD PNP_InstallDevInst(
2522 handle_t hBinding)
2523 {
2524 UNIMPLEMENTED;
2525 return CR_CALL_NOT_IMPLEMENTED;
2526 }
2527
2528
2529 /* Function 69 */
2530 DWORD PNP_ApplyPowerSettings(
2531 handle_t hBinding)
2532 {
2533 UNIMPLEMENTED;
2534 return CR_CALL_NOT_IMPLEMENTED;
2535 }
2536
2537
2538 /* Function 70 */
2539 DWORD PNP_DriverStoreAddDriverPackage(
2540 handle_t hBinding)
2541 {
2542 UNIMPLEMENTED;
2543 return CR_CALL_NOT_IMPLEMENTED;
2544 }
2545
2546
2547 /* Function 71 */
2548 DWORD PNP_DriverStoreDeleteDriverPackage(
2549 handle_t hBinding)
2550 {
2551 UNIMPLEMENTED;
2552 return CR_CALL_NOT_IMPLEMENTED;
2553 }
2554
2555
2556 /* Function 72 */
2557 DWORD PNP_RegisterServiceNotification(
2558 handle_t hBinding)
2559 {
2560 UNIMPLEMENTED;
2561 return CR_CALL_NOT_IMPLEMENTED;
2562 }
2563
2564
2565 /* Function 73 */
2566 DWORD PNP_SetActiveService(
2567 handle_t hBinding)
2568 {
2569 UNIMPLEMENTED;
2570 return CR_CALL_NOT_IMPLEMENTED;
2571 }
2572
2573
2574 /* Function 74 */
2575 DWORD PNP_DeleteServiceDevices(
2576 handle_t hBinding)
2577 {
2578 UNIMPLEMENTED;
2579 return CR_CALL_NOT_IMPLEMENTED;
2580 }
2581
2582
2583 static BOOL
2584 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
2585 {
2586 BOOL DeviceInstalled = FALSE;
2587 DWORD BytesWritten;
2588 DWORD Value;
2589 HANDLE hPipe = INVALID_HANDLE_VALUE;
2590 LPVOID Environment = NULL;
2591 PROCESS_INFORMATION ProcessInfo;
2592 STARTUPINFOW StartupInfo;
2593 UUID RandomUuid;
2594 HKEY DeviceKey;
2595
2596 /* The following lengths are constant (see below), they cannot overflow */
2597 WCHAR CommandLine[116];
2598 WCHAR InstallEventName[73];
2599 WCHAR PipeName[74];
2600 WCHAR UuidString[39];
2601
2602 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
2603
2604 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
2605
2606 if (RegOpenKeyExW(hEnumKey,
2607 DeviceInstance,
2608 0,
2609 KEY_QUERY_VALUE,
2610 &DeviceKey) == ERROR_SUCCESS)
2611 {
2612 if (RegQueryValueExW(DeviceKey,
2613 L"ClassGUID",
2614 NULL,
2615 NULL,
2616 NULL,
2617 NULL) == ERROR_SUCCESS)
2618 {
2619 DPRINT("No need to install: %S\n", DeviceInstance);
2620 RegCloseKey(DeviceKey);
2621 return TRUE;
2622 }
2623
2624 RegCloseKey(DeviceKey);
2625 }
2626
2627 DPRINT1("Installing: %S\n", DeviceInstance);
2628
2629 /* Create a random UUID for the named pipe */
2630 UuidCreate(&RandomUuid);
2631 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2632 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
2633 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
2634 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
2635 RandomUuid.Data4[6], RandomUuid.Data4[7]);
2636
2637 /* Create the named pipe */
2638 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2639 wcscat(PipeName, UuidString);
2640 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
2641
2642 if(hPipe == INVALID_HANDLE_VALUE)
2643 {
2644 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2645 goto cleanup;
2646 }
2647
2648 /* Launch rundll32 to call ClientSideInstallW */
2649 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
2650 wcscat(CommandLine, PipeName);
2651
2652 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
2653 StartupInfo.cb = sizeof(StartupInfo);
2654
2655 if(hUserToken)
2656 {
2657 /* newdev has to run under the environment of the current user */
2658 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
2659 {
2660 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2661 goto cleanup;
2662 }
2663
2664 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
2665 {
2666 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2667 goto cleanup;
2668 }
2669 }
2670 else
2671 {
2672 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2673
2674 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2675 (ShowWizard is only set to FALSE for these two modes) */
2676 ASSERT(!ShowWizard);
2677
2678 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2679 {
2680 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2681 goto cleanup;
2682 }
2683 }
2684
2685 /* Wait for the function to connect to our pipe */
2686 if(!ConnectNamedPipe(hPipe, NULL))
2687 {
2688 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2689 goto cleanup;
2690 }
2691
2692 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2693 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2694 wcscat(InstallEventName, UuidString);
2695
2696 Value = sizeof(InstallEventName);
2697 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2698 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2699
2700 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2701 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2702 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2703
2704 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2705 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2706 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2707
2708 /* Wait for newdev.dll to finish processing */
2709 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2710
2711 /* The following check for success is probably not compatible to Windows, but should do its job */
2712 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2713 {
2714 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2715 goto cleanup;
2716 }
2717
2718 DeviceInstalled = Value;
2719
2720 cleanup:
2721 if(hPipe != INVALID_HANDLE_VALUE)
2722 CloseHandle(hPipe);
2723
2724 if(Environment)
2725 DestroyEnvironmentBlock(Environment);
2726
2727 if(ProcessInfo.hProcess)
2728 CloseHandle(ProcessInfo.hProcess);
2729
2730 if(ProcessInfo.hThread)
2731 CloseHandle(ProcessInfo.hThread);
2732
2733 DPRINT1("Success? %d\n", DeviceInstalled);
2734
2735 return DeviceInstalled;
2736 }
2737
2738
2739 static LONG
2740 ReadRegSzKey(
2741 IN HKEY hKey,
2742 IN LPCWSTR pszKey,
2743 OUT LPWSTR* pValue)
2744 {
2745 LONG rc;
2746 DWORD dwType;
2747 DWORD cbData = 0;
2748 LPWSTR Value;
2749
2750 if (!pValue)
2751 return ERROR_INVALID_PARAMETER;
2752
2753 *pValue = NULL;
2754 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2755 if (rc != ERROR_SUCCESS)
2756 return rc;
2757 if (dwType != REG_SZ)
2758 return ERROR_FILE_NOT_FOUND;
2759 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2760 if (!Value)
2761 return ERROR_NOT_ENOUGH_MEMORY;
2762 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2763 if (rc != ERROR_SUCCESS)
2764 {
2765 HeapFree(GetProcessHeap(), 0, Value);
2766 return rc;
2767 }
2768 /* NULL-terminate the string */
2769 Value[cbData / sizeof(WCHAR)] = '\0';
2770
2771 *pValue = Value;
2772 return ERROR_SUCCESS;
2773 }
2774
2775
2776 static BOOL
2777 SetupIsActive(VOID)
2778 {
2779 HKEY hKey = NULL;
2780 DWORD regType, active, size;
2781 LONG rc;
2782 BOOL ret = FALSE;
2783
2784 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2785 if (rc != ERROR_SUCCESS)
2786 goto cleanup;
2787
2788 size = sizeof(DWORD);
2789 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2790 if (rc != ERROR_SUCCESS)
2791 goto cleanup;
2792 if (regType != REG_DWORD || size != sizeof(DWORD))
2793 goto cleanup;
2794
2795 ret = (active != 0);
2796
2797 cleanup:
2798 if (hKey != NULL)
2799 RegCloseKey(hKey);
2800
2801 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2802
2803 return ret;
2804 }
2805
2806
2807 static BOOL
2808 IsConsoleBoot(VOID)
2809 {
2810 HKEY ControlKey = NULL;
2811 LPWSTR SystemStartOptions = NULL;
2812 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2813 BOOL ConsoleBoot = FALSE;
2814 LONG rc;
2815
2816 rc = RegOpenKeyExW(
2817 HKEY_LOCAL_MACHINE,
2818 L"SYSTEM\\CurrentControlSet\\Control",
2819 0,
2820 KEY_QUERY_VALUE,
2821 &ControlKey);
2822
2823 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2824 if (rc != ERROR_SUCCESS)
2825 goto cleanup;
2826
2827 /* Check for CMDCONS in SystemStartOptions */
2828 CurrentOption = SystemStartOptions;
2829 while (CurrentOption)
2830 {
2831 NextOption = wcschr(CurrentOption, L' ');
2832 if (NextOption)
2833 *NextOption = L'\0';
2834 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2835 {
2836 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2837 ConsoleBoot = TRUE;
2838 goto cleanup;
2839 }
2840 CurrentOption = NextOption ? NextOption + 1 : NULL;
2841 }
2842
2843 cleanup:
2844 if (ControlKey != NULL)
2845 RegCloseKey(ControlKey);
2846 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2847 return ConsoleBoot;
2848 }
2849
2850
2851 /* Loop to install all queued devices installations */
2852 static DWORD WINAPI
2853 DeviceInstallThread(LPVOID lpParameter)
2854 {
2855 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2856 PSLIST_ENTRY ListEntry;
2857 #else
2858 PLIST_ENTRY ListEntry;
2859 #endif
2860 DeviceInstallParams* Params;
2861 BOOL showWizard;
2862
2863 UNREFERENCED_PARAMETER(lpParameter);
2864
2865 WaitForSingleObject(hInstallEvent, INFINITE);
2866
2867 showWizard = !SetupIsActive() && !IsConsoleBoot();
2868
2869 while (TRUE)
2870 {
2871 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2872 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2873 #else
2874 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2875 ListEntry = NULL;
2876 else
2877 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2878 #endif
2879 if (ListEntry == NULL)
2880 {
2881 SetEvent(hNoPendingInstalls);
2882 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2883 }
2884 else
2885 {
2886 ResetEvent(hNoPendingInstalls);
2887 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2888 InstallDevice(Params->DeviceIds, showWizard);
2889 }
2890 }
2891
2892 return 0;
2893 }
2894
2895
2896 static DWORD WINAPI
2897 PnpEventThread(LPVOID lpParameter)
2898 {
2899 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2900 ULONG PnpEventSize;
2901 NTSTATUS Status;
2902 RPC_STATUS RpcStatus;
2903
2904 UNREFERENCED_PARAMETER(lpParameter);
2905
2906 PnpEventSize = 0x1000;
2907 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2908 if (PnpEvent == NULL)
2909 return ERROR_OUTOFMEMORY;
2910
2911 for (;;)
2912 {
2913 DPRINT("Calling NtGetPlugPlayEvent()\n");
2914
2915 /* Wait for the next pnp event */
2916 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2917
2918 /* Resize the buffer for the PnP event if it's too small. */
2919 if (Status == STATUS_BUFFER_TOO_SMALL)
2920 {
2921 PnpEventSize += 0x400;
2922 HeapFree(GetProcessHeap(), 0, PnpEvent);
2923 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2924 if (PnpEvent == NULL)
2925 return ERROR_OUTOFMEMORY;
2926 continue;
2927 }
2928
2929 if (!NT_SUCCESS(Status))
2930 {
2931 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2932 break;
2933 }
2934
2935 /* Process the pnp event */
2936 DPRINT("Received PnP Event\n");
2937 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2938 {
2939 DeviceInstallParams* Params;
2940 DWORD len;
2941 DWORD DeviceIdLength;
2942
2943 DPRINT1("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
2944
2945 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2946 if (DeviceIdLength)
2947 {
2948 /* Queue device install (will be dequeued by DeviceInstallThread */
2949 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2950 Params = HeapAlloc(GetProcessHeap(), 0, len);
2951 if (Params)
2952 {
2953 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2954 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2955 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2956 #else
2957 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2958 #endif
2959 SetEvent(hDeviceInstallListNotEmpty);
2960 }
2961 }
2962 }
2963 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
2964 {
2965 DPRINT1("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
2966 /* FIXME: ? */
2967 }
2968 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
2969 {
2970 DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
2971 }
2972 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
2973 {
2974 DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
2975 }
2976 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
2977 {
2978 DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
2979 }
2980 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
2981 {
2982 DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
2983 }
2984 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
2985 {
2986 DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
2987 }
2988 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
2989 {
2990 DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
2991 }
2992 else
2993 {
2994 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2995 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2996 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2997 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2998 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2999 }
3000
3001 /* Dequeue the current pnp event and signal the next one */
3002 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
3003 }
3004
3005 HeapFree(GetProcessHeap(), 0, PnpEvent);
3006
3007 return ERROR_SUCCESS;
3008 }
3009
3010
3011 static VOID
3012 UpdateServiceStatus(DWORD dwState)
3013 {
3014 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
3015 ServiceStatus.dwCurrentState = dwState;
3016 ServiceStatus.dwControlsAccepted = 0;
3017 ServiceStatus.dwWin32ExitCode = 0;
3018 ServiceStatus.dwServiceSpecificExitCode = 0;
3019 ServiceStatus.dwCheckPoint = 0;
3020
3021 if (dwState == SERVICE_START_PENDING ||
3022 dwState == SERVICE_STOP_PENDING ||
3023 dwState == SERVICE_PAUSE_PENDING ||
3024 dwState == SERVICE_CONTINUE_PENDING)
3025 ServiceStatus.dwWaitHint = 10000;
3026 else
3027 ServiceStatus.dwWaitHint = 0;
3028
3029 SetServiceStatus(ServiceStatusHandle,
3030 &ServiceStatus);
3031 }
3032
3033
3034 static DWORD WINAPI
3035 ServiceControlHandler(DWORD dwControl,
3036 DWORD dwEventType,
3037 LPVOID lpEventData,
3038 LPVOID lpContext)
3039 {
3040 DPRINT1("ServiceControlHandler() called\n");
3041
3042 switch (dwControl)
3043 {
3044 case SERVICE_CONTROL_STOP:
3045 DPRINT1(" SERVICE_CONTROL_STOP received\n");
3046 UpdateServiceStatus(SERVICE_STOPPED);
3047 return ERROR_SUCCESS;
3048
3049 case SERVICE_CONTROL_PAUSE:
3050 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
3051 UpdateServiceStatus(SERVICE_PAUSED);
3052 return ERROR_SUCCESS;
3053
3054 case SERVICE_CONTROL_CONTINUE:
3055 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
3056 UpdateServiceStatus(SERVICE_RUNNING);
3057 return ERROR_SUCCESS;
3058
3059 case SERVICE_CONTROL_INTERROGATE:
3060 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
3061 SetServiceStatus(ServiceStatusHandle,
3062 &ServiceStatus);
3063 return ERROR_SUCCESS;
3064
3065 case SERVICE_CONTROL_SHUTDOWN:
3066 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
3067 UpdateServiceStatus(SERVICE_STOPPED);
3068 return ERROR_SUCCESS;
3069
3070 default :
3071 DPRINT1(" Control %lu received\n");
3072 return ERROR_CALL_NOT_IMPLEMENTED;
3073 }
3074 }
3075
3076
3077 static VOID CALLBACK
3078 ServiceMain(DWORD argc, LPTSTR *argv)
3079 {
3080 HANDLE hThread;
3081 DWORD dwThreadId;
3082
3083 UNREFERENCED_PARAMETER(argc);
3084 UNREFERENCED_PARAMETER(argv);
3085
3086 DPRINT("ServiceMain() called\n");
3087
3088 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
3089 ServiceControlHandler,
3090 NULL);
3091 if (!ServiceStatusHandle)
3092 {
3093 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
3094 return;
3095 }
3096
3097 UpdateServiceStatus(SERVICE_START_PENDING);
3098
3099 hThread = CreateThread(NULL,
3100 0,
3101 PnpEventThread,
3102 NULL,
3103 0,
3104 &dwThreadId);
3105 if (hThread != NULL)
3106 CloseHandle(hThread);
3107
3108 hThread = CreateThread(NULL,
3109 0,
3110 RpcServerThread,
3111 NULL,
3112 0,
3113 &dwThreadId);
3114 if (hThread != NULL)
3115 CloseHandle(hThread);
3116
3117 hThread = CreateThread(NULL,
3118 0,
3119 DeviceInstallThread,
3120 NULL,
3121 0,
3122 &dwThreadId);
3123 if (hThread != NULL)
3124 CloseHandle(hThread);
3125
3126 UpdateServiceStatus(SERVICE_RUNNING);
3127
3128 DPRINT("ServiceMain() done\n");
3129 }
3130
3131
3132 int
3133 wmain(int argc, WCHAR *argv[])
3134 {
3135 BOOLEAN OldValue;
3136 DWORD dwError;
3137
3138 UNREFERENCED_PARAMETER(argc);
3139 UNREFERENCED_PARAMETER(argv);
3140
3141 DPRINT("Umpnpmgr: main() started\n");
3142
3143 /* We need this privilege for using CreateProcessAsUserW */
3144 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
3145
3146 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
3147 if (hInstallEvent == NULL)
3148 {
3149 dwError = GetLastError();
3150 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
3151 return dwError;
3152 }
3153
3154 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
3155 if (hDeviceInstallListNotEmpty == NULL)
3156 {
3157 dwError = GetLastError();
3158 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3159 return dwError;
3160 }
3161
3162 hNoPendingInstalls = CreateEventW(NULL,
3163 TRUE,
3164 FALSE,
3165 L"Global\\PnP_No_Pending_Install_Events");
3166 if (hNoPendingInstalls == NULL)
3167 {
3168 dwError = GetLastError();
3169 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3170 return dwError;
3171 }
3172
3173 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
3174 InitializeSListHead(&DeviceInstallListHead);
3175 #else
3176 InitializeListHead(&DeviceInstallListHead);
3177 #endif
3178
3179 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3180 L"System\\CurrentControlSet\\Enum",
3181 0,
3182 KEY_ALL_ACCESS,
3183 &hEnumKey);
3184 if (dwError != ERROR_SUCCESS)
3185 {
3186 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
3187 return dwError;
3188 }
3189
3190 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3191 L"System\\CurrentControlSet\\Control\\Class",
3192 0,
3193 KEY_ALL_ACCESS,
3194 &hClassKey);
3195 if (dwError != ERROR_SUCCESS)
3196 {
3197 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
3198 return dwError;
3199 }
3200
3201 StartServiceCtrlDispatcher(ServiceTable);
3202
3203 DPRINT("Umpnpmgr: main() done\n");
3204
3205 ExitThread(0);
3206
3207 return 0;
3208 }
3209
3210 /* EOF */