fb04757ab972814d8dcdf9cd555254d6270a459a
[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 CONFIGRET ret = CR_SUCCESS;
1253 LPWSTR lpValueName = NULL;
1254 HKEY hInstKey = 0;
1255 HKEY hPropKey = 0;
1256 LONG lError;
1257
1258 UNREFERENCED_PARAMETER(hBinding);
1259
1260 DPRINT("PNP_SetClassRegProp() called\n");
1261
1262 if (ulFlags != 0)
1263 return CR_INVALID_FLAG;
1264
1265 switch (ulProperty)
1266 {
1267 case CM_DRP_SECURITY:
1268 lpValueName = L"Security";
1269 break;
1270
1271 case CM_DRP_DEVTYPE:
1272 lpValueName = L"DeviceType";
1273 break;
1274
1275 case CM_DRP_EXCLUSIVE:
1276 lpValueName = L"Exclusive";
1277 break;
1278
1279 case CM_DRP_CHARACTERISTICS:
1280 lpValueName = L"DeviceCharacteristics";
1281 break;
1282
1283 default:
1284 return CR_INVALID_PROPERTY;
1285 }
1286
1287 lError = RegOpenKeyExW(hClassKey,
1288 pszClassGuid,
1289 0,
1290 KEY_WRITE,
1291 &hInstKey);
1292 if (lError != ERROR_SUCCESS)
1293 {
1294 ret = CR_NO_SUCH_REGISTRY_KEY;
1295 goto done;
1296 }
1297
1298 /* FIXME: Set security descriptor */
1299 lError = RegCreateKeyExW(hInstKey,
1300 L"Properties",
1301 0,
1302 NULL,
1303 REG_OPTION_NON_VOLATILE,
1304 KEY_ALL_ACCESS,
1305 NULL,
1306 &hPropKey,
1307 NULL);
1308 if (lError != ERROR_SUCCESS)
1309 {
1310 ret = CR_REGISTRY_ERROR;
1311 goto done;
1312 }
1313
1314 if (ulLength == 0)
1315 {
1316 if (RegDeleteValueW(hPropKey,
1317 lpValueName))
1318 ret = CR_REGISTRY_ERROR;
1319 }
1320 else
1321 {
1322 if (RegSetValueExW(hPropKey,
1323 lpValueName,
1324 0,
1325 ulDataType,
1326 Buffer,
1327 ulLength))
1328 ret = CR_REGISTRY_ERROR;
1329 }
1330
1331 done:;
1332 if (hPropKey != NULL)
1333 RegCloseKey(hPropKey);
1334
1335 if (hInstKey != NULL)
1336 RegCloseKey(hInstKey);
1337
1338 return ret;
1339 }
1340
1341
1342 static VOID
1343 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
1344 OUT LPWSTR pszEnumerator,
1345 OUT LPWSTR pszDevice,
1346 OUT LPWSTR pszInstance)
1347 {
1348 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
1349 LPWSTR lpEnumerator = NULL;
1350 LPWSTR lpDevice = NULL;
1351 LPWSTR lpInstance = NULL;
1352 LPWSTR ptr;
1353
1354 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
1355
1356 *pszEnumerator = 0;
1357 *pszDevice = 0;
1358 *pszInstance = 0;
1359
1360 lpEnumerator = szLocalDeviceInstanceID;
1361
1362 ptr = wcschr(lpEnumerator, L'\\');
1363 if (ptr != NULL)
1364 {
1365 *ptr = 0;
1366 lpDevice = ++ptr;
1367
1368 ptr = wcschr(lpDevice, L'\\');
1369 if (ptr != NULL)
1370 {
1371 *ptr = 0;
1372 lpInstance = ++ptr;
1373 }
1374 }
1375
1376 if (lpEnumerator != NULL)
1377 wcscpy(pszEnumerator, lpEnumerator);
1378
1379 if (lpDevice != NULL)
1380 wcscpy(pszDevice, lpDevice);
1381
1382 if (lpInstance != NULL)
1383 wcscpy(pszInstance, lpInstance);
1384 }
1385
1386
1387 static CONFIGRET
1388 CreateDeviceInstance(LPWSTR pszDeviceID)
1389 {
1390 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1391 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1392 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1393 HKEY hKeyEnumerator;
1394 HKEY hKeyDevice;
1395 HKEY hKeyInstance;
1396 HKEY hKeyControl;
1397 LONG lError;
1398
1399 /* Split the instance ID */
1400 SplitDeviceInstanceID(pszDeviceID,
1401 szEnumerator,
1402 szDevice,
1403 szInstance);
1404
1405 /* Open or create the enumerator key */
1406 lError = RegCreateKeyExW(hEnumKey,
1407 szEnumerator,
1408 0,
1409 NULL,
1410 REG_OPTION_NON_VOLATILE,
1411 KEY_ALL_ACCESS,
1412 NULL,
1413 &hKeyEnumerator,
1414 NULL);
1415 if (lError != ERROR_SUCCESS)
1416 {
1417 return CR_REGISTRY_ERROR;
1418 }
1419
1420 /* Open or create the device key */
1421 lError = RegCreateKeyExW(hKeyEnumerator,
1422 szDevice,
1423 0,
1424 NULL,
1425 REG_OPTION_NON_VOLATILE,
1426 KEY_ALL_ACCESS,
1427 NULL,
1428 &hKeyDevice,
1429 NULL);
1430
1431 /* Close the enumerator key */
1432 RegCloseKey(hKeyEnumerator);
1433
1434 if (lError != ERROR_SUCCESS)
1435 {
1436 return CR_REGISTRY_ERROR;
1437 }
1438
1439 /* Try to open the instance key and fail if it exists */
1440 lError = RegOpenKeyExW(hKeyDevice,
1441 szInstance,
1442 0,
1443 KEY_SET_VALUE,
1444 &hKeyInstance);
1445 if (lError == ERROR_SUCCESS)
1446 {
1447 DPRINT1("Instance %S already exists!\n", szInstance);
1448 RegCloseKey(hKeyInstance);
1449 RegCloseKey(hKeyDevice);
1450 return CR_ALREADY_SUCH_DEVINST;
1451 }
1452
1453 /* Create a new instance key */
1454 lError = RegCreateKeyExW(hKeyDevice,
1455 szInstance,
1456 0,
1457 NULL,
1458 REG_OPTION_NON_VOLATILE,
1459 KEY_ALL_ACCESS,
1460 NULL,
1461 &hKeyInstance,
1462 NULL);
1463
1464 /* Close the device key */
1465 RegCloseKey(hKeyDevice);
1466
1467 if (lError != ERROR_SUCCESS)
1468 {
1469 return CR_REGISTRY_ERROR;
1470 }
1471
1472 /* Create the 'Control' sub key */
1473 lError = RegCreateKeyExW(hKeyInstance,
1474 L"Control",
1475 0,
1476 NULL,
1477 REG_OPTION_NON_VOLATILE,
1478 KEY_ALL_ACCESS,
1479 NULL,
1480 &hKeyControl,
1481 NULL);
1482 if (lError == ERROR_SUCCESS)
1483 {
1484 RegCloseKey(hKeyControl);
1485 }
1486
1487 RegCloseKey(hKeyInstance);
1488
1489 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
1490 }
1491
1492
1493 /* Function 28 */
1494 DWORD PNP_CreateDevInst(
1495 handle_t hBinding,
1496 LPWSTR pszDeviceID,
1497 LPWSTR pszParentDeviceID,
1498 PNP_RPC_STRING_LEN ulLength,
1499 DWORD ulFlags)
1500 {
1501 CONFIGRET ret = CR_SUCCESS;
1502
1503 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
1504
1505 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
1506 {
1507 /* FIXME */
1508 DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret);
1509 ret = CR_CALL_NOT_IMPLEMENTED;
1510 goto done;
1511 }
1512
1513 /* Create the device instance */
1514 ret = CreateDeviceInstance(pszDeviceID);
1515
1516 done:;
1517 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
1518
1519 return ret;
1520 }
1521
1522
1523 static CONFIGRET
1524 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
1525 LPWSTR pszDeviceInstanceSource)
1526 {
1527 DPRINT("MoveDeviceInstance: not implemented\n");
1528 /* FIXME */
1529 return CR_CALL_NOT_IMPLEMENTED;
1530 }
1531
1532
1533 static CONFIGRET
1534 SetupDeviceInstance(LPWSTR pszDeviceInstance,
1535 DWORD ulFlags)
1536 {
1537 DPRINT("SetupDeviceInstance: not implemented\n");
1538 /* FIXME */
1539 return CR_CALL_NOT_IMPLEMENTED;
1540 }
1541
1542
1543 static CONFIGRET
1544 EnableDeviceInstance(LPWSTR pszDeviceInstance)
1545 {
1546 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1547 CONFIGRET ret = CR_SUCCESS;
1548 NTSTATUS Status;
1549
1550 DPRINT("Enable device instance\n");
1551
1552 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
1553 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1554 if (!NT_SUCCESS(Status))
1555 ret = NtStatusToCrError(Status);
1556
1557 return ret;
1558 }
1559
1560
1561 static CONFIGRET
1562 DisableDeviceInstance(LPWSTR pszDeviceInstance)
1563 {
1564 DPRINT("DisableDeviceInstance: not implemented\n");
1565 /* FIXME */
1566 return CR_CALL_NOT_IMPLEMENTED;
1567 }
1568
1569
1570 static CONFIGRET
1571 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
1572 {
1573 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1574 /* FIXME */
1575 return CR_CALL_NOT_IMPLEMENTED;
1576 }
1577
1578
1579 /* Function 29 */
1580 DWORD PNP_DeviceInstanceAction(
1581 handle_t hBinding,
1582 DWORD ulAction,
1583 DWORD ulFlags,
1584 LPWSTR pszDeviceInstance1,
1585 LPWSTR pszDeviceInstance2)
1586 {
1587 CONFIGRET ret = CR_SUCCESS;
1588
1589 UNREFERENCED_PARAMETER(hBinding);
1590
1591 DPRINT("PNP_DeviceInstanceAction() called\n");
1592
1593 switch (ulAction)
1594 {
1595 case PNP_DEVINST_MOVE:
1596 ret = MoveDeviceInstance(pszDeviceInstance1,
1597 pszDeviceInstance2);
1598 break;
1599
1600 case PNP_DEVINST_SETUP:
1601 ret = SetupDeviceInstance(pszDeviceInstance1,
1602 ulFlags);
1603 break;
1604
1605 case PNP_DEVINST_ENABLE:
1606 ret = EnableDeviceInstance(pszDeviceInstance1);
1607 break;
1608
1609 case PNP_DEVINST_DISABLE:
1610 ret = DisableDeviceInstance(pszDeviceInstance1);
1611 break;
1612
1613 case PNP_DEVINST_REENUMERATE:
1614 ret = ReenumerateDeviceInstance(pszDeviceInstance1);
1615 break;
1616
1617 default:
1618 DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
1619 ret = CR_CALL_NOT_IMPLEMENTED;
1620 }
1621
1622 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1623
1624 return ret;
1625 }
1626
1627
1628 /* Function 30 */
1629 DWORD PNP_GetDeviceStatus(
1630 handle_t hBinding,
1631 LPWSTR pDeviceID,
1632 DWORD *pulStatus,
1633 DWORD *pulProblem,
1634 DWORD ulFlags)
1635 {
1636 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1637 CONFIGRET ret = CR_SUCCESS;
1638 NTSTATUS Status;
1639
1640 UNREFERENCED_PARAMETER(hBinding);
1641 UNREFERENCED_PARAMETER(ulFlags);
1642
1643 DPRINT("PNP_GetDeviceStatus() called\n");
1644
1645 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1646 pDeviceID);
1647 PlugPlayData.Operation = 0; /* Get status */
1648
1649 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1650 (PVOID)&PlugPlayData,
1651 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1652 if (NT_SUCCESS(Status))
1653 {
1654 *pulStatus = PlugPlayData.DeviceStatus;
1655 *pulProblem = PlugPlayData.DeviceProblem;
1656 }
1657 else
1658 {
1659 ret = NtStatusToCrError(Status);
1660 }
1661
1662 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1663
1664 return ret;
1665 }
1666
1667
1668 /* Function 31 */
1669 DWORD PNP_SetDeviceProblem(
1670 handle_t hBinding,
1671 LPWSTR pDeviceID,
1672 DWORD ulProblem,
1673 DWORD ulFlags)
1674 {
1675 UNIMPLEMENTED;
1676 return CR_CALL_NOT_IMPLEMENTED;
1677 }
1678
1679
1680 /* Function 32 */
1681 DWORD PNP_DisableDevInst(
1682 handle_t hBinding,
1683 LPWSTR pDeviceID,
1684 PPNP_VETO_TYPE pVetoType,
1685 LPWSTR pszVetoName,
1686 DWORD ulNameLength,
1687 DWORD ulFlags)
1688 {
1689 UNIMPLEMENTED;
1690 return CR_CALL_NOT_IMPLEMENTED;
1691 }
1692
1693 /* Function 33 */
1694 DWORD PNP_UninstallDevInst(
1695 handle_t hBinding,
1696 LPWSTR pDeviceID,
1697 DWORD ulFlags)
1698 {
1699 UNIMPLEMENTED;
1700 return CR_CALL_NOT_IMPLEMENTED;
1701 }
1702
1703
1704 static BOOL
1705 CheckForDeviceId(LPWSTR lpDeviceIdList,
1706 LPWSTR lpDeviceId)
1707 {
1708 LPWSTR lpPtr;
1709 DWORD dwLength;
1710
1711 lpPtr = lpDeviceIdList;
1712 while (*lpPtr != 0)
1713 {
1714 dwLength = wcslen(lpPtr);
1715 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1716 return TRUE;
1717
1718 lpPtr += (dwLength + 1);
1719 }
1720
1721 return FALSE;
1722 }
1723
1724
1725 static VOID
1726 AppendDeviceId(LPWSTR lpDeviceIdList,
1727 LPDWORD lpDeviceIdListSize,
1728 LPWSTR lpDeviceId)
1729 {
1730 DWORD dwLen;
1731 DWORD dwPos;
1732
1733 dwLen = wcslen(lpDeviceId);
1734 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1735
1736 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1737
1738 dwPos += (dwLen + 1);
1739
1740 lpDeviceIdList[dwPos] = 0;
1741
1742 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1743 }
1744
1745
1746 /* Function 34 */
1747 DWORD PNP_AddID(
1748 handle_t hBinding,
1749 LPWSTR pszDeviceID,
1750 LPWSTR pszID,
1751 DWORD ulFlags)
1752 {
1753 CONFIGRET ret = CR_SUCCESS;
1754 HKEY hDeviceKey;
1755 LPWSTR pszSubKey;
1756 DWORD dwDeviceIdListSize;
1757 DWORD dwNewDeviceIdSize;
1758 WCHAR * pszDeviceIdList = NULL;
1759
1760 UNREFERENCED_PARAMETER(hBinding);
1761
1762 DPRINT("PNP_AddID() called\n");
1763 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1764 DPRINT(" DeviceId: %S\n", pszID);
1765 DPRINT(" Flags: %lx\n", ulFlags);
1766
1767 if (RegOpenKeyExW(hEnumKey,
1768 pszDeviceID,
1769 0,
1770 KEY_QUERY_VALUE | KEY_SET_VALUE,
1771 &hDeviceKey) != ERROR_SUCCESS)
1772 {
1773 DPRINT("Failed to open the device key!\n");
1774 return CR_INVALID_DEVNODE;
1775 }
1776
1777 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1778
1779 if (RegQueryValueExW(hDeviceKey,
1780 pszSubKey,
1781 NULL,
1782 NULL,
1783 NULL,
1784 &dwDeviceIdListSize) != ERROR_SUCCESS)
1785 {
1786 DPRINT("Failed to query the desired ID string!\n");
1787 ret = CR_REGISTRY_ERROR;
1788 goto Done;
1789 }
1790
1791 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1792 if (!dwNewDeviceIdSize)
1793 {
1794 ret = CR_INVALID_POINTER;
1795 goto Done;
1796 }
1797
1798 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1799
1800 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1801 if (!pszDeviceIdList)
1802 {
1803 DPRINT("Failed to allocate memory for the desired ID string!\n");
1804 ret = CR_OUT_OF_MEMORY;
1805 goto Done;
1806 }
1807
1808 if (RegQueryValueExW(hDeviceKey,
1809 pszSubKey,
1810 NULL,
1811 NULL,
1812 (LPBYTE)pszDeviceIdList,
1813 &dwDeviceIdListSize) != ERROR_SUCCESS)
1814 {
1815 DPRINT("Failed to query the desired ID string!\n");
1816 ret = CR_REGISTRY_ERROR;
1817 goto Done;
1818 }
1819
1820 /* Check whether the device ID is already in use */
1821 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1822 {
1823 DPRINT("Device ID was found in the ID string!\n");
1824 ret = CR_SUCCESS;
1825 goto Done;
1826 }
1827
1828 /* Append the Device ID */
1829 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1830
1831 if (RegSetValueExW(hDeviceKey,
1832 pszSubKey,
1833 0,
1834 REG_MULTI_SZ,
1835 (LPBYTE)pszDeviceIdList,
1836 dwDeviceIdListSize) != ERROR_SUCCESS)
1837 {
1838 DPRINT("Failed to set the desired ID string!\n");
1839 ret = CR_REGISTRY_ERROR;
1840 }
1841
1842 Done:
1843 RegCloseKey(hDeviceKey);
1844 if (pszDeviceIdList)
1845 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1846
1847 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1848
1849 return ret;
1850 }
1851
1852
1853 /* Function 35 */
1854 DWORD PNP_RegisterDriver(
1855 handle_t hBinding,
1856 LPWSTR pszDeviceID,
1857 DWORD ulFlags)
1858 {
1859 UNIMPLEMENTED;
1860 return CR_CALL_NOT_IMPLEMENTED;
1861 }
1862
1863
1864 /* Function 36 */
1865 DWORD PNP_QueryRemove(
1866 handle_t hBinding,
1867 LPWSTR pszDeviceID,
1868 PPNP_VETO_TYPE pVetoType,
1869 LPWSTR pszVetoName,
1870 DWORD ulNameLength,
1871 DWORD ulFlags)
1872 {
1873 UNIMPLEMENTED;
1874 return CR_CALL_NOT_IMPLEMENTED;
1875 }
1876
1877
1878 /* Function 37 */
1879 DWORD PNP_RequestDeviceEject(
1880 handle_t hBinding,
1881 LPWSTR pszDeviceID,
1882 PPNP_VETO_TYPE pVetoType,
1883 LPWSTR pszVetoName,
1884 DWORD ulNameLength,
1885 DWORD ulFlags)
1886 {
1887 UNIMPLEMENTED;
1888 return CR_CALL_NOT_IMPLEMENTED;
1889 }
1890
1891 /* Function 38 */
1892 CONFIGRET
1893 PNP_IsDockStationPresent(handle_t hBinding,
1894 BOOL *Present)
1895 {
1896 HKEY hKey;
1897 DWORD dwType;
1898 DWORD dwValue;
1899 DWORD dwSize;
1900 CONFIGRET ret = CR_SUCCESS;
1901
1902 UNREFERENCED_PARAMETER(hBinding);
1903
1904 DPRINT1("PNP_IsDockStationPresent() called\n");
1905
1906 *Present = FALSE;
1907
1908 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1909 L"CurrentDockInfo",
1910 0,
1911 KEY_READ,
1912 &hKey) != ERROR_SUCCESS)
1913 return CR_REGISTRY_ERROR;
1914
1915 dwSize = sizeof(DWORD);
1916 if (RegQueryValueExW(hKey,
1917 L"DockingState",
1918 NULL,
1919 &dwType,
1920 (LPBYTE)&dwValue,
1921 &dwSize) != ERROR_SUCCESS)
1922 ret = CR_REGISTRY_ERROR;
1923
1924 RegCloseKey(hKey);
1925
1926 if (ret == CR_SUCCESS)
1927 {
1928 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1929 {
1930 ret = CR_REGISTRY_ERROR;
1931 }
1932 else if (dwValue != 0)
1933 {
1934 *Present = TRUE;
1935 }
1936 }
1937
1938 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1939
1940 return ret;
1941 }
1942
1943
1944 /* Function 39 */
1945 DWORD PNP_RequestEjectPC(
1946 handle_t hBinding)
1947 {
1948 UNIMPLEMENTED;
1949 return CR_CALL_NOT_IMPLEMENTED;
1950 }
1951
1952
1953 /* Function 40 */
1954 DWORD PNP_HwProfFlags(
1955 handle_t hBinding,
1956 DWORD ulAction,
1957 LPWSTR pDeviceID,
1958 DWORD ulConfig,
1959 DWORD *pulValue,
1960 PPNP_VETO_TYPE pVetoType,
1961 LPWSTR pszVetoName,
1962 DWORD ulNameLength,
1963 DWORD ulFlags)
1964 {
1965 CONFIGRET ret = CR_SUCCESS;
1966 WCHAR szKeyName[MAX_PATH];
1967 HKEY hKey;
1968 HKEY hDeviceKey;
1969 DWORD dwSize;
1970
1971 UNREFERENCED_PARAMETER(hBinding);
1972
1973 DPRINT("PNP_HwProfFlags() called\n");
1974
1975 if (ulConfig == 0)
1976 {
1977 wcscpy(szKeyName,
1978 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1979 }
1980 else
1981 {
1982 swprintf(szKeyName,
1983 L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1984 ulConfig);
1985 }
1986
1987 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1988 szKeyName,
1989 0,
1990 KEY_QUERY_VALUE,
1991 &hKey) != ERROR_SUCCESS)
1992 return CR_REGISTRY_ERROR;
1993
1994 if (ulAction == PNP_GET_HWPROFFLAGS)
1995 {
1996 if (RegOpenKeyExW(hKey,
1997 pDeviceID,
1998 0,
1999 KEY_QUERY_VALUE,
2000 &hDeviceKey) != ERROR_SUCCESS)
2001 {
2002 *pulValue = 0;
2003 }
2004 else
2005 {
2006 dwSize = sizeof(DWORD);
2007 if (!RegQueryValueExW(hDeviceKey,
2008 L"CSConfigFlags",
2009 NULL,
2010 NULL,
2011 (LPBYTE)pulValue,
2012 &dwSize) != ERROR_SUCCESS)
2013 {
2014 *pulValue = 0;
2015 }
2016
2017 RegCloseKey(hDeviceKey);
2018 }
2019 }
2020 else if (ulAction == PNP_SET_HWPROFFLAGS)
2021 {
2022 /* FIXME: not implemented yet */
2023 ret = CR_CALL_NOT_IMPLEMENTED;
2024 }
2025
2026 RegCloseKey(hKey);
2027
2028 return ret;
2029 }
2030
2031
2032 /* Function 41 */
2033 DWORD PNP_GetHwProfInfo(
2034 handle_t hBinding,
2035 DWORD ulIndex,
2036 HWPROFILEINFO *pHWProfileInfo,
2037 DWORD ulProfileInfoSize,
2038 DWORD ulFlags)
2039 {
2040 UNIMPLEMENTED;
2041 return CR_CALL_NOT_IMPLEMENTED;
2042 }
2043
2044
2045 /* Function 42 */
2046 DWORD PNP_AddEmptyLogConf(
2047 handle_t hBinding,
2048 LPWSTR pDeviceID,
2049 DWORD ulPriority,
2050 DWORD *pulLogConfTag,
2051 DWORD ulFlags)
2052 {
2053 UNIMPLEMENTED;
2054 return CR_CALL_NOT_IMPLEMENTED;
2055 }
2056
2057
2058 /* Function 43 */
2059 DWORD PNP_FreeLogConf(
2060 handle_t hBinding,
2061 LPWSTR pDeviceID,
2062 DWORD ulLogConfType,
2063 DWORD ulLogConfTag,
2064 DWORD ulFlags)
2065 {
2066 UNIMPLEMENTED;
2067 return CR_CALL_NOT_IMPLEMENTED;
2068 }
2069
2070
2071 /* Function 44 */
2072 DWORD PNP_GetFirstLogConf(
2073 handle_t hBinding,
2074 LPWSTR pDeviceID,
2075 DWORD ulLogConfType,
2076 DWORD *pulLogConfTag,
2077 DWORD ulFlags)
2078 {
2079 UNIMPLEMENTED;
2080 return CR_CALL_NOT_IMPLEMENTED;
2081 }
2082
2083
2084 /* Function 45 */
2085 DWORD PNP_GetNextLogConf(
2086 handle_t hBinding,
2087 LPWSTR pDeviceID,
2088 DWORD ulLogConfType,
2089 DWORD ulCurrentTag,
2090 DWORD *pulNextTag,
2091 DWORD ulFlags)
2092 {
2093 UNIMPLEMENTED;
2094 return CR_CALL_NOT_IMPLEMENTED;
2095 }
2096
2097
2098 /* Function 46 */
2099 DWORD PNP_GetLogConfPriority(
2100 handle_t hBinding,
2101 LPWSTR pDeviceID,
2102 DWORD ulType,
2103 DWORD ulTag,
2104 DWORD *pPriority,
2105 DWORD ulFlags)
2106 {
2107 UNIMPLEMENTED;
2108 return CR_CALL_NOT_IMPLEMENTED;
2109 }
2110
2111
2112 /* Function 47 */
2113 DWORD PNP_AddResDes(
2114 handle_t hBinding,
2115 LPWSTR pDeviceID,
2116 DWORD ulLogConfTag,
2117 DWORD ulLogConfType,
2118 RESOURCEID ResourceID,
2119 DWORD *pulResourceTag,
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 48 */
2130 DWORD PNP_FreeResDes(
2131 handle_t hBinding,
2132 LPWSTR pDeviceID,
2133 DWORD ulLogConfTag,
2134 DWORD ulLogConfType,
2135 RESOURCEID ResourceID,
2136 DWORD ulResourceTag,
2137 DWORD *pulPreviousResType,
2138 DWORD *pulPreviousResTag,
2139 DWORD ulFlags)
2140 {
2141 UNIMPLEMENTED;
2142 return CR_CALL_NOT_IMPLEMENTED;
2143 }
2144
2145
2146 /* Function 49 */
2147 DWORD PNP_GetNextResDes(
2148 handle_t hBinding,
2149 LPWSTR pDeviceID,
2150 DWORD ulLogConfTag,
2151 DWORD ulLogConfType,
2152 RESOURCEID ResourceID,
2153 DWORD ulResourceTag,
2154 DWORD *pulNextResType,
2155 DWORD *pulNextResTag,
2156 DWORD ulFlags)
2157 {
2158 UNIMPLEMENTED;
2159 return CR_CALL_NOT_IMPLEMENTED;
2160 }
2161
2162
2163 /* Function 50 */
2164 DWORD PNP_GetResDesData(
2165 handle_t hBinding,
2166 LPWSTR pDeviceID,
2167 DWORD ulLogConfTag,
2168 DWORD ulLogConfType,
2169 RESOURCEID ResourceID,
2170 DWORD ulResourceTag,
2171 BYTE *Buffer,
2172 PNP_RPC_BUFFER_SIZE BufferLen,
2173 DWORD ulFlags)
2174 {
2175 UNIMPLEMENTED;
2176 return CR_CALL_NOT_IMPLEMENTED;
2177 }
2178
2179
2180 /* Function 51 */
2181 DWORD PNP_GetResDesDataSize(
2182 handle_t hBinding,
2183 LPWSTR pDeviceID,
2184 DWORD ulLogConfTag,
2185 DWORD ulLogConfType,
2186 RESOURCEID ResourceID,
2187 DWORD ulResourceTag,
2188 DWORD *pulSize,
2189 DWORD ulFlags)
2190 {
2191 UNIMPLEMENTED;
2192 return CR_CALL_NOT_IMPLEMENTED;
2193 }
2194
2195
2196 /* Function 52 */
2197 DWORD PNP_ModifyResDes(
2198 handle_t hBinding,
2199 LPWSTR pDeviceID,
2200 DWORD ulLogConfTag,
2201 DWORD ulLogConfType,
2202 RESOURCEID CurrentResourceID,
2203 RESOURCEID NewResourceID,
2204 DWORD ulResourceTag,
2205 BYTE *ResourceData,
2206 PNP_RPC_BUFFER_SIZE ResourceLen,
2207 DWORD ulFlags)
2208 {
2209 UNIMPLEMENTED;
2210 return CR_CALL_NOT_IMPLEMENTED;
2211 }
2212
2213
2214 /* Function 53 */
2215 DWORD PNP_DetectResourceConflict(
2216 handle_t hBinding,
2217 LPWSTR pDeviceID,
2218 RESOURCEID ResourceID,
2219 BYTE *ResourceData,
2220 PNP_RPC_BUFFER_SIZE ResourceLen,
2221 BOOL *pbConflictDetected,
2222 DWORD ulFlags)
2223 {
2224 UNIMPLEMENTED;
2225 return CR_CALL_NOT_IMPLEMENTED;
2226 }
2227
2228
2229 /* Function 54 */
2230 DWORD PNP_QueryResConfList(
2231 handle_t hBinding,
2232 LPWSTR pDeviceID,
2233 RESOURCEID ResourceID,
2234 BYTE *ResourceData,
2235 PNP_RPC_BUFFER_SIZE ResourceLen,
2236 BYTE *Buffer,
2237 PNP_RPC_BUFFER_SIZE BufferLen,
2238 DWORD ulFlags)
2239 {
2240 UNIMPLEMENTED;
2241 return CR_CALL_NOT_IMPLEMENTED;
2242 }
2243
2244
2245 /* Function 55 */
2246 DWORD PNP_SetHwProf(
2247 handle_t hBinding,
2248 DWORD ulHardwareProfile,
2249 DWORD ulFlags)
2250 {
2251 UNIMPLEMENTED;
2252 return CR_CALL_NOT_IMPLEMENTED;
2253 }
2254
2255
2256 /* Function 56 */
2257 DWORD PNP_QueryArbitratorFreeData(
2258 handle_t hBinding,
2259 BYTE *pData,
2260 DWORD DataLen,
2261 LPWSTR pDeviceID,
2262 RESOURCEID ResourceID,
2263 DWORD ulFlags)
2264 {
2265 UNIMPLEMENTED;
2266 return CR_CALL_NOT_IMPLEMENTED;
2267 }
2268
2269
2270 /* Function 57 */
2271 DWORD PNP_QueryArbitratorFreeSize(
2272 handle_t hBinding,
2273 DWORD *pulSize,
2274 LPWSTR pDeviceID,
2275 RESOURCEID ResourceID,
2276 DWORD ulFlags)
2277 {
2278 UNIMPLEMENTED;
2279 return CR_CALL_NOT_IMPLEMENTED;
2280 }
2281
2282
2283 /* Function 58 */
2284 CONFIGRET
2285 PNP_RunDetection(
2286 handle_t hBinding,
2287 DWORD ulFlags)
2288 {
2289 return CR_CALL_NOT_IMPLEMENTED;
2290 }
2291
2292
2293 /* Function 59 */
2294 DWORD PNP_RegisterNotification(
2295 handle_t hBinding)
2296 {
2297 UNIMPLEMENTED;
2298 return CR_CALL_NOT_IMPLEMENTED;
2299 }
2300
2301
2302 /* Function 60 */
2303 DWORD PNP_UnregisterNotification(
2304 handle_t hBinding)
2305 {
2306 UNIMPLEMENTED;
2307 return CR_CALL_NOT_IMPLEMENTED;
2308 }
2309
2310
2311 /* Function 61 */
2312 DWORD PNP_GetCustomDevProp(
2313 handle_t hBinding,
2314 LPWSTR pDeviceID,
2315 LPWSTR CustomPropName,
2316 DWORD *pulRegDataType,
2317 BYTE *Buffer,
2318 PNP_RPC_STRING_LEN *pulTransferLen,
2319 PNP_RPC_STRING_LEN *pulLength,
2320 DWORD ulFlags)
2321 {
2322 UNIMPLEMENTED;
2323 return CR_CALL_NOT_IMPLEMENTED;
2324 }
2325
2326
2327 /* Function 62 */
2328 DWORD PNP_GetVersionInternal(
2329 handle_t hBinding,
2330 WORD *pwVersion)
2331 {
2332 UNIMPLEMENTED;
2333 return CR_CALL_NOT_IMPLEMENTED;
2334 }
2335
2336
2337 /* Function 63 */
2338 DWORD PNP_GetBlockedDriverInfo(
2339 handle_t hBinding,
2340 BYTE *Buffer,
2341 PNP_RPC_BUFFER_SIZE *pulTransferLen,
2342 PNP_RPC_BUFFER_SIZE *pulLength,
2343 DWORD ulFlags)
2344 {
2345 UNIMPLEMENTED;
2346 return CR_CALL_NOT_IMPLEMENTED;
2347 }
2348
2349
2350 /* Function 64 */
2351 DWORD PNP_GetServerSideDeviceInstallFlags(
2352 handle_t hBinding,
2353 DWORD *pulSSDIFlags,
2354 DWORD ulFlags)
2355 {
2356 UNIMPLEMENTED;
2357 return CR_CALL_NOT_IMPLEMENTED;
2358 }
2359
2360
2361 /* Function 65 */
2362 DWORD PNP_GetObjectPropKeys(
2363 handle_t hBinding,
2364 LPWSTR ObjectName,
2365 DWORD ObjectType,
2366 LPWSTR PropertyCultureName,
2367 PNP_PROP_COUNT *PropertyCount,
2368 PNP_PROP_COUNT *TransferLen,
2369 DEVPROPKEY *PropertyKeys,
2370 DWORD Flags)
2371 {
2372 UNIMPLEMENTED;
2373 return CR_CALL_NOT_IMPLEMENTED;
2374 }
2375
2376
2377 /* Function 66 */
2378 DWORD PNP_GetObjectProp(
2379 handle_t hBinding,
2380 LPWSTR ObjectName,
2381 DWORD ObjectType,
2382 LPWSTR PropertyCultureName,
2383 const DEVPROPKEY *PropertyKey,
2384 DEVPROPTYPE *PropertyType,
2385 PNP_PROP_SIZE *PropertySize,
2386 PNP_PROP_SIZE *TransferLen,
2387 BYTE *PropertyBuffer,
2388 DWORD Flags)
2389 {
2390 UNIMPLEMENTED;
2391 return CR_CALL_NOT_IMPLEMENTED;
2392 }
2393
2394
2395 /* Function 67 */
2396 DWORD PNP_SetObjectProp(
2397 handle_t hBinding,
2398 LPWSTR ObjectName,
2399 DWORD ObjectType,
2400 LPWSTR PropertyCultureName,
2401 const DEVPROPKEY *PropertyKey,
2402 DEVPROPTYPE PropertyType,
2403 PNP_PROP_SIZE PropertySize,
2404 BYTE *PropertyBuffer,
2405 DWORD Flags)
2406 {
2407 UNIMPLEMENTED;
2408 return CR_CALL_NOT_IMPLEMENTED;
2409 }
2410
2411
2412 /* Function 68 */
2413 DWORD PNP_InstallDevInst(
2414 handle_t hBinding)
2415 {
2416 UNIMPLEMENTED;
2417 return CR_CALL_NOT_IMPLEMENTED;
2418 }
2419
2420
2421 /* Function 69 */
2422 DWORD PNP_ApplyPowerSettings(
2423 handle_t hBinding)
2424 {
2425 UNIMPLEMENTED;
2426 return CR_CALL_NOT_IMPLEMENTED;
2427 }
2428
2429
2430 /* Function 70 */
2431 DWORD PNP_DriverStoreAddDriverPackage(
2432 handle_t hBinding)
2433 {
2434 UNIMPLEMENTED;
2435 return CR_CALL_NOT_IMPLEMENTED;
2436 }
2437
2438
2439 /* Function 71 */
2440 DWORD PNP_DriverStoreDeleteDriverPackage(
2441 handle_t hBinding)
2442 {
2443 UNIMPLEMENTED;
2444 return CR_CALL_NOT_IMPLEMENTED;
2445 }
2446
2447
2448 /* Function 72 */
2449 DWORD PNP_RegisterServiceNotification(
2450 handle_t hBinding)
2451 {
2452 UNIMPLEMENTED;
2453 return CR_CALL_NOT_IMPLEMENTED;
2454 }
2455
2456
2457 /* Function 73 */
2458 DWORD PNP_SetActiveService(
2459 handle_t hBinding)
2460 {
2461 UNIMPLEMENTED;
2462 return CR_CALL_NOT_IMPLEMENTED;
2463 }
2464
2465
2466 /* Function 74 */
2467 DWORD PNP_DeleteServiceDevices(
2468 handle_t hBinding)
2469 {
2470 UNIMPLEMENTED;
2471 return CR_CALL_NOT_IMPLEMENTED;
2472 }
2473
2474
2475 static BOOL
2476 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
2477 {
2478 BOOL DeviceInstalled = FALSE;
2479 DWORD BytesWritten;
2480 DWORD Value;
2481 HANDLE hPipe = INVALID_HANDLE_VALUE;
2482 LPVOID Environment = NULL;
2483 PROCESS_INFORMATION ProcessInfo;
2484 STARTUPINFOW StartupInfo;
2485 UUID RandomUuid;
2486 HKEY DeviceKey;
2487
2488 /* The following lengths are constant (see below), they cannot overflow */
2489 WCHAR CommandLine[116];
2490 WCHAR InstallEventName[73];
2491 WCHAR PipeName[74];
2492 WCHAR UuidString[39];
2493
2494 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
2495
2496 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
2497
2498 if (RegOpenKeyExW(hEnumKey,
2499 DeviceInstance,
2500 0,
2501 KEY_QUERY_VALUE,
2502 &DeviceKey) == ERROR_SUCCESS)
2503 {
2504 if (RegQueryValueExW(DeviceKey,
2505 L"ClassGUID",
2506 NULL,
2507 NULL,
2508 NULL,
2509 NULL) == ERROR_SUCCESS)
2510 {
2511 DPRINT("No need to install: %S\n", DeviceInstance);
2512 RegCloseKey(DeviceKey);
2513 return TRUE;
2514 }
2515
2516 RegCloseKey(DeviceKey);
2517 }
2518
2519 DPRINT1("Installing: %S\n", DeviceInstance);
2520
2521 /* Create a random UUID for the named pipe */
2522 UuidCreate(&RandomUuid);
2523 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2524 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
2525 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
2526 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
2527 RandomUuid.Data4[6], RandomUuid.Data4[7]);
2528
2529 /* Create the named pipe */
2530 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2531 wcscat(PipeName, UuidString);
2532 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
2533
2534 if(hPipe == INVALID_HANDLE_VALUE)
2535 {
2536 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2537 goto cleanup;
2538 }
2539
2540 /* Launch rundll32 to call ClientSideInstallW */
2541 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
2542 wcscat(CommandLine, PipeName);
2543
2544 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
2545 StartupInfo.cb = sizeof(StartupInfo);
2546
2547 if(hUserToken)
2548 {
2549 /* newdev has to run under the environment of the current user */
2550 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
2551 {
2552 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2553 goto cleanup;
2554 }
2555
2556 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
2557 {
2558 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2559 goto cleanup;
2560 }
2561 }
2562 else
2563 {
2564 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2565
2566 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2567 (ShowWizard is only set to FALSE for these two modes) */
2568 ASSERT(!ShowWizard);
2569
2570 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2571 {
2572 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2573 goto cleanup;
2574 }
2575 }
2576
2577 /* Wait for the function to connect to our pipe */
2578 if(!ConnectNamedPipe(hPipe, NULL))
2579 {
2580 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2581 goto cleanup;
2582 }
2583
2584 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2585 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2586 wcscat(InstallEventName, UuidString);
2587
2588 Value = sizeof(InstallEventName);
2589 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2590 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2591
2592 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2593 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2594 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2595
2596 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2597 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2598 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2599
2600 /* Wait for newdev.dll to finish processing */
2601 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2602
2603 /* The following check for success is probably not compatible to Windows, but should do its job */
2604 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2605 {
2606 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2607 goto cleanup;
2608 }
2609
2610 DeviceInstalled = Value;
2611
2612 cleanup:
2613 if(hPipe != INVALID_HANDLE_VALUE)
2614 CloseHandle(hPipe);
2615
2616 if(Environment)
2617 DestroyEnvironmentBlock(Environment);
2618
2619 if(ProcessInfo.hProcess)
2620 CloseHandle(ProcessInfo.hProcess);
2621
2622 if(ProcessInfo.hThread)
2623 CloseHandle(ProcessInfo.hThread);
2624
2625 DPRINT1("Success? %d\n", DeviceInstalled);
2626
2627 return DeviceInstalled;
2628 }
2629
2630
2631 static LONG
2632 ReadRegSzKey(
2633 IN HKEY hKey,
2634 IN LPCWSTR pszKey,
2635 OUT LPWSTR* pValue)
2636 {
2637 LONG rc;
2638 DWORD dwType;
2639 DWORD cbData = 0;
2640 LPWSTR Value;
2641
2642 if (!pValue)
2643 return ERROR_INVALID_PARAMETER;
2644
2645 *pValue = NULL;
2646 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2647 if (rc != ERROR_SUCCESS)
2648 return rc;
2649 if (dwType != REG_SZ)
2650 return ERROR_FILE_NOT_FOUND;
2651 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2652 if (!Value)
2653 return ERROR_NOT_ENOUGH_MEMORY;
2654 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2655 if (rc != ERROR_SUCCESS)
2656 {
2657 HeapFree(GetProcessHeap(), 0, Value);
2658 return rc;
2659 }
2660 /* NULL-terminate the string */
2661 Value[cbData / sizeof(WCHAR)] = '\0';
2662
2663 *pValue = Value;
2664 return ERROR_SUCCESS;
2665 }
2666
2667
2668 static BOOL
2669 SetupIsActive(VOID)
2670 {
2671 HKEY hKey = NULL;
2672 DWORD regType, active, size;
2673 LONG rc;
2674 BOOL ret = FALSE;
2675
2676 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2677 if (rc != ERROR_SUCCESS)
2678 goto cleanup;
2679
2680 size = sizeof(DWORD);
2681 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2682 if (rc != ERROR_SUCCESS)
2683 goto cleanup;
2684 if (regType != REG_DWORD || size != sizeof(DWORD))
2685 goto cleanup;
2686
2687 ret = (active != 0);
2688
2689 cleanup:
2690 if (hKey != NULL)
2691 RegCloseKey(hKey);
2692
2693 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2694
2695 return ret;
2696 }
2697
2698
2699 static BOOL
2700 IsConsoleBoot(VOID)
2701 {
2702 HKEY ControlKey = NULL;
2703 LPWSTR SystemStartOptions = NULL;
2704 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2705 BOOL ConsoleBoot = FALSE;
2706 LONG rc;
2707
2708 rc = RegOpenKeyExW(
2709 HKEY_LOCAL_MACHINE,
2710 L"SYSTEM\\CurrentControlSet\\Control",
2711 0,
2712 KEY_QUERY_VALUE,
2713 &ControlKey);
2714
2715 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2716 if (rc != ERROR_SUCCESS)
2717 goto cleanup;
2718
2719 /* Check for CMDCONS in SystemStartOptions */
2720 CurrentOption = SystemStartOptions;
2721 while (CurrentOption)
2722 {
2723 NextOption = wcschr(CurrentOption, L' ');
2724 if (NextOption)
2725 *NextOption = L'\0';
2726 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2727 {
2728 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2729 ConsoleBoot = TRUE;
2730 goto cleanup;
2731 }
2732 CurrentOption = NextOption ? NextOption + 1 : NULL;
2733 }
2734
2735 cleanup:
2736 if (ControlKey != NULL)
2737 RegCloseKey(ControlKey);
2738 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2739 return ConsoleBoot;
2740 }
2741
2742
2743 /* Loop to install all queued devices installations */
2744 static DWORD WINAPI
2745 DeviceInstallThread(LPVOID lpParameter)
2746 {
2747 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2748 PSLIST_ENTRY ListEntry;
2749 #else
2750 PLIST_ENTRY ListEntry;
2751 #endif
2752 DeviceInstallParams* Params;
2753 BOOL showWizard;
2754
2755 UNREFERENCED_PARAMETER(lpParameter);
2756
2757 WaitForSingleObject(hInstallEvent, INFINITE);
2758
2759 showWizard = !SetupIsActive() && !IsConsoleBoot();
2760
2761 while (TRUE)
2762 {
2763 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2764 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2765 #else
2766 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2767 ListEntry = NULL;
2768 else
2769 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2770 #endif
2771 if (ListEntry == NULL)
2772 {
2773 SetEvent(hNoPendingInstalls);
2774 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2775 }
2776 else
2777 {
2778 ResetEvent(hNoPendingInstalls);
2779 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2780 InstallDevice(Params->DeviceIds, showWizard);
2781 }
2782 }
2783
2784 return 0;
2785 }
2786
2787
2788 static DWORD WINAPI
2789 PnpEventThread(LPVOID lpParameter)
2790 {
2791 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2792 ULONG PnpEventSize;
2793 NTSTATUS Status;
2794 RPC_STATUS RpcStatus;
2795
2796 UNREFERENCED_PARAMETER(lpParameter);
2797
2798 PnpEventSize = 0x1000;
2799 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2800 if (PnpEvent == NULL)
2801 return ERROR_OUTOFMEMORY;
2802
2803 for (;;)
2804 {
2805 DPRINT("Calling NtGetPlugPlayEvent()\n");
2806
2807 /* Wait for the next pnp event */
2808 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2809
2810 /* Resize the buffer for the PnP event if it's too small. */
2811 if (Status == STATUS_BUFFER_TOO_SMALL)
2812 {
2813 PnpEventSize += 0x400;
2814 HeapFree(GetProcessHeap(), 0, PnpEvent);
2815 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2816 if (PnpEvent == NULL)
2817 return ERROR_OUTOFMEMORY;
2818 continue;
2819 }
2820
2821 if (!NT_SUCCESS(Status))
2822 {
2823 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2824 break;
2825 }
2826
2827 /* Process the pnp event */
2828 DPRINT("Received PnP Event\n");
2829 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2830 {
2831 DeviceInstallParams* Params;
2832 DWORD len;
2833 DWORD DeviceIdLength;
2834
2835 DPRINT1("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
2836
2837 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2838 if (DeviceIdLength)
2839 {
2840 /* Queue device install (will be dequeued by DeviceInstallThread */
2841 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2842 Params = HeapAlloc(GetProcessHeap(), 0, len);
2843 if (Params)
2844 {
2845 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2846 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2847 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2848 #else
2849 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2850 #endif
2851 SetEvent(hDeviceInstallListNotEmpty);
2852 }
2853 }
2854 }
2855 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
2856 {
2857 DPRINT1("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
2858 /* FIXME: ? */
2859 }
2860 else
2861 {
2862 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2863 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2864 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2865 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2866 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2867 }
2868
2869 /* Dequeue the current pnp event and signal the next one */
2870 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
2871 }
2872
2873 HeapFree(GetProcessHeap(), 0, PnpEvent);
2874
2875 return ERROR_SUCCESS;
2876 }
2877
2878
2879 static VOID
2880 UpdateServiceStatus(DWORD dwState)
2881 {
2882 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2883 ServiceStatus.dwCurrentState = dwState;
2884 ServiceStatus.dwControlsAccepted = 0;
2885 ServiceStatus.dwWin32ExitCode = 0;
2886 ServiceStatus.dwServiceSpecificExitCode = 0;
2887 ServiceStatus.dwCheckPoint = 0;
2888
2889 if (dwState == SERVICE_START_PENDING ||
2890 dwState == SERVICE_STOP_PENDING ||
2891 dwState == SERVICE_PAUSE_PENDING ||
2892 dwState == SERVICE_CONTINUE_PENDING)
2893 ServiceStatus.dwWaitHint = 10000;
2894 else
2895 ServiceStatus.dwWaitHint = 0;
2896
2897 SetServiceStatus(ServiceStatusHandle,
2898 &ServiceStatus);
2899 }
2900
2901
2902 static DWORD WINAPI
2903 ServiceControlHandler(DWORD dwControl,
2904 DWORD dwEventType,
2905 LPVOID lpEventData,
2906 LPVOID lpContext)
2907 {
2908 DPRINT1("ServiceControlHandler() called\n");
2909
2910 switch (dwControl)
2911 {
2912 case SERVICE_CONTROL_STOP:
2913 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2914 UpdateServiceStatus(SERVICE_STOPPED);
2915 return ERROR_SUCCESS;
2916
2917 case SERVICE_CONTROL_PAUSE:
2918 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2919 UpdateServiceStatus(SERVICE_PAUSED);
2920 return ERROR_SUCCESS;
2921
2922 case SERVICE_CONTROL_CONTINUE:
2923 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2924 UpdateServiceStatus(SERVICE_RUNNING);
2925 return ERROR_SUCCESS;
2926
2927 case SERVICE_CONTROL_INTERROGATE:
2928 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2929 SetServiceStatus(ServiceStatusHandle,
2930 &ServiceStatus);
2931 return ERROR_SUCCESS;
2932
2933 case SERVICE_CONTROL_SHUTDOWN:
2934 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2935 UpdateServiceStatus(SERVICE_STOPPED);
2936 return ERROR_SUCCESS;
2937
2938 default :
2939 DPRINT1(" Control %lu received\n");
2940 return ERROR_CALL_NOT_IMPLEMENTED;
2941 }
2942 }
2943
2944
2945 static VOID CALLBACK
2946 ServiceMain(DWORD argc, LPTSTR *argv)
2947 {
2948 HANDLE hThread;
2949 DWORD dwThreadId;
2950
2951 UNREFERENCED_PARAMETER(argc);
2952 UNREFERENCED_PARAMETER(argv);
2953
2954 DPRINT("ServiceMain() called\n");
2955
2956 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
2957 ServiceControlHandler,
2958 NULL);
2959 if (!ServiceStatusHandle)
2960 {
2961 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2962 return;
2963 }
2964
2965 UpdateServiceStatus(SERVICE_START_PENDING);
2966
2967 hThread = CreateThread(NULL,
2968 0,
2969 PnpEventThread,
2970 NULL,
2971 0,
2972 &dwThreadId);
2973 if (hThread != NULL)
2974 CloseHandle(hThread);
2975
2976 hThread = CreateThread(NULL,
2977 0,
2978 RpcServerThread,
2979 NULL,
2980 0,
2981 &dwThreadId);
2982 if (hThread != NULL)
2983 CloseHandle(hThread);
2984
2985 hThread = CreateThread(NULL,
2986 0,
2987 DeviceInstallThread,
2988 NULL,
2989 0,
2990 &dwThreadId);
2991 if (hThread != NULL)
2992 CloseHandle(hThread);
2993
2994 UpdateServiceStatus(SERVICE_RUNNING);
2995
2996 DPRINT("ServiceMain() done\n");
2997 }
2998
2999
3000 int
3001 wmain(int argc, WCHAR *argv[])
3002 {
3003 BOOLEAN OldValue;
3004 DWORD dwError;
3005
3006 UNREFERENCED_PARAMETER(argc);
3007 UNREFERENCED_PARAMETER(argv);
3008
3009 DPRINT("Umpnpmgr: main() started\n");
3010
3011 /* We need this privilege for using CreateProcessAsUserW */
3012 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
3013
3014 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
3015 if (hInstallEvent == NULL)
3016 {
3017 dwError = GetLastError();
3018 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
3019 return dwError;
3020 }
3021
3022 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
3023 if (hDeviceInstallListNotEmpty == NULL)
3024 {
3025 dwError = GetLastError();
3026 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3027 return dwError;
3028 }
3029
3030 hNoPendingInstalls = CreateEventW(NULL,
3031 TRUE,
3032 FALSE,
3033 L"Global\\PnP_No_Pending_Install_Events");
3034 if (hNoPendingInstalls == NULL)
3035 {
3036 dwError = GetLastError();
3037 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3038 return dwError;
3039 }
3040
3041 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
3042 InitializeSListHead(&DeviceInstallListHead);
3043 #else
3044 InitializeListHead(&DeviceInstallListHead);
3045 #endif
3046
3047 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3048 L"System\\CurrentControlSet\\Enum",
3049 0,
3050 KEY_ALL_ACCESS,
3051 &hEnumKey);
3052 if (dwError != ERROR_SUCCESS)
3053 {
3054 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
3055 return dwError;
3056 }
3057
3058 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3059 L"System\\CurrentControlSet\\Control\\Class",
3060 0,
3061 KEY_ALL_ACCESS,
3062 &hClassKey);
3063 if (dwError != ERROR_SUCCESS)
3064 {
3065 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
3066 return dwError;
3067 }
3068
3069 StartServiceCtrlDispatcher(ServiceTable);
3070
3071 DPRINT("Umpnpmgr: main() done\n");
3072
3073 ExitThread(0);
3074
3075 return 0;
3076 }
3077
3078 /* EOF */