e1b0e1f276867eb27ca33b759c0979d92f0b732b
[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: base/services/umpnpmgr/umpnpmgr.c
23 * PURPOSE: User-mode Plug and Play manager
24 * PROGRAMMER: Eric Kohl (eric.kohl@reactos.org)
25 * Hervé Poussineau (hpoussin@reactos.org)
26 * Colin Finck (colin@reactos.org)
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #define WIN32_NO_STATUS
32 #define _INC_WINDOWS
33 #define COM_NO_WINDOWS_H
34 #include <stdarg.h>
35 #include <windef.h>
36 #include <winbase.h>
37 #include <winreg.h>
38 #include <winsvc.h>
39 #include <winuser.h>
40 #include <dbt.h>
41 #include <stdio.h>
42 #include <cmfuncs.h>
43 #include <rtlfuncs.h>
44 #include <setypes.h>
45 #include <umpnpmgr/sysguid.h>
46 #include <cfgmgr32.h>
47 #include <regstr.h>
48 #include <userenv.h>
49 #include <shlwapi.h>
50 #include <pnp_s.h>
51
52 #define NDEBUG
53 #include <debug.h>
54
55 /* GLOBALS ******************************************************************/
56
57 static WCHAR ServiceName[] = L"PlugPlay";
58
59 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
60 static SERVICE_STATUS ServiceStatus;
61
62 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
63
64 static HKEY hEnumKey = NULL;
65 static HKEY hClassKey = NULL;
66
67 static HANDLE hUserToken = NULL;
68 static HANDLE hInstallEvent = NULL;
69 static HANDLE hNoPendingInstalls = NULL;
70
71 static SLIST_HEADER DeviceInstallListHead;
72 static HANDLE hDeviceInstallListNotEmpty;
73
74 typedef struct
75 {
76 SLIST_ENTRY ListEntry;
77 WCHAR DeviceIds[1];
78 } DeviceInstallParams;
79
80 /* FUNCTIONS *****************************************************************/
81
82 static DWORD WINAPI
83 RpcServerThread(LPVOID lpParameter)
84 {
85 RPC_STATUS Status;
86 BOOLEAN RegisteredProtSeq = FALSE;
87
88 UNREFERENCED_PARAMETER(lpParameter);
89
90 DPRINT("RpcServerThread() called\n");
91
92 #if 0
93 /* 2k/XP/2k3-compatible protocol sequence/endpoint */
94 Status = RpcServerUseProtseqEpW(L"ncacn_np",
95 20,
96 L"\\pipe\\ntsvcs",
97 NULL); // Security descriptor
98 if (Status == RPC_S_OK)
99 RegisteredProtSeq = TRUE;
100 else
101 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
102 #endif
103
104 /* Vista/7-compatible protocol sequence/endpoint */
105 Status = RpcServerUseProtseqEpW(L"ncacn_np",
106 20,
107 L"\\pipe\\plugplay",
108 NULL); // Security descriptor
109 if (Status == RPC_S_OK)
110 RegisteredProtSeq = TRUE;
111 else
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
113
114 /* Make sure there's a usable endpoint */
115 if (RegisteredProtSeq == FALSE)
116 return 0;
117
118 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
119 NULL,
120 NULL);
121 if (Status != RPC_S_OK)
122 {
123 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
124 return 0;
125 }
126
127 Status = RpcServerListen(1,
128 20,
129 FALSE);
130 if (Status != RPC_S_OK)
131 {
132 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
133 return 0;
134 }
135
136 /* ROS HACK (this should never happen...) */
137 DPRINT1("*** Other devices won't be installed correctly. If something\n");
138 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
139
140 DPRINT("RpcServerThread() done\n");
141
142 return 0;
143 }
144
145
146 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
147 {
148 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
149 }
150
151
152 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
153 {
154 HeapFree(GetProcessHeap(), 0, ptr);
155 }
156
157
158 static CONFIGRET WINAPI
159 NtStatusToCrError(NTSTATUS Status)
160 {
161 switch (Status)
162 {
163 case STATUS_NOT_IMPLEMENTED:
164 return CR_CALL_NOT_IMPLEMENTED;
165
166 case STATUS_INVALID_PARAMETER:
167 return CR_INVALID_DATA;
168
169 case STATUS_NO_SUCH_DEVICE:
170 return CR_NO_SUCH_DEVINST;
171
172 case STATUS_ACCESS_DENIED:
173 return CR_ACCESS_DENIED;
174
175 case STATUS_BUFFER_TOO_SMALL:
176 return CR_BUFFER_SMALL;
177
178 case STATUS_OBJECT_NAME_NOT_FOUND:
179 return CR_NO_SUCH_VALUE;
180
181 default:
182 return CR_FAILURE;
183 }
184 }
185
186
187 /* Function 0 */
188 DWORD
189 WINAPI
190 PNP_Disconnect(
191 handle_t hBinding)
192 {
193 UNREFERENCED_PARAMETER(hBinding);
194 return CR_SUCCESS;
195 }
196
197
198 /* Function 1 */
199 DWORD
200 WINAPI
201 PNP_Connect(
202 handle_t hBinding)
203 {
204 UNREFERENCED_PARAMETER(hBinding);
205 return CR_SUCCESS;
206 }
207
208
209 /* Function 2 */
210 DWORD
211 WINAPI
212 PNP_GetVersion(
213 handle_t hBinding,
214 WORD *pVersion)
215 {
216 UNREFERENCED_PARAMETER(hBinding);
217
218 *pVersion = 0x0400;
219 return CR_SUCCESS;
220 }
221
222
223 /* Function 3 */
224 DWORD
225 WINAPI
226 PNP_GetGlobalState(
227 handle_t hBinding,
228 DWORD *pulState,
229 DWORD ulFlags)
230 {
231 UNREFERENCED_PARAMETER(hBinding);
232 UNREFERENCED_PARAMETER(ulFlags);
233
234 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
235 return CR_SUCCESS;
236 }
237
238
239 /* Function 4 */
240 DWORD
241 WINAPI
242 PNP_InitDetection(
243 handle_t hBinding)
244 {
245 UNREFERENCED_PARAMETER(hBinding);
246
247 DPRINT("PNP_InitDetection() called\n");
248 return CR_SUCCESS;
249 }
250
251
252 /* Function 5 */
253 DWORD
254 WINAPI
255 PNP_ReportLogOn(
256 handle_t hBinding,
257 BOOL Admin,
258 DWORD ProcessId)
259 {
260 DWORD ReturnValue = CR_FAILURE;
261 HANDLE hProcess;
262
263 UNREFERENCED_PARAMETER(hBinding);
264 UNREFERENCED_PARAMETER(Admin);
265
266 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
267
268 /* Get the users token */
269 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
270
271 if (!hProcess)
272 {
273 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
274 goto cleanup;
275 }
276
277 if (hUserToken)
278 {
279 CloseHandle(hUserToken);
280 hUserToken = NULL;
281 }
282
283 if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
284 {
285 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
286 goto cleanup;
287 }
288
289 /* Trigger the installer thread */
290 if (hInstallEvent)
291 SetEvent(hInstallEvent);
292
293 ReturnValue = CR_SUCCESS;
294
295 cleanup:
296 if (hProcess)
297 CloseHandle(hProcess);
298
299 return ReturnValue;
300 }
301
302
303 /* Function 6 */
304 DWORD
305 WINAPI
306 PNP_ValidateDeviceInstance(
307 handle_t hBinding,
308 LPWSTR pDeviceID,
309 DWORD ulFlags)
310 {
311 CONFIGRET ret = CR_SUCCESS;
312 HKEY hDeviceKey = NULL;
313
314 UNREFERENCED_PARAMETER(hBinding);
315 UNREFERENCED_PARAMETER(ulFlags);
316
317 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
318 pDeviceID, ulFlags);
319
320 if (RegOpenKeyExW(hEnumKey,
321 pDeviceID,
322 0,
323 KEY_READ,
324 &hDeviceKey))
325 {
326 DPRINT("Could not open the Device Key!\n");
327 ret = CR_NO_SUCH_DEVNODE;
328 goto Done;
329 }
330
331 /* FIXME: add more tests */
332
333 Done:
334 if (hDeviceKey != NULL)
335 RegCloseKey(hDeviceKey);
336
337 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
338
339 return ret;
340 }
341
342
343 /* Function 7 */
344 DWORD
345 WINAPI
346 PNP_GetRootDeviceInstance(
347 handle_t hBinding,
348 LPWSTR pDeviceID,
349 PNP_RPC_STRING_LEN ulLength)
350 {
351 CONFIGRET ret = CR_SUCCESS;
352
353 UNREFERENCED_PARAMETER(hBinding);
354
355 DPRINT("PNP_GetRootDeviceInstance() called\n");
356
357 if (!pDeviceID)
358 {
359 ret = CR_INVALID_POINTER;
360 goto Done;
361 }
362 if (ulLength < lstrlenW(szRootDeviceId) + 1)
363 {
364 ret = CR_BUFFER_SMALL;
365 goto Done;
366 }
367
368 lstrcpyW(pDeviceID,
369 szRootDeviceId);
370
371 Done:
372 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
373
374 return ret;
375 }
376
377
378 /* Function 8 */
379 DWORD
380 WINAPI
381 PNP_GetRelatedDeviceInstance(
382 handle_t hBinding,
383 DWORD ulRelationship,
384 LPWSTR pDeviceID,
385 LPWSTR pRelatedDeviceId,
386 PNP_RPC_STRING_LEN *pulLength,
387 DWORD ulFlags)
388 {
389 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
390 CONFIGRET ret = CR_SUCCESS;
391 NTSTATUS Status;
392
393 UNREFERENCED_PARAMETER(hBinding);
394 UNREFERENCED_PARAMETER(ulFlags);
395
396 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
397 DPRINT(" Relationship %ld\n", ulRelationship);
398 DPRINT(" DeviceId %S\n", pDeviceID);
399
400 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
401 pDeviceID);
402
403 PlugPlayData.Relation = ulRelationship;
404
405 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
406 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
407
408 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
409 (PVOID)&PlugPlayData,
410 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
411 if (!NT_SUCCESS(Status))
412 {
413 ret = NtStatusToCrError(Status);
414 }
415
416 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
417 if (ret == CR_SUCCESS)
418 {
419 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
420 }
421
422 return ret;
423 }
424
425
426 /* Function 9 */
427 DWORD
428 WINAPI
429 PNP_EnumerateSubKeys(
430 handle_t hBinding,
431 DWORD ulBranch,
432 DWORD ulIndex,
433 LPWSTR Buffer,
434 PNP_RPC_STRING_LEN ulLength,
435 PNP_RPC_STRING_LEN *pulRequiredLen,
436 DWORD ulFlags)
437 {
438 CONFIGRET ret = CR_SUCCESS;
439 HKEY hKey;
440 DWORD dwError;
441
442 UNREFERENCED_PARAMETER(hBinding);
443 UNREFERENCED_PARAMETER(ulFlags);
444
445 DPRINT("PNP_EnumerateSubKeys() called\n");
446
447 switch (ulBranch)
448 {
449 case PNP_ENUMERATOR_SUBKEYS:
450 hKey = hEnumKey;
451 break;
452
453 case PNP_CLASS_SUBKEYS:
454 hKey = hClassKey;
455 break;
456
457 default:
458 return CR_FAILURE;
459 }
460
461 *pulRequiredLen = ulLength;
462 dwError = RegEnumKeyExW(hKey,
463 ulIndex,
464 Buffer,
465 pulRequiredLen,
466 NULL,
467 NULL,
468 NULL,
469 NULL);
470 if (dwError != ERROR_SUCCESS)
471 {
472 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
473 }
474 else
475 {
476 (*pulRequiredLen)++;
477 }
478
479 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
480
481 return ret;
482 }
483
484
485 /* Function 10 */
486 DWORD
487 WINAPI
488 PNP_GetDeviceList(
489 handle_t hBinding,
490 LPWSTR pszFilter,
491 LPWSTR Buffer,
492 PNP_RPC_STRING_LEN *pulLength,
493 DWORD ulFlags)
494 {
495 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
496 CONFIGRET ret = CR_SUCCESS;
497 NTSTATUS Status;
498
499 DPRINT("PNP_GetDeviceList() called\n");
500
501 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
502 return CR_INVALID_FLAG;
503
504 if (pulLength == NULL || pszFilter == NULL)
505 return CR_INVALID_POINTER;
506
507 // if (Buffer == NULL)
508 // return CR_INVALID_POINTER;
509
510 if (ulFlags &
511 (CM_GETIDLIST_FILTER_BUSRELATIONS |
512 CM_GETIDLIST_FILTER_POWERRELATIONS |
513 CM_GETIDLIST_FILTER_REMOVALRELATIONS |
514 CM_GETIDLIST_FILTER_EJECTRELATIONS))
515 {
516 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
517 pszFilter);
518 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
519 {
520 PlugPlayData.Relations = 3;
521 }
522 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
523 {
524 PlugPlayData.Relations = 2;
525 }
526 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
527 {
528 PlugPlayData.Relations = 1;
529 }
530 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
531 {
532 PlugPlayData.Relations = 0;
533 }
534
535 PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR);
536 PlugPlayData.Buffer = Buffer;
537
538 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
539 (PVOID)&PlugPlayData,
540 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
541 if (NT_SUCCESS(Status))
542 {
543 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
544 }
545 else
546 {
547 ret = NtStatusToCrError(Status);
548 }
549 }
550 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
551 {
552 ret = CR_CALL_NOT_IMPLEMENTED;
553 }
554 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
555 {
556 ret = CR_CALL_NOT_IMPLEMENTED;
557 }
558 else /* CM_GETIDLIST_FILTER_NONE */
559 {
560 ret = CR_CALL_NOT_IMPLEMENTED;
561 }
562
563 return ret;
564 }
565
566
567 /* Function 11 */
568 DWORD
569 WINAPI
570 PNP_GetDeviceListSize(
571 handle_t hBinding,
572 LPWSTR pszFilter,
573 PNP_RPC_BUFFER_SIZE *pulLength,
574 DWORD ulFlags)
575 {
576 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
577 CONFIGRET ret = CR_SUCCESS;
578 NTSTATUS Status;
579
580 DPRINT("PNP_GetDeviceListSize() called\n");
581
582 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
583 return CR_INVALID_FLAG;
584
585 if (pulLength == NULL || pszFilter == NULL)
586 return CR_INVALID_POINTER;
587
588 *pulLength = 0;
589
590 if (ulFlags &
591 (CM_GETIDLIST_FILTER_BUSRELATIONS |
592 CM_GETIDLIST_FILTER_POWERRELATIONS |
593 CM_GETIDLIST_FILTER_REMOVALRELATIONS |
594 CM_GETIDLIST_FILTER_EJECTRELATIONS))
595 {
596 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
597 pszFilter);
598 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
599 {
600 PlugPlayData.Relations = 3;
601 }
602 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
603 {
604 PlugPlayData.Relations = 2;
605 }
606 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
607 {
608 PlugPlayData.Relations = 1;
609 }
610 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
611 {
612 PlugPlayData.Relations = 0;
613 }
614
615 PlugPlayData.BufferSize = 0;
616 PlugPlayData.Buffer = NULL;
617
618 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
619 (PVOID)&PlugPlayData,
620 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
621 if (NT_SUCCESS(Status))
622 {
623 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
624 }
625 else
626 {
627 ret = NtStatusToCrError(Status);
628 }
629 }
630 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
631 {
632 ret = CR_CALL_NOT_IMPLEMENTED;
633 }
634 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
635 {
636 ret = CR_CALL_NOT_IMPLEMENTED;
637 }
638 else /* CM_GETIDLIST_FILTER_NONE */
639 {
640 ret = CR_CALL_NOT_IMPLEMENTED;
641 }
642
643 return ret;
644 }
645
646
647 /* Function 12 */
648 DWORD
649 WINAPI
650 PNP_GetDepth(
651 handle_t hBinding,
652 LPWSTR pszDeviceID,
653 DWORD *pulDepth,
654 DWORD ulFlags)
655 {
656 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
657 CONFIGRET ret = CR_SUCCESS;
658 NTSTATUS Status;
659
660 UNREFERENCED_PARAMETER(hBinding);
661 UNREFERENCED_PARAMETER(ulFlags);
662
663 DPRINT("PNP_GetDepth() called\n");
664
665 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
666 pszDeviceID);
667
668 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
669 (PVOID)&PlugPlayData,
670 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
671 if (NT_SUCCESS(Status))
672 {
673 *pulDepth = PlugPlayData.Depth;
674 }
675 else
676 {
677 ret = NtStatusToCrError(Status);
678 }
679
680 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
681
682 return ret;
683 }
684
685
686 /* Function 13 */
687 DWORD
688 WINAPI
689 PNP_GetDeviceRegProp(
690 handle_t hBinding,
691 LPWSTR pDeviceID,
692 DWORD ulProperty,
693 DWORD *pulRegDataType,
694 BYTE *Buffer,
695 PNP_PROP_SIZE *pulTransferLen,
696 PNP_PROP_SIZE *pulLength,
697 DWORD ulFlags)
698 {
699 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
700 CONFIGRET ret = CR_SUCCESS;
701 LPWSTR lpValueName = NULL;
702 HKEY hKey = NULL;
703 LONG lError;
704 NTSTATUS Status;
705
706 UNREFERENCED_PARAMETER(hBinding);
707
708 DPRINT("PNP_GetDeviceRegProp() called\n");
709
710 if (pulTransferLen == NULL || pulLength == NULL)
711 {
712 ret = CR_INVALID_POINTER;
713 goto done;
714 }
715
716 if (ulFlags != 0)
717 {
718 ret = CR_INVALID_FLAG;
719 goto done;
720 }
721
722 /* FIXME: Check pDeviceID */
723
724 if (*pulLength < *pulTransferLen)
725 *pulLength = *pulTransferLen;
726
727 *pulTransferLen = 0;
728
729 switch (ulProperty)
730 {
731 case CM_DRP_DEVICEDESC:
732 lpValueName = L"DeviceDesc";
733 break;
734
735 case CM_DRP_HARDWAREID:
736 lpValueName = L"HardwareID";
737 break;
738
739 case CM_DRP_COMPATIBLEIDS:
740 lpValueName = L"CompatibleIDs";
741 break;
742
743 case CM_DRP_SERVICE:
744 lpValueName = L"Service";
745 break;
746
747 case CM_DRP_CLASS:
748 lpValueName = L"Class";
749 break;
750
751 case CM_DRP_CLASSGUID:
752 lpValueName = L"ClassGUID";
753 break;
754
755 case CM_DRP_DRIVER:
756 lpValueName = L"Driver";
757 break;
758
759 case CM_DRP_CONFIGFLAGS:
760 lpValueName = L"ConfigFlags";
761 break;
762
763 case CM_DRP_MFG:
764 lpValueName = L"Mfg";
765 break;
766
767 case CM_DRP_FRIENDLYNAME:
768 lpValueName = L"FriendlyName";
769 break;
770
771 case CM_DRP_LOCATION_INFORMATION:
772 lpValueName = L"LocationInformation";
773 break;
774
775 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
776 PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME;
777 break;
778
779 case CM_DRP_CAPABILITIES:
780 lpValueName = L"Capabilities";
781 break;
782
783 case CM_DRP_UI_NUMBER:
784 PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER;
785 break;
786
787 case CM_DRP_UPPERFILTERS:
788 lpValueName = L"UpperFilters";
789 break;
790
791 case CM_DRP_LOWERFILTERS:
792 lpValueName = L"LowerFilters";
793 break;
794
795 case CM_DRP_BUSTYPEGUID:
796 PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID;
797 break;
798
799 case CM_DRP_LEGACYBUSTYPE:
800 PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE;
801 break;
802
803 case CM_DRP_BUSNUMBER:
804 PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER;
805 break;
806
807 case CM_DRP_ENUMERATOR_NAME:
808 PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME;
809 break;
810
811 case CM_DRP_SECURITY:
812 lpValueName = L"Security";
813 break;
814
815 case CM_DRP_DEVTYPE:
816 lpValueName = L"DeviceType";
817 break;
818
819 case CM_DRP_EXCLUSIVE:
820 lpValueName = L"Exclusive";
821 break;
822
823 case CM_DRP_CHARACTERISTICS:
824 lpValueName = L"DeviceCharacteristics";
825 break;
826
827 case CM_DRP_ADDRESS:
828 PlugPlayData.Property = PNP_PROPERTY_ADDRESS;
829 break;
830
831 case CM_DRP_UI_NUMBER_DESC_FORMAT:
832 lpValueName = L"UINumberDescFormat";
833 break;
834
835 case CM_DRP_DEVICE_POWER_DATA:
836 PlugPlayData.Property = PNP_PROPERTY_POWER_DATA;
837 break;
838
839 case CM_DRP_REMOVAL_POLICY:
840 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY;
841 break;
842
843 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
844 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT;
845 break;
846
847 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
848 lpValueName = L"RemovalPolicy";
849 break;
850
851 case CM_DRP_INSTALL_STATE:
852 PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE;
853 break;
854
855 #if (WINVER >= _WIN32_WINNT_WS03)
856 case CM_DRP_LOCATION_PATHS:
857 PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS;
858 break;
859 #endif
860
861 #if (WINVER >= _WIN32_WINNT_WIN7)
862 case CM_DRP_BASE_CONTAINERID:
863 PlugPlayData.Property = PNP_PROPERTY_CONTAINERID;
864 break;
865 #endif
866
867 default:
868 ret = CR_INVALID_PROPERTY;
869 goto done;
870 }
871
872 DPRINT("Value name: %S\n", lpValueName);
873
874 if (lpValueName)
875 {
876 /* Retrieve information from the Registry */
877 lError = RegOpenKeyExW(hEnumKey,
878 pDeviceID,
879 0,
880 KEY_QUERY_VALUE,
881 &hKey);
882 if (lError != ERROR_SUCCESS)
883 {
884 hKey = NULL;
885 *pulLength = 0;
886 ret = CR_INVALID_DEVNODE;
887 goto done;
888 }
889
890 lError = RegQueryValueExW(hKey,
891 lpValueName,
892 NULL,
893 pulRegDataType,
894 Buffer,
895 pulLength);
896 if (lError != ERROR_SUCCESS)
897 {
898 if (lError == ERROR_MORE_DATA)
899 {
900 ret = CR_BUFFER_SMALL;
901 }
902 else
903 {
904 *pulLength = 0;
905 ret = CR_NO_SUCH_VALUE;
906 }
907 }
908 }
909 else
910 {
911 /* Retrieve information from the Device Node */
912 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
913 pDeviceID);
914 PlugPlayData.Buffer = Buffer;
915 PlugPlayData.BufferSize = *pulLength;
916
917 Status = NtPlugPlayControl(PlugPlayControlProperty,
918 (PVOID)&PlugPlayData,
919 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
920 if (NT_SUCCESS(Status))
921 {
922 *pulLength = PlugPlayData.BufferSize;
923 }
924 else
925 {
926 ret = NtStatusToCrError(Status);
927 }
928 }
929
930 done:
931 if (pulTransferLen)
932 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
933
934 if (hKey != NULL)
935 RegCloseKey(hKey);
936
937 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
938
939 return ret;
940 }
941
942
943 /* Function 14 */
944 DWORD
945 WINAPI
946 PNP_SetDeviceRegProp(
947 handle_t hBinding,
948 LPWSTR pDeviceId,
949 DWORD ulProperty,
950 DWORD ulDataType,
951 BYTE *Buffer,
952 PNP_PROP_SIZE ulLength,
953 DWORD ulFlags)
954 {
955 CONFIGRET ret = CR_SUCCESS;
956 LPWSTR lpValueName = NULL;
957 HKEY hKey = 0;
958
959 UNREFERENCED_PARAMETER(hBinding);
960 UNREFERENCED_PARAMETER(ulFlags);
961
962 DPRINT("PNP_SetDeviceRegProp() called\n");
963
964 DPRINT("DeviceId: %S\n", pDeviceId);
965 DPRINT("Property: %lu\n", ulProperty);
966 DPRINT("DataType: %lu\n", ulDataType);
967 DPRINT("Length: %lu\n", ulLength);
968
969 switch (ulProperty)
970 {
971 case CM_DRP_DEVICEDESC:
972 lpValueName = L"DeviceDesc";
973 break;
974
975 case CM_DRP_HARDWAREID:
976 lpValueName = L"HardwareID";
977 break;
978
979 case CM_DRP_COMPATIBLEIDS:
980 lpValueName = L"CompatibleIDs";
981 break;
982
983 case CM_DRP_SERVICE:
984 lpValueName = L"Service";
985 break;
986
987 case CM_DRP_CLASS:
988 lpValueName = L"Class";
989 break;
990
991 case CM_DRP_CLASSGUID:
992 lpValueName = L"ClassGUID";
993 break;
994
995 case CM_DRP_DRIVER:
996 lpValueName = L"Driver";
997 break;
998
999 case CM_DRP_CONFIGFLAGS:
1000 lpValueName = L"ConfigFlags";
1001 break;
1002
1003 case CM_DRP_MFG:
1004 lpValueName = L"Mfg";
1005 break;
1006
1007 case CM_DRP_FRIENDLYNAME:
1008 lpValueName = L"FriendlyName";
1009 break;
1010
1011 case CM_DRP_LOCATION_INFORMATION:
1012 lpValueName = L"LocationInformation";
1013 break;
1014
1015 case CM_DRP_UPPERFILTERS:
1016 lpValueName = L"UpperFilters";
1017 break;
1018
1019 case CM_DRP_LOWERFILTERS:
1020 lpValueName = L"LowerFilters";
1021 break;
1022
1023 case CM_DRP_SECURITY:
1024 lpValueName = L"Security";
1025 break;
1026
1027 case CM_DRP_DEVTYPE:
1028 lpValueName = L"DeviceType";
1029 break;
1030
1031 case CM_DRP_EXCLUSIVE:
1032 lpValueName = L"Exclusive";
1033 break;
1034
1035 case CM_DRP_CHARACTERISTICS:
1036 lpValueName = L"DeviceCharacteristics";
1037 break;
1038
1039 case CM_DRP_UI_NUMBER_DESC_FORMAT:
1040 lpValueName = L"UINumberDescFormat";
1041 break;
1042
1043 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
1044 lpValueName = L"RemovalPolicy";
1045 break;
1046
1047 default:
1048 return CR_INVALID_PROPERTY;
1049 }
1050
1051 DPRINT("Value name: %S\n", lpValueName);
1052
1053 if (RegOpenKeyExW(hEnumKey,
1054 pDeviceId,
1055 0,
1056 KEY_SET_VALUE,
1057 &hKey))
1058 return CR_INVALID_DEVNODE;
1059
1060 if (ulLength == 0)
1061 {
1062 if (RegDeleteValueW(hKey,
1063 lpValueName))
1064 ret = CR_REGISTRY_ERROR;
1065 }
1066 else
1067 {
1068 if (RegSetValueExW(hKey,
1069 lpValueName,
1070 0,
1071 ulDataType,
1072 Buffer,
1073 ulLength))
1074 ret = CR_REGISTRY_ERROR;
1075 }
1076
1077 RegCloseKey(hKey);
1078
1079 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
1080
1081 return ret;
1082 }
1083
1084
1085 /* Function 15 */
1086 DWORD
1087 WINAPI
1088 PNP_GetClassInstance(
1089 handle_t hBinding,
1090 LPWSTR pDeviceId,
1091 LPWSTR pszClassInstance,
1092 PNP_RPC_STRING_LEN ulLength)
1093 {
1094 UNIMPLEMENTED;
1095 return CR_CALL_NOT_IMPLEMENTED;
1096 }
1097
1098
1099 /* Function 16 */
1100 DWORD
1101 WINAPI
1102 PNP_CreateKey(
1103 handle_t hBinding,
1104 LPWSTR pszSubKey,
1105 DWORD samDesired,
1106 DWORD ulFlags)
1107 {
1108 HKEY hKey = 0;
1109
1110 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1111 pszSubKey,
1112 0,
1113 NULL,
1114 0,
1115 KEY_ALL_ACCESS,
1116 NULL,
1117 &hKey,
1118 NULL))
1119 return CR_REGISTRY_ERROR;
1120
1121 /* FIXME: Set security key */
1122
1123 RegCloseKey(hKey);
1124
1125 return CR_SUCCESS;
1126 }
1127
1128
1129 /* Function 17 */
1130 DWORD
1131 WINAPI
1132 PNP_DeleteRegistryKey(
1133 handle_t hBinding,
1134 LPWSTR pszDeviceID,
1135 LPWSTR pszParentKey,
1136 LPWSTR pszChildKey,
1137 DWORD ulFlags)
1138 {
1139 UNIMPLEMENTED;
1140 return CR_CALL_NOT_IMPLEMENTED;
1141 }
1142
1143
1144 /* Function 18 */
1145 DWORD
1146 WINAPI
1147 PNP_GetClassCount(
1148 handle_t hBinding,
1149 DWORD *pulClassCount,
1150 DWORD ulFlags)
1151 {
1152 HKEY hKey;
1153 DWORD dwError;
1154
1155 UNREFERENCED_PARAMETER(hBinding);
1156 UNREFERENCED_PARAMETER(ulFlags);
1157
1158 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1159 REGSTR_PATH_CLASS,
1160 0,
1161 KEY_QUERY_VALUE,
1162 &hKey);
1163 if (dwError != ERROR_SUCCESS)
1164 return CR_INVALID_DATA;
1165
1166 dwError = RegQueryInfoKeyW(hKey,
1167 NULL,
1168 NULL,
1169 NULL,
1170 pulClassCount,
1171 NULL,
1172 NULL,
1173 NULL,
1174 NULL,
1175 NULL,
1176 NULL,
1177 NULL);
1178 RegCloseKey(hKey);
1179 if (dwError != ERROR_SUCCESS)
1180 return CR_INVALID_DATA;
1181
1182 return CR_SUCCESS;
1183 }
1184
1185
1186 /* Function 19 */
1187 DWORD
1188 WINAPI
1189 PNP_GetClassName(
1190 handle_t hBinding,
1191 LPWSTR pszClassGuid,
1192 LPWSTR Buffer,
1193 PNP_RPC_STRING_LEN *pulLength,
1194 DWORD ulFlags)
1195 {
1196 WCHAR szKeyName[MAX_PATH];
1197 CONFIGRET ret = CR_SUCCESS;
1198 HKEY hKey;
1199 DWORD dwSize;
1200
1201 UNREFERENCED_PARAMETER(hBinding);
1202 UNREFERENCED_PARAMETER(ulFlags);
1203
1204 DPRINT("PNP_GetClassName() called\n");
1205
1206 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
1207 if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
1208 lstrcatW(szKeyName, pszClassGuid);
1209 else
1210 return CR_INVALID_DATA;
1211
1212 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1213 szKeyName,
1214 0,
1215 KEY_QUERY_VALUE,
1216 &hKey))
1217 return CR_REGISTRY_ERROR;
1218
1219 dwSize = *pulLength * sizeof(WCHAR);
1220 if (RegQueryValueExW(hKey,
1221 L"Class",
1222 NULL,
1223 NULL,
1224 (LPBYTE)Buffer,
1225 &dwSize))
1226 {
1227 *pulLength = 0;
1228 ret = CR_REGISTRY_ERROR;
1229 }
1230 else
1231 {
1232 *pulLength = dwSize / sizeof(WCHAR);
1233 }
1234
1235 RegCloseKey(hKey);
1236
1237 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
1238
1239 return ret;
1240 }
1241
1242
1243 /* Function 20 */
1244 DWORD
1245 WINAPI
1246 PNP_DeleteClassKey(
1247 handle_t hBinding,
1248 LPWSTR pszClassGuid,
1249 DWORD ulFlags)
1250 {
1251 CONFIGRET ret = CR_SUCCESS;
1252
1253 UNREFERENCED_PARAMETER(hBinding);
1254
1255 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
1256
1257 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
1258 {
1259 if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
1260 ret = CR_REGISTRY_ERROR;
1261 }
1262 else
1263 {
1264 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
1265 ret = CR_REGISTRY_ERROR;
1266 }
1267
1268 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
1269
1270 return ret;
1271 }
1272
1273
1274 /* Function 21 */
1275 DWORD
1276 WINAPI
1277 PNP_GetInterfaceDeviceAlias(
1278 handle_t hBinding,
1279 LPWSTR pszInterfaceDevice,
1280 GUID *AliasInterfaceGuid,
1281 LPWSTR pszAliasInterfaceDevice,
1282 PNP_RPC_STRING_LEN *pulLength,
1283 PNP_RPC_STRING_LEN *pulTransferLen,
1284 DWORD ulFlags)
1285 {
1286 UNIMPLEMENTED;
1287 return CR_CALL_NOT_IMPLEMENTED;
1288 }
1289
1290
1291 /* Function 22 */
1292 DWORD
1293 WINAPI
1294 PNP_GetInterfaceDeviceList(
1295 handle_t hBinding,
1296 GUID *InterfaceGuid,
1297 LPWSTR pszDeviceID,
1298 BYTE *Buffer,
1299 PNP_RPC_BUFFER_SIZE *pulLength,
1300 DWORD ulFlags)
1301 {
1302 NTSTATUS Status;
1303 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
1304 DWORD ret = CR_SUCCESS;
1305
1306 UNREFERENCED_PARAMETER(hBinding);
1307
1308 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1309 pszDeviceID);
1310
1311 PlugPlayData.Flags = ulFlags;
1312 PlugPlayData.FilterGuid = InterfaceGuid;
1313 PlugPlayData.Buffer = Buffer;
1314 PlugPlayData.BufferSize = *pulLength;
1315
1316 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
1317 (PVOID)&PlugPlayData,
1318 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
1319 if (NT_SUCCESS(Status))
1320 {
1321 *pulLength = PlugPlayData.BufferSize;
1322 }
1323 else
1324 {
1325 ret = NtStatusToCrError(Status);
1326 }
1327
1328 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
1329 return ret;
1330 }
1331
1332
1333 /* Function 23 */
1334 DWORD
1335 WINAPI
1336 PNP_GetInterfaceDeviceListSize(
1337 handle_t hBinding,
1338 PNP_RPC_BUFFER_SIZE *pulLen,
1339 GUID *InterfaceGuid,
1340 LPWSTR pszDeviceID,
1341 DWORD ulFlags)
1342 {
1343 NTSTATUS Status;
1344 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
1345 DWORD ret = CR_SUCCESS;
1346
1347 UNREFERENCED_PARAMETER(hBinding);
1348
1349 DPRINT("PNP_GetInterfaceDeviceListSize() called\n");
1350
1351 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1352 pszDeviceID);
1353
1354 PlugPlayData.FilterGuid = InterfaceGuid;
1355 PlugPlayData.Buffer = NULL;
1356 PlugPlayData.BufferSize = 0;
1357 PlugPlayData.Flags = ulFlags;
1358
1359 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
1360 (PVOID)&PlugPlayData,
1361 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
1362 if (NT_SUCCESS(Status))
1363 {
1364 *pulLen = PlugPlayData.BufferSize;
1365 }
1366 else
1367 {
1368 ret = NtStatusToCrError(Status);
1369 }
1370
1371 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
1372 return ret;
1373 }
1374
1375
1376 /* Function 24 */
1377 DWORD
1378 WINAPI
1379 PNP_RegisterDeviceClassAssociation(
1380 handle_t hBinding,
1381 LPWSTR pszDeviceID,
1382 GUID *InterfaceGuid,
1383 LPWSTR pszReference,
1384 LPWSTR pszSymLink,
1385 PNP_RPC_STRING_LEN *pulLength,
1386 PNP_RPC_STRING_LEN *pulTransferLen,
1387 DWORD ulFlags)
1388 {
1389 UNIMPLEMENTED;
1390 return CR_CALL_NOT_IMPLEMENTED;
1391 }
1392
1393
1394 /* Function 25 */
1395 DWORD
1396 WINAPI
1397 PNP_UnregisterDeviceClassAssociation(
1398 handle_t hBinding,
1399 LPWSTR pszInterfaceDevice,
1400 DWORD ulFlags)
1401 {
1402 UNIMPLEMENTED;
1403 return CR_CALL_NOT_IMPLEMENTED;
1404 }
1405
1406
1407 /* Function 26 */
1408 DWORD
1409 WINAPI
1410 PNP_GetClassRegProp(
1411 handle_t hBinding,
1412 LPWSTR pszClassGuid,
1413 DWORD ulProperty,
1414 DWORD *pulRegDataType,
1415 BYTE *Buffer,
1416 PNP_RPC_STRING_LEN *pulTransferLen,
1417 PNP_RPC_STRING_LEN *pulLength,
1418 DWORD ulFlags)
1419 {
1420 CONFIGRET ret = CR_SUCCESS;
1421 LPWSTR lpValueName = NULL;
1422 HKEY hInstKey = NULL;
1423 HKEY hPropKey = NULL;
1424 LONG lError;
1425
1426 UNREFERENCED_PARAMETER(hBinding);
1427
1428 DPRINT("PNP_GetClassRegProp() called\n");
1429
1430 if (pulTransferLen == NULL || pulLength == NULL)
1431 {
1432 ret = CR_INVALID_POINTER;
1433 goto done;
1434 }
1435
1436 if (ulFlags != 0)
1437 {
1438 ret = CR_INVALID_FLAG;
1439 goto done;
1440 }
1441
1442 if (*pulLength < *pulTransferLen)
1443 *pulLength = *pulTransferLen;
1444
1445 *pulTransferLen = 0;
1446
1447 switch (ulProperty)
1448 {
1449 case CM_CRP_SECURITY:
1450 lpValueName = L"Security";
1451 break;
1452
1453 case CM_CRP_DEVTYPE:
1454 lpValueName = L"DeviceType";
1455 break;
1456
1457 case CM_CRP_EXCLUSIVE:
1458 lpValueName = L"Exclusive";
1459 break;
1460
1461 case CM_CRP_CHARACTERISTICS:
1462 lpValueName = L"DeviceCharacteristics";
1463 break;
1464
1465 default:
1466 ret = CR_INVALID_PROPERTY;
1467 goto done;
1468 }
1469
1470 DPRINT("Value name: %S\n", lpValueName);
1471
1472 lError = RegOpenKeyExW(hClassKey,
1473 pszClassGuid,
1474 0,
1475 KEY_READ,
1476 &hInstKey);
1477 if (lError != ERROR_SUCCESS)
1478 {
1479 *pulLength = 0;
1480 ret = CR_NO_SUCH_REGISTRY_KEY;
1481 goto done;
1482 }
1483
1484 lError = RegOpenKeyExW(hInstKey,
1485 L"Properties",
1486 0,
1487 KEY_READ,
1488 &hPropKey);
1489 if (lError != ERROR_SUCCESS)
1490 {
1491 *pulLength = 0;
1492 ret = CR_NO_SUCH_REGISTRY_KEY;
1493 goto done;
1494 }
1495
1496 lError = RegQueryValueExW(hPropKey,
1497 lpValueName,
1498 NULL,
1499 pulRegDataType,
1500 Buffer,
1501 pulLength);
1502 if (lError != ERROR_SUCCESS)
1503 {
1504 if (lError == ERROR_MORE_DATA)
1505 {
1506 ret = CR_BUFFER_SMALL;
1507 }
1508 else
1509 {
1510 *pulLength = 0;
1511 ret = CR_NO_SUCH_VALUE;
1512 }
1513 }
1514
1515 done:
1516 if (ret == CR_SUCCESS)
1517 *pulTransferLen = *pulLength;
1518
1519 if (hPropKey != NULL)
1520 RegCloseKey(hPropKey);
1521
1522 if (hInstKey != NULL)
1523 RegCloseKey(hInstKey);
1524
1525 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
1526
1527 return ret;
1528 }
1529
1530
1531 /* Function 27 */
1532 DWORD
1533 WINAPI
1534 PNP_SetClassRegProp(
1535 handle_t hBinding,
1536 LPWSTR pszClassGuid,
1537 DWORD ulProperty,
1538 DWORD ulDataType,
1539 BYTE *Buffer,
1540 PNP_PROP_SIZE ulLength,
1541 DWORD ulFlags)
1542 {
1543 CONFIGRET ret = CR_SUCCESS;
1544 LPWSTR lpValueName = NULL;
1545 HKEY hInstKey = 0;
1546 HKEY hPropKey = 0;
1547 LONG lError;
1548
1549 UNREFERENCED_PARAMETER(hBinding);
1550
1551 DPRINT("PNP_SetClassRegProp() called\n");
1552
1553 if (ulFlags != 0)
1554 return CR_INVALID_FLAG;
1555
1556 switch (ulProperty)
1557 {
1558 case CM_CRP_SECURITY:
1559 lpValueName = L"Security";
1560 break;
1561
1562 case CM_CRP_DEVTYPE:
1563 lpValueName = L"DeviceType";
1564 break;
1565
1566 case CM_CRP_EXCLUSIVE:
1567 lpValueName = L"Exclusive";
1568 break;
1569
1570 case CM_CRP_CHARACTERISTICS:
1571 lpValueName = L"DeviceCharacteristics";
1572 break;
1573
1574 default:
1575 return CR_INVALID_PROPERTY;
1576 }
1577
1578 lError = RegOpenKeyExW(hClassKey,
1579 pszClassGuid,
1580 0,
1581 KEY_WRITE,
1582 &hInstKey);
1583 if (lError != ERROR_SUCCESS)
1584 {
1585 ret = CR_NO_SUCH_REGISTRY_KEY;
1586 goto done;
1587 }
1588
1589 /* FIXME: Set security descriptor */
1590 lError = RegCreateKeyExW(hInstKey,
1591 L"Properties",
1592 0,
1593 NULL,
1594 REG_OPTION_NON_VOLATILE,
1595 KEY_ALL_ACCESS,
1596 NULL,
1597 &hPropKey,
1598 NULL);
1599 if (lError != ERROR_SUCCESS)
1600 {
1601 ret = CR_REGISTRY_ERROR;
1602 goto done;
1603 }
1604
1605 if (ulLength == 0)
1606 {
1607 if (RegDeleteValueW(hPropKey,
1608 lpValueName))
1609 ret = CR_REGISTRY_ERROR;
1610 }
1611 else
1612 {
1613 if (RegSetValueExW(hPropKey,
1614 lpValueName,
1615 0,
1616 ulDataType,
1617 Buffer,
1618 ulLength))
1619 ret = CR_REGISTRY_ERROR;
1620 }
1621
1622 done:
1623 if (hPropKey != NULL)
1624 RegCloseKey(hPropKey);
1625
1626 if (hInstKey != NULL)
1627 RegCloseKey(hInstKey);
1628
1629 return ret;
1630 }
1631
1632
1633 static VOID
1634 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
1635 OUT LPWSTR pszEnumerator,
1636 OUT LPWSTR pszDevice,
1637 OUT LPWSTR pszInstance)
1638 {
1639 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
1640 LPWSTR lpEnumerator = NULL;
1641 LPWSTR lpDevice = NULL;
1642 LPWSTR lpInstance = NULL;
1643 LPWSTR ptr;
1644
1645 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
1646
1647 *pszEnumerator = 0;
1648 *pszDevice = 0;
1649 *pszInstance = 0;
1650
1651 lpEnumerator = szLocalDeviceInstanceID;
1652
1653 ptr = wcschr(lpEnumerator, L'\\');
1654 if (ptr != NULL)
1655 {
1656 *ptr = 0;
1657 lpDevice = ++ptr;
1658
1659 ptr = wcschr(lpDevice, L'\\');
1660 if (ptr != NULL)
1661 {
1662 *ptr = 0;
1663 lpInstance = ++ptr;
1664 }
1665 }
1666
1667 if (lpEnumerator != NULL)
1668 wcscpy(pszEnumerator, lpEnumerator);
1669
1670 if (lpDevice != NULL)
1671 wcscpy(pszDevice, lpDevice);
1672
1673 if (lpInstance != NULL)
1674 wcscpy(pszInstance, lpInstance);
1675 }
1676
1677
1678 static CONFIGRET
1679 CreateDeviceInstance(LPWSTR pszDeviceID)
1680 {
1681 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1682 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1683 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1684 HKEY hKeyEnumerator;
1685 HKEY hKeyDevice;
1686 HKEY hKeyInstance;
1687 HKEY hKeyControl;
1688 LONG lError;
1689
1690 /* Split the instance ID */
1691 SplitDeviceInstanceID(pszDeviceID,
1692 szEnumerator,
1693 szDevice,
1694 szInstance);
1695
1696 /* Open or create the enumerator key */
1697 lError = RegCreateKeyExW(hEnumKey,
1698 szEnumerator,
1699 0,
1700 NULL,
1701 REG_OPTION_NON_VOLATILE,
1702 KEY_ALL_ACCESS,
1703 NULL,
1704 &hKeyEnumerator,
1705 NULL);
1706 if (lError != ERROR_SUCCESS)
1707 {
1708 return CR_REGISTRY_ERROR;
1709 }
1710
1711 /* Open or create the device key */
1712 lError = RegCreateKeyExW(hKeyEnumerator,
1713 szDevice,
1714 0,
1715 NULL,
1716 REG_OPTION_NON_VOLATILE,
1717 KEY_ALL_ACCESS,
1718 NULL,
1719 &hKeyDevice,
1720 NULL);
1721
1722 /* Close the enumerator key */
1723 RegCloseKey(hKeyEnumerator);
1724
1725 if (lError != ERROR_SUCCESS)
1726 {
1727 return CR_REGISTRY_ERROR;
1728 }
1729
1730 /* Try to open the instance key and fail if it exists */
1731 lError = RegOpenKeyExW(hKeyDevice,
1732 szInstance,
1733 0,
1734 KEY_SET_VALUE,
1735 &hKeyInstance);
1736 if (lError == ERROR_SUCCESS)
1737 {
1738 DPRINT1("Instance %S already exists!\n", szInstance);
1739 RegCloseKey(hKeyInstance);
1740 RegCloseKey(hKeyDevice);
1741 return CR_ALREADY_SUCH_DEVINST;
1742 }
1743
1744 /* Create a new instance key */
1745 lError = RegCreateKeyExW(hKeyDevice,
1746 szInstance,
1747 0,
1748 NULL,
1749 REG_OPTION_NON_VOLATILE,
1750 KEY_ALL_ACCESS,
1751 NULL,
1752 &hKeyInstance,
1753 NULL);
1754
1755 /* Close the device key */
1756 RegCloseKey(hKeyDevice);
1757
1758 if (lError != ERROR_SUCCESS)
1759 {
1760 return CR_REGISTRY_ERROR;
1761 }
1762
1763 /* Create the 'Control' sub key */
1764 lError = RegCreateKeyExW(hKeyInstance,
1765 L"Control",
1766 0,
1767 NULL,
1768 REG_OPTION_NON_VOLATILE,
1769 KEY_ALL_ACCESS,
1770 NULL,
1771 &hKeyControl,
1772 NULL);
1773 if (lError == ERROR_SUCCESS)
1774 {
1775 RegCloseKey(hKeyControl);
1776 }
1777
1778 RegCloseKey(hKeyInstance);
1779
1780 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
1781 }
1782
1783
1784 /* Function 28 */
1785 DWORD
1786 WINAPI
1787 PNP_CreateDevInst(
1788 handle_t hBinding,
1789 LPWSTR pszDeviceID,
1790 LPWSTR pszParentDeviceID,
1791 PNP_RPC_STRING_LEN ulLength,
1792 DWORD ulFlags)
1793 {
1794 CONFIGRET ret = CR_SUCCESS;
1795
1796 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
1797
1798 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
1799 {
1800 WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN];
1801 DWORD dwInstanceNumber;
1802
1803 /* Generated ID is: Root\<Device ID>\<Instance number> */
1804 dwInstanceNumber = 0;
1805 do
1806 {
1807 swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu",
1808 pszDeviceID, dwInstanceNumber);
1809
1810 /* Try to create a device instance with this ID */
1811 ret = CreateDeviceInstance(szGeneratedInstance);
1812
1813 dwInstanceNumber++;
1814 }
1815 while (ret == CR_ALREADY_SUCH_DEVINST);
1816
1817 if (ret == CR_SUCCESS)
1818 {
1819 /* pszDeviceID is an out parameter too for generated IDs */
1820 if (wcslen(szGeneratedInstance) > ulLength)
1821 {
1822 ret = CR_BUFFER_SMALL;
1823 }
1824 else
1825 {
1826 wcscpy(pszDeviceID, szGeneratedInstance);
1827 }
1828 }
1829 }
1830 else
1831 {
1832 /* Create the device instance */
1833 ret = CreateDeviceInstance(pszDeviceID);
1834 }
1835
1836 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
1837
1838 return ret;
1839 }
1840
1841
1842 static CONFIGRET
1843 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
1844 LPWSTR pszDeviceInstanceSource)
1845 {
1846 DPRINT("MoveDeviceInstance: not implemented\n");
1847 /* FIXME */
1848 return CR_CALL_NOT_IMPLEMENTED;
1849 }
1850
1851
1852 static CONFIGRET
1853 SetupDeviceInstance(LPWSTR pszDeviceInstance,
1854 DWORD ulFlags)
1855 {
1856 DPRINT("SetupDeviceInstance: not implemented\n");
1857 /* FIXME */
1858 return CR_CALL_NOT_IMPLEMENTED;
1859 }
1860
1861
1862 static CONFIGRET
1863 EnableDeviceInstance(LPWSTR pszDeviceInstance)
1864 {
1865 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1866 CONFIGRET ret = CR_SUCCESS;
1867 NTSTATUS Status;
1868
1869 DPRINT("Enable device instance %S\n", pszDeviceInstance);
1870
1871 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
1872 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1873 if (!NT_SUCCESS(Status))
1874 ret = NtStatusToCrError(Status);
1875
1876 return ret;
1877 }
1878
1879
1880 static CONFIGRET
1881 DisableDeviceInstance(LPWSTR pszDeviceInstance)
1882 {
1883 DPRINT("DisableDeviceInstance: not implemented\n");
1884 /* FIXME */
1885 return CR_CALL_NOT_IMPLEMENTED;
1886 }
1887
1888
1889 static CONFIGRET
1890 ReenumerateDeviceInstance(
1891 _In_ LPWSTR pszDeviceInstance,
1892 _In_ ULONG ulFlags)
1893 {
1894 PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
1895 CONFIGRET ret = CR_SUCCESS;
1896 NTSTATUS Status;
1897
1898 DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
1899 pszDeviceInstance, ulFlags);
1900
1901 if (ulFlags & ~CM_REENUMERATE_BITS)
1902 return CR_INVALID_FLAG;
1903
1904 if (ulFlags & CM_REENUMERATE_RETRY_INSTALLATION)
1905 {
1906 DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
1907 }
1908
1909 RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance,
1910 pszDeviceInstance);
1911 EnumerateDeviceData.Flags = 0;
1912
1913 Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice,
1914 &EnumerateDeviceData,
1915 sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA));
1916 if (!NT_SUCCESS(Status))
1917 ret = NtStatusToCrError(Status);
1918
1919 return ret;
1920 }
1921
1922
1923 /* Function 29 */
1924 DWORD
1925 WINAPI
1926 PNP_DeviceInstanceAction(
1927 handle_t hBinding,
1928 DWORD ulAction,
1929 DWORD ulFlags,
1930 LPWSTR pszDeviceInstance1,
1931 LPWSTR pszDeviceInstance2)
1932 {
1933 CONFIGRET ret = CR_SUCCESS;
1934
1935 UNREFERENCED_PARAMETER(hBinding);
1936
1937 DPRINT("PNP_DeviceInstanceAction() called\n");
1938
1939 switch (ulAction)
1940 {
1941 case PNP_DEVINST_MOVE:
1942 ret = MoveDeviceInstance(pszDeviceInstance1,
1943 pszDeviceInstance2);
1944 break;
1945
1946 case PNP_DEVINST_SETUP:
1947 ret = SetupDeviceInstance(pszDeviceInstance1,
1948 ulFlags);
1949 break;
1950
1951 case PNP_DEVINST_ENABLE:
1952 ret = EnableDeviceInstance(pszDeviceInstance1);
1953 break;
1954
1955 case PNP_DEVINST_DISABLE:
1956 ret = DisableDeviceInstance(pszDeviceInstance1);
1957 break;
1958
1959 case PNP_DEVINST_REENUMERATE:
1960 ret = ReenumerateDeviceInstance(pszDeviceInstance1,
1961 ulFlags);
1962 break;
1963
1964 default:
1965 DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
1966 ret = CR_CALL_NOT_IMPLEMENTED;
1967 }
1968
1969 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1970
1971 return ret;
1972 }
1973
1974
1975 /* Function 30 */
1976 DWORD
1977 WINAPI
1978 PNP_GetDeviceStatus(
1979 handle_t hBinding,
1980 LPWSTR pDeviceID,
1981 DWORD *pulStatus,
1982 DWORD *pulProblem,
1983 DWORD ulFlags)
1984 {
1985 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1986 CONFIGRET ret = CR_SUCCESS;
1987 NTSTATUS Status;
1988
1989 UNREFERENCED_PARAMETER(hBinding);
1990 UNREFERENCED_PARAMETER(ulFlags);
1991
1992 DPRINT("PNP_GetDeviceStatus() called\n");
1993
1994 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1995 pDeviceID);
1996 PlugPlayData.Operation = 0; /* Get status */
1997
1998 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1999 (PVOID)&PlugPlayData,
2000 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
2001 if (NT_SUCCESS(Status))
2002 {
2003 *pulStatus = PlugPlayData.DeviceStatus;
2004 *pulProblem = PlugPlayData.DeviceProblem;
2005 }
2006 else
2007 {
2008 ret = NtStatusToCrError(Status);
2009 }
2010
2011 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
2012
2013 return ret;
2014 }
2015
2016
2017 /* Function 31 */
2018 DWORD
2019 WINAPI
2020 PNP_SetDeviceProblem(
2021 handle_t hBinding,
2022 LPWSTR pDeviceID,
2023 DWORD ulProblem,
2024 DWORD ulFlags)
2025 {
2026 UNIMPLEMENTED;
2027 return CR_CALL_NOT_IMPLEMENTED;
2028 }
2029
2030
2031 /* Function 32 */
2032 DWORD
2033 WINAPI
2034 PNP_DisableDevInst(
2035 handle_t hBinding,
2036 LPWSTR pDeviceID,
2037 PPNP_VETO_TYPE pVetoType,
2038 LPWSTR pszVetoName,
2039 DWORD ulNameLength,
2040 DWORD ulFlags)
2041 {
2042 UNIMPLEMENTED;
2043 return CR_CALL_NOT_IMPLEMENTED;
2044 }
2045
2046 /* Function 33 */
2047 DWORD
2048 WINAPI
2049 PNP_UninstallDevInst(
2050 handle_t hBinding,
2051 LPWSTR pDeviceID,
2052 DWORD ulFlags)
2053 {
2054 UNIMPLEMENTED;
2055 return CR_CALL_NOT_IMPLEMENTED;
2056 }
2057
2058
2059 static BOOL
2060 CheckForDeviceId(LPWSTR lpDeviceIdList,
2061 LPWSTR lpDeviceId)
2062 {
2063 LPWSTR lpPtr;
2064 DWORD dwLength;
2065
2066 lpPtr = lpDeviceIdList;
2067 while (*lpPtr != 0)
2068 {
2069 dwLength = wcslen(lpPtr);
2070 if (0 == _wcsicmp(lpPtr, lpDeviceId))
2071 return TRUE;
2072
2073 lpPtr += (dwLength + 1);
2074 }
2075
2076 return FALSE;
2077 }
2078
2079
2080 static VOID
2081 AppendDeviceId(LPWSTR lpDeviceIdList,
2082 LPDWORD lpDeviceIdListSize,
2083 LPWSTR lpDeviceId)
2084 {
2085 DWORD dwLen;
2086 DWORD dwPos;
2087
2088 dwLen = wcslen(lpDeviceId);
2089 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
2090
2091 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
2092
2093 dwPos += (dwLen + 1);
2094
2095 lpDeviceIdList[dwPos] = 0;
2096
2097 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
2098 }
2099
2100
2101 /* Function 34 */
2102 DWORD
2103 WINAPI
2104 PNP_AddID(
2105 handle_t hBinding,
2106 LPWSTR pszDeviceID,
2107 LPWSTR pszID,
2108 DWORD ulFlags)
2109 {
2110 CONFIGRET ret = CR_SUCCESS;
2111 HKEY hDeviceKey;
2112 LPWSTR pszSubKey;
2113 DWORD dwDeviceIdListSize;
2114 DWORD dwNewDeviceIdSize;
2115 WCHAR * pszDeviceIdList = NULL;
2116
2117 UNREFERENCED_PARAMETER(hBinding);
2118
2119 DPRINT("PNP_AddID() called\n");
2120 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
2121 DPRINT(" DeviceId: %S\n", pszID);
2122 DPRINT(" Flags: %lx\n", ulFlags);
2123
2124 if (RegOpenKeyExW(hEnumKey,
2125 pszDeviceID,
2126 0,
2127 KEY_QUERY_VALUE | KEY_SET_VALUE,
2128 &hDeviceKey) != ERROR_SUCCESS)
2129 {
2130 DPRINT("Failed to open the device key!\n");
2131 return CR_INVALID_DEVNODE;
2132 }
2133
2134 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
2135
2136 if (RegQueryValueExW(hDeviceKey,
2137 pszSubKey,
2138 NULL,
2139 NULL,
2140 NULL,
2141 &dwDeviceIdListSize) != ERROR_SUCCESS)
2142 {
2143 DPRINT("Failed to query the desired ID string!\n");
2144 ret = CR_REGISTRY_ERROR;
2145 goto Done;
2146 }
2147
2148 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
2149 if (!dwNewDeviceIdSize)
2150 {
2151 ret = CR_INVALID_POINTER;
2152 goto Done;
2153 }
2154
2155 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
2156
2157 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
2158 if (!pszDeviceIdList)
2159 {
2160 DPRINT("Failed to allocate memory for the desired ID string!\n");
2161 ret = CR_OUT_OF_MEMORY;
2162 goto Done;
2163 }
2164
2165 if (RegQueryValueExW(hDeviceKey,
2166 pszSubKey,
2167 NULL,
2168 NULL,
2169 (LPBYTE)pszDeviceIdList,
2170 &dwDeviceIdListSize) != ERROR_SUCCESS)
2171 {
2172 DPRINT("Failed to query the desired ID string!\n");
2173 ret = CR_REGISTRY_ERROR;
2174 goto Done;
2175 }
2176
2177 /* Check whether the device ID is already in use */
2178 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
2179 {
2180 DPRINT("Device ID was found in the ID string!\n");
2181 ret = CR_SUCCESS;
2182 goto Done;
2183 }
2184
2185 /* Append the Device ID */
2186 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
2187
2188 if (RegSetValueExW(hDeviceKey,
2189 pszSubKey,
2190 0,
2191 REG_MULTI_SZ,
2192 (LPBYTE)pszDeviceIdList,
2193 dwDeviceIdListSize) != ERROR_SUCCESS)
2194 {
2195 DPRINT("Failed to set the desired ID string!\n");
2196 ret = CR_REGISTRY_ERROR;
2197 }
2198
2199 Done:
2200 RegCloseKey(hDeviceKey);
2201 if (pszDeviceIdList)
2202 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
2203
2204 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
2205
2206 return ret;
2207 }
2208
2209
2210 /* Function 35 */
2211 DWORD
2212 WINAPI
2213 PNP_RegisterDriver(
2214 handle_t hBinding,
2215 LPWSTR pszDeviceID,
2216 DWORD ulFlags)
2217 {
2218 UNIMPLEMENTED;
2219 return CR_CALL_NOT_IMPLEMENTED;
2220 }
2221
2222
2223 /* Function 36 */
2224 DWORD
2225 WINAPI
2226 PNP_QueryRemove(
2227 handle_t hBinding,
2228 LPWSTR pszDeviceID,
2229 PPNP_VETO_TYPE pVetoType,
2230 LPWSTR pszVetoName,
2231 DWORD ulNameLength,
2232 DWORD ulFlags)
2233 {
2234 UNIMPLEMENTED;
2235 return CR_CALL_NOT_IMPLEMENTED;
2236 }
2237
2238
2239 /* Function 37 */
2240 DWORD
2241 WINAPI
2242 PNP_RequestDeviceEject(
2243 handle_t hBinding,
2244 LPWSTR pszDeviceID,
2245 PPNP_VETO_TYPE pVetoType,
2246 LPWSTR pszVetoName,
2247 DWORD ulNameLength,
2248 DWORD ulFlags)
2249 {
2250 UNIMPLEMENTED;
2251 return CR_CALL_NOT_IMPLEMENTED;
2252 }
2253
2254
2255 /* Function 38 */
2256 CONFIGRET
2257 WINAPI
2258 PNP_IsDockStationPresent(
2259 handle_t hBinding,
2260 BOOL *Present)
2261 {
2262 HKEY hKey;
2263 DWORD dwType;
2264 DWORD dwValue;
2265 DWORD dwSize;
2266 CONFIGRET ret = CR_SUCCESS;
2267
2268 UNREFERENCED_PARAMETER(hBinding);
2269
2270 DPRINT1("PNP_IsDockStationPresent() called\n");
2271
2272 *Present = FALSE;
2273
2274 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
2275 L"CurrentDockInfo",
2276 0,
2277 KEY_READ,
2278 &hKey) != ERROR_SUCCESS)
2279 return CR_REGISTRY_ERROR;
2280
2281 dwSize = sizeof(DWORD);
2282 if (RegQueryValueExW(hKey,
2283 L"DockingState",
2284 NULL,
2285 &dwType,
2286 (LPBYTE)&dwValue,
2287 &dwSize) != ERROR_SUCCESS)
2288 ret = CR_REGISTRY_ERROR;
2289
2290 RegCloseKey(hKey);
2291
2292 if (ret == CR_SUCCESS)
2293 {
2294 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
2295 {
2296 ret = CR_REGISTRY_ERROR;
2297 }
2298 else if (dwValue != 0)
2299 {
2300 *Present = TRUE;
2301 }
2302 }
2303
2304 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
2305
2306 return ret;
2307 }
2308
2309
2310 /* Function 39 */
2311 DWORD
2312 WINAPI
2313 PNP_RequestEjectPC(
2314 handle_t hBinding)
2315 {
2316 UNIMPLEMENTED;
2317 return CR_CALL_NOT_IMPLEMENTED;
2318 }
2319
2320
2321 /* Function 40 */
2322 DWORD
2323 WINAPI
2324 PNP_HwProfFlags(
2325 handle_t hBinding,
2326 DWORD ulAction,
2327 LPWSTR pDeviceID,
2328 DWORD ulConfig,
2329 DWORD *pulValue,
2330 PPNP_VETO_TYPE pVetoType,
2331 LPWSTR pszVetoName,
2332 DWORD ulNameLength,
2333 DWORD ulFlags)
2334 {
2335 CONFIGRET ret = CR_SUCCESS;
2336 WCHAR szKeyName[MAX_PATH];
2337 HKEY hKey;
2338 HKEY hDeviceKey;
2339 DWORD dwSize;
2340
2341 UNREFERENCED_PARAMETER(hBinding);
2342
2343 DPRINT("PNP_HwProfFlags() called\n");
2344
2345 if (ulConfig == 0)
2346 {
2347 wcscpy(szKeyName,
2348 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
2349 }
2350 else
2351 {
2352 swprintf(szKeyName,
2353 L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum",
2354 ulConfig);
2355 }
2356
2357 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2358 szKeyName,
2359 0,
2360 KEY_QUERY_VALUE,
2361 &hKey) != ERROR_SUCCESS)
2362 return CR_REGISTRY_ERROR;
2363
2364 if (ulAction == PNP_GET_HWPROFFLAGS)
2365 {
2366 if (RegOpenKeyExW(hKey,
2367 pDeviceID,
2368 0,
2369 KEY_QUERY_VALUE,
2370 &hDeviceKey) != ERROR_SUCCESS)
2371 {
2372 *pulValue = 0;
2373 }
2374 else
2375 {
2376 dwSize = sizeof(DWORD);
2377 if (RegQueryValueExW(hDeviceKey,
2378 L"CSConfigFlags",
2379 NULL,
2380 NULL,
2381 (LPBYTE)pulValue,
2382 &dwSize) != ERROR_SUCCESS)
2383 {
2384 *pulValue = 0;
2385 }
2386
2387 RegCloseKey(hDeviceKey);
2388 }
2389 }
2390 else if (ulAction == PNP_SET_HWPROFFLAGS)
2391 {
2392 /* FIXME: not implemented yet */
2393 ret = CR_CALL_NOT_IMPLEMENTED;
2394 }
2395
2396 RegCloseKey(hKey);
2397
2398 return ret;
2399 }
2400
2401
2402 /* Function 41 */
2403 DWORD
2404 WINAPI
2405 PNP_GetHwProfInfo(
2406 handle_t hBinding,
2407 DWORD ulIndex,
2408 HWPROFILEINFO *pHWProfileInfo,
2409 DWORD ulProfileInfoSize,
2410 DWORD ulFlags)
2411 {
2412 WCHAR szProfileName[5];
2413 HKEY hKeyConfig = NULL;
2414 HKEY hKeyProfiles = NULL;
2415 HKEY hKeyProfile = NULL;
2416 DWORD dwDisposition;
2417 DWORD dwSize;
2418 LONG lError;
2419 CONFIGRET ret = CR_SUCCESS;
2420
2421 UNREFERENCED_PARAMETER(hBinding);
2422
2423 DPRINT("PNP_GetHwProfInfo() called\n");
2424
2425 if (ulProfileInfoSize == 0)
2426 {
2427 ret = CR_INVALID_DATA;
2428 goto done;
2429 }
2430
2431 if (ulFlags != 0)
2432 {
2433 ret = CR_INVALID_FLAG;
2434 goto done;
2435 }
2436
2437 /* Initialize the profile information */
2438 pHWProfileInfo->HWPI_ulHWProfile = 0;
2439 pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
2440 pHWProfileInfo->HWPI_dwFlags = 0;
2441
2442 /* Open the 'IDConfigDB' key */
2443 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2444 L"System\\CurrentControlSet\\Control\\IDConfigDB",
2445 0,
2446 NULL,
2447 REG_OPTION_NON_VOLATILE,
2448 KEY_QUERY_VALUE,
2449 NULL,
2450 &hKeyConfig,
2451 &dwDisposition);
2452 if (lError != ERROR_SUCCESS)
2453 {
2454 ret = CR_REGISTRY_ERROR;
2455 goto done;
2456 }
2457
2458 /* Open the 'Hardware Profiles' subkey */
2459 lError = RegCreateKeyExW(hKeyConfig,
2460 L"Hardware Profiles",
2461 0,
2462 NULL,
2463 REG_OPTION_NON_VOLATILE,
2464 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
2465 NULL,
2466 &hKeyProfiles,
2467 &dwDisposition);
2468 if (lError != ERROR_SUCCESS)
2469 {
2470 ret = CR_REGISTRY_ERROR;
2471 goto done;
2472 }
2473
2474 if (ulIndex == (ULONG)-1)
2475 {
2476 dwSize = sizeof(ULONG);
2477 lError = RegQueryValueExW(hKeyConfig,
2478 L"CurrentConfig",
2479 NULL,
2480 NULL,
2481 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
2482 &dwSize);
2483 if (lError != ERROR_SUCCESS)
2484 {
2485 pHWProfileInfo->HWPI_ulHWProfile = 0;
2486 ret = CR_REGISTRY_ERROR;
2487 goto done;
2488 }
2489 }
2490 else
2491 {
2492 /* FIXME: not implemented yet */
2493 ret = CR_CALL_NOT_IMPLEMENTED;
2494 goto done;
2495 }
2496
2497 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
2498
2499 lError = RegOpenKeyExW(hKeyProfiles,
2500 szProfileName,
2501 0,
2502 KEY_QUERY_VALUE,
2503 &hKeyProfile);
2504 if (lError != ERROR_SUCCESS)
2505 {
2506 ret = CR_REGISTRY_ERROR;
2507 goto done;
2508 }
2509
2510 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
2511 lError = RegQueryValueExW(hKeyProfile,
2512 L"FriendlyName",
2513 NULL,
2514 NULL,
2515 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
2516 &dwSize);
2517 if (lError != ERROR_SUCCESS)
2518 {
2519 ret = CR_REGISTRY_ERROR;
2520 goto done;
2521 }
2522
2523 done:
2524 if (hKeyProfile != NULL)
2525 RegCloseKey(hKeyProfile);
2526
2527 if (hKeyProfiles != NULL)
2528 RegCloseKey(hKeyProfiles);
2529
2530 if (hKeyConfig != NULL)
2531 RegCloseKey(hKeyConfig);
2532
2533 return ret;
2534 }
2535
2536
2537 /* Function 42 */
2538 DWORD
2539 WINAPI
2540 PNP_AddEmptyLogConf(
2541 handle_t hBinding,
2542 LPWSTR pDeviceID,
2543 DWORD ulPriority,
2544 DWORD *pulLogConfTag,
2545 DWORD ulFlags)
2546 {
2547 UNIMPLEMENTED;
2548 return CR_CALL_NOT_IMPLEMENTED;
2549 }
2550
2551
2552 /* Function 43 */
2553 DWORD
2554 WINAPI
2555 PNP_FreeLogConf(
2556 handle_t hBinding,
2557 LPWSTR pDeviceID,
2558 DWORD ulLogConfType,
2559 DWORD ulLogConfTag,
2560 DWORD ulFlags)
2561 {
2562 UNIMPLEMENTED;
2563 return CR_CALL_NOT_IMPLEMENTED;
2564 }
2565
2566
2567 /* Function 44 */
2568 DWORD
2569 WINAPI
2570 PNP_GetFirstLogConf(
2571 handle_t hBinding,
2572 LPWSTR pDeviceID,
2573 DWORD ulLogConfType,
2574 DWORD *pulLogConfTag,
2575 DWORD ulFlags)
2576 {
2577 UNIMPLEMENTED;
2578 return CR_CALL_NOT_IMPLEMENTED;
2579 }
2580
2581
2582 /* Function 45 */
2583 DWORD
2584 WINAPI
2585 PNP_GetNextLogConf(
2586 handle_t hBinding,
2587 LPWSTR pDeviceID,
2588 DWORD ulLogConfType,
2589 DWORD ulCurrentTag,
2590 DWORD *pulNextTag,
2591 DWORD ulFlags)
2592 {
2593 UNIMPLEMENTED;
2594 return CR_CALL_NOT_IMPLEMENTED;
2595 }
2596
2597
2598 /* Function 46 */
2599 DWORD
2600 WINAPI
2601 PNP_GetLogConfPriority(
2602 handle_t hBinding,
2603 LPWSTR pDeviceID,
2604 DWORD ulType,
2605 DWORD ulTag,
2606 DWORD *pPriority,
2607 DWORD ulFlags)
2608 {
2609 UNIMPLEMENTED;
2610 return CR_CALL_NOT_IMPLEMENTED;
2611 }
2612
2613
2614 /* Function 47 */
2615 DWORD
2616 WINAPI
2617 PNP_AddResDes(
2618 handle_t hBinding,
2619 LPWSTR pDeviceID,
2620 DWORD ulLogConfTag,
2621 DWORD ulLogConfType,
2622 RESOURCEID ResourceID,
2623 DWORD *pulResourceTag,
2624 BYTE *ResourceData,
2625 PNP_RPC_BUFFER_SIZE ResourceLen,
2626 DWORD ulFlags)
2627 {
2628 UNIMPLEMENTED;
2629 return CR_CALL_NOT_IMPLEMENTED;
2630 }
2631
2632
2633 /* Function 48 */
2634 DWORD
2635 WINAPI
2636 PNP_FreeResDes(
2637 handle_t hBinding,
2638 LPWSTR pDeviceID,
2639 DWORD ulLogConfTag,
2640 DWORD ulLogConfType,
2641 RESOURCEID ResourceID,
2642 DWORD ulResourceTag,
2643 DWORD *pulPreviousResType,
2644 DWORD *pulPreviousResTag,
2645 DWORD ulFlags)
2646 {
2647 UNIMPLEMENTED;
2648 return CR_CALL_NOT_IMPLEMENTED;
2649 }
2650
2651
2652 /* Function 49 */
2653 DWORD
2654 WINAPI
2655 PNP_GetNextResDes(
2656 handle_t hBinding,
2657 LPWSTR pDeviceID,
2658 DWORD ulLogConfTag,
2659 DWORD ulLogConfType,
2660 RESOURCEID ResourceID,
2661 DWORD ulResourceTag,
2662 DWORD *pulNextResType,
2663 DWORD *pulNextResTag,
2664 DWORD ulFlags)
2665 {
2666 UNIMPLEMENTED;
2667 return CR_CALL_NOT_IMPLEMENTED;
2668 }
2669
2670
2671 /* Function 50 */
2672 DWORD
2673 WINAPI
2674 PNP_GetResDesData(
2675 handle_t hBinding,
2676 LPWSTR pDeviceID,
2677 DWORD ulLogConfTag,
2678 DWORD ulLogConfType,
2679 RESOURCEID ResourceID,
2680 DWORD ulResourceTag,
2681 BYTE *Buffer,
2682 PNP_RPC_BUFFER_SIZE BufferLen,
2683 DWORD ulFlags)
2684 {
2685 UNIMPLEMENTED;
2686 return CR_CALL_NOT_IMPLEMENTED;
2687 }
2688
2689
2690 /* Function 51 */
2691 DWORD
2692 WINAPI
2693 PNP_GetResDesDataSize(
2694 handle_t hBinding,
2695 LPWSTR pDeviceID,
2696 DWORD ulLogConfTag,
2697 DWORD ulLogConfType,
2698 RESOURCEID ResourceID,
2699 DWORD ulResourceTag,
2700 DWORD *pulSize,
2701 DWORD ulFlags)
2702 {
2703 UNIMPLEMENTED;
2704 return CR_CALL_NOT_IMPLEMENTED;
2705 }
2706
2707
2708 /* Function 52 */
2709 DWORD
2710 WINAPI
2711 PNP_ModifyResDes(
2712 handle_t hBinding,
2713 LPWSTR pDeviceID,
2714 DWORD ulLogConfTag,
2715 DWORD ulLogConfType,
2716 RESOURCEID CurrentResourceID,
2717 RESOURCEID NewResourceID,
2718 DWORD ulResourceTag,
2719 BYTE *ResourceData,
2720 PNP_RPC_BUFFER_SIZE ResourceLen,
2721 DWORD ulFlags)
2722 {
2723 UNIMPLEMENTED;
2724 return CR_CALL_NOT_IMPLEMENTED;
2725 }
2726
2727
2728 /* Function 53 */
2729 DWORD
2730 WINAPI
2731 PNP_DetectResourceConflict(
2732 handle_t hBinding,
2733 LPWSTR pDeviceID,
2734 RESOURCEID ResourceID,
2735 BYTE *ResourceData,
2736 PNP_RPC_BUFFER_SIZE ResourceLen,
2737 BOOL *pbConflictDetected,
2738 DWORD ulFlags)
2739 {
2740 DPRINT("PNP_DetectResourceConflict()\n");
2741
2742 if (pbConflictDetected != NULL)
2743 *pbConflictDetected = FALSE;
2744
2745 return CR_CALL_NOT_IMPLEMENTED;
2746 }
2747
2748
2749 /* Function 54 */
2750 DWORD
2751 WINAPI
2752 PNP_QueryResConfList(
2753 handle_t hBinding,
2754 LPWSTR pDeviceID,
2755 RESOURCEID ResourceID,
2756 BYTE *ResourceData,
2757 PNP_RPC_BUFFER_SIZE ResourceLen,
2758 BYTE *Buffer,
2759 PNP_RPC_BUFFER_SIZE BufferLen,
2760 DWORD ulFlags)
2761 {
2762 UNIMPLEMENTED;
2763 return CR_CALL_NOT_IMPLEMENTED;
2764 }
2765
2766
2767 /* Function 55 */
2768 DWORD
2769 WINAPI
2770 PNP_SetHwProf(
2771 handle_t hBinding,
2772 DWORD ulHardwareProfile,
2773 DWORD ulFlags)
2774 {
2775 UNIMPLEMENTED;
2776 return CR_CALL_NOT_IMPLEMENTED;
2777 }
2778
2779
2780 /* Function 56 */
2781 DWORD
2782 WINAPI
2783 PNP_QueryArbitratorFreeData(
2784 handle_t hBinding,
2785 BYTE *pData,
2786 DWORD DataLen,
2787 LPWSTR pDeviceID,
2788 RESOURCEID ResourceID,
2789 DWORD ulFlags)
2790 {
2791 UNIMPLEMENTED;
2792 return CR_CALL_NOT_IMPLEMENTED;
2793 }
2794
2795
2796 /* Function 57 */
2797 DWORD
2798 WINAPI
2799 PNP_QueryArbitratorFreeSize(
2800 handle_t hBinding,
2801 DWORD *pulSize,
2802 LPWSTR pDeviceID,
2803 RESOURCEID ResourceID,
2804 DWORD ulFlags)
2805 {
2806 UNIMPLEMENTED;
2807 return CR_CALL_NOT_IMPLEMENTED;
2808 }
2809
2810
2811 /* Function 58 */
2812 CONFIGRET
2813 WINAPI
2814 PNP_RunDetection(
2815 handle_t hBinding,
2816 DWORD ulFlags)
2817 {
2818 return CR_CALL_NOT_IMPLEMENTED;
2819 }
2820
2821
2822 /* Function 59 */
2823 DWORD
2824 WINAPI
2825 PNP_RegisterNotification(
2826 handle_t hBinding,
2827 DWORD ulFlags,
2828 DWORD *pulNotify)
2829 {
2830 #if 0
2831 PNOTIFY_DATA pNotifyData;
2832 #endif
2833
2834 DPRINT1("PNP_RegisterNotification(%p 0x%lx %p)\n",
2835 hBinding, ulFlags, pulNotify);
2836
2837 #if 0
2838 pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA));
2839 if (pNotifyData == NULL)
2840 return CR_OUT_OF_MEMORY;
2841
2842 *pulNotify = (DWORD)pNotifyData;
2843 #endif
2844
2845 *pulNotify = 1;
2846
2847 return CR_SUCCESS;
2848 }
2849
2850
2851 /* Function 60 */
2852 DWORD
2853 WINAPI
2854 PNP_UnregisterNotification(
2855 handle_t hBinding,
2856 DWORD ulNotify)
2857 {
2858 DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n",
2859 hBinding, ulNotify);
2860
2861 #if 0
2862 UNIMPLEMENTED;
2863 return CR_CALL_NOT_IMPLEMENTED;
2864 #endif
2865
2866 return CR_SUCCESS;
2867 }
2868
2869
2870 /* Function 61 */
2871 DWORD
2872 WINAPI
2873 PNP_GetCustomDevProp(
2874 handle_t hBinding,
2875 LPWSTR pDeviceID,
2876 LPWSTR CustomPropName,
2877 DWORD *pulRegDataType,
2878 BYTE *Buffer,
2879 PNP_RPC_STRING_LEN *pulTransferLen,
2880 PNP_RPC_STRING_LEN *pulLength,
2881 DWORD ulFlags)
2882 {
2883 HKEY hDeviceKey = NULL;
2884 HKEY hParamKey = NULL;
2885 LONG lError;
2886 CONFIGRET ret = CR_SUCCESS;
2887
2888 UNREFERENCED_PARAMETER(hBinding);
2889
2890 DPRINT("PNP_GetCustomDevProp() called\n");
2891
2892 if (pulTransferLen == NULL || pulLength == NULL)
2893 {
2894 ret = CR_INVALID_POINTER;
2895 goto done;
2896 }
2897
2898 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
2899 {
2900 ret = CR_INVALID_FLAG;
2901 goto done;
2902 }
2903
2904 if (*pulLength < *pulTransferLen)
2905 *pulLength = *pulTransferLen;
2906
2907 *pulTransferLen = 0;
2908
2909 lError = RegOpenKeyExW(hEnumKey,
2910 pDeviceID,
2911 0,
2912 KEY_READ,
2913 &hDeviceKey);
2914 if (lError != ERROR_SUCCESS)
2915 {
2916 ret = CR_REGISTRY_ERROR;
2917 goto done;
2918 }
2919
2920 lError = RegOpenKeyExW(hDeviceKey,
2921 L"Device Parameters",
2922 0,
2923 KEY_READ,
2924 &hParamKey);
2925 if (lError != ERROR_SUCCESS)
2926 {
2927 ret = CR_REGISTRY_ERROR;
2928 goto done;
2929 }
2930
2931 lError = RegQueryValueExW(hParamKey,
2932 CustomPropName,
2933 NULL,
2934 pulRegDataType,
2935 Buffer,
2936 pulLength);
2937 if (lError != ERROR_SUCCESS)
2938 {
2939 if (lError == ERROR_MORE_DATA)
2940 {
2941 ret = CR_BUFFER_SMALL;
2942 }
2943 else
2944 {
2945 *pulLength = 0;
2946 ret = CR_NO_SUCH_VALUE;
2947 }
2948 }
2949
2950 done:
2951 if (ret == CR_SUCCESS)
2952 *pulTransferLen = *pulLength;
2953
2954 if (hParamKey != NULL)
2955 RegCloseKey(hParamKey);
2956
2957 if (hDeviceKey != NULL)
2958 RegCloseKey(hDeviceKey);
2959
2960 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
2961
2962 return ret;
2963 }
2964
2965
2966 /* Function 62 */
2967 DWORD
2968 WINAPI
2969 PNP_GetVersionInternal(
2970 handle_t hBinding,
2971 WORD *pwVersion)
2972 {
2973 UNREFERENCED_PARAMETER(hBinding);
2974
2975 *pwVersion = 0x501;
2976 return CR_SUCCESS;
2977 }
2978
2979
2980 /* Function 63 */
2981 DWORD
2982 WINAPI
2983 PNP_GetBlockedDriverInfo(
2984 handle_t hBinding,
2985 BYTE *Buffer,
2986 PNP_RPC_BUFFER_SIZE *pulTransferLen,
2987 PNP_RPC_BUFFER_SIZE *pulLength,
2988 DWORD ulFlags)
2989 {
2990 UNIMPLEMENTED;
2991 return CR_CALL_NOT_IMPLEMENTED;
2992 }
2993
2994
2995 /* Function 64 */
2996 DWORD
2997 WINAPI
2998 PNP_GetServerSideDeviceInstallFlags(
2999 handle_t hBinding,
3000 DWORD *pulSSDIFlags,
3001 DWORD ulFlags)
3002 {
3003 UNREFERENCED_PARAMETER(hBinding);
3004
3005 DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n",
3006 hBinding, pulSSDIFlags, ulFlags);
3007
3008 if (pulSSDIFlags == NULL)
3009 return CR_INVALID_POINTER;
3010
3011 if (ulFlags != 0)
3012 return CR_INVALID_FLAG;
3013
3014 /* FIXME */
3015 *pulSSDIFlags = 0;
3016
3017 return CR_SUCCESS;
3018 }
3019
3020
3021 /* Function 65 */
3022 DWORD
3023 WINAPI
3024 PNP_GetObjectPropKeys(
3025 handle_t hBinding,
3026 LPWSTR ObjectName,
3027 DWORD ObjectType,
3028 LPWSTR PropertyCultureName,
3029 PNP_PROP_COUNT *PropertyCount,
3030 PNP_PROP_COUNT *TransferLen,
3031 DEVPROPKEY *PropertyKeys,
3032 DWORD Flags)
3033 {
3034 UNIMPLEMENTED;
3035 return CR_CALL_NOT_IMPLEMENTED;
3036 }
3037
3038
3039 /* Function 66 */
3040 DWORD
3041 WINAPI
3042 PNP_GetObjectProp(
3043 handle_t hBinding,
3044 LPWSTR ObjectName,
3045 DWORD ObjectType,
3046 LPWSTR PropertyCultureName,
3047 const DEVPROPKEY *PropertyKey,
3048 DEVPROPTYPE *PropertyType,
3049 PNP_PROP_SIZE *PropertySize,
3050 PNP_PROP_SIZE *TransferLen,
3051 BYTE *PropertyBuffer,
3052 DWORD Flags)
3053 {
3054 UNIMPLEMENTED;
3055 return CR_CALL_NOT_IMPLEMENTED;
3056 }
3057
3058
3059 /* Function 67 */
3060 DWORD
3061 WINAPI
3062 PNP_SetObjectProp(
3063 handle_t hBinding,
3064 LPWSTR ObjectName,
3065 DWORD ObjectType,
3066 LPWSTR PropertyCultureName,
3067 const DEVPROPKEY *PropertyKey,
3068 DEVPROPTYPE PropertyType,
3069 PNP_PROP_SIZE PropertySize,
3070 BYTE *PropertyBuffer,
3071 DWORD Flags)
3072 {
3073 UNIMPLEMENTED;
3074 return CR_CALL_NOT_IMPLEMENTED;
3075 }
3076
3077
3078 /* Function 68 */
3079 DWORD
3080 WINAPI
3081 PNP_InstallDevInst(
3082 handle_t hBinding)
3083 {
3084 UNIMPLEMENTED;
3085 return CR_CALL_NOT_IMPLEMENTED;
3086 }
3087
3088
3089 /* Function 69 */
3090 DWORD
3091 WINAPI
3092 PNP_ApplyPowerSettings(
3093 handle_t hBinding)
3094 {
3095 UNIMPLEMENTED;
3096 return CR_CALL_NOT_IMPLEMENTED;
3097 }
3098
3099
3100 /* Function 70 */
3101 DWORD
3102 WINAPI
3103 PNP_DriverStoreAddDriverPackage(
3104 handle_t hBinding)
3105 {
3106 UNIMPLEMENTED;
3107 return CR_CALL_NOT_IMPLEMENTED;
3108 }
3109
3110
3111 /* Function 71 */
3112 DWORD
3113 WINAPI
3114 PNP_DriverStoreDeleteDriverPackage(
3115 handle_t hBinding)
3116 {
3117 UNIMPLEMENTED;
3118 return CR_CALL_NOT_IMPLEMENTED;
3119 }
3120
3121
3122 /* Function 72 */
3123 DWORD
3124 WINAPI
3125 PNP_RegisterServiceNotification(
3126 handle_t hBinding)
3127 {
3128 UNIMPLEMENTED;
3129 return CR_CALL_NOT_IMPLEMENTED;
3130 }
3131
3132
3133 /* Function 73 */
3134 DWORD
3135 WINAPI
3136 PNP_SetActiveService(
3137 handle_t hBinding,
3138 LPWSTR pszFilter,
3139 DWORD ulFlags)
3140 {
3141 UNIMPLEMENTED;
3142 return CR_CALL_NOT_IMPLEMENTED;
3143 }
3144
3145
3146 /* Function 74 */
3147 DWORD
3148 WINAPI
3149 PNP_DeleteServiceDevices(
3150 handle_t hBinding)
3151 {
3152 UNIMPLEMENTED;
3153 return CR_CALL_NOT_IMPLEMENTED;
3154 }
3155
3156
3157 static BOOL
3158 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
3159 {
3160 BOOL DeviceInstalled = FALSE;
3161 DWORD BytesWritten;
3162 DWORD Value;
3163 HANDLE hInstallEvent;
3164 HANDLE hPipe = INVALID_HANDLE_VALUE;
3165 LPVOID Environment = NULL;
3166 PROCESS_INFORMATION ProcessInfo;
3167 STARTUPINFOW StartupInfo;
3168 UUID RandomUuid;
3169 HKEY DeviceKey;
3170
3171 /* The following lengths are constant (see below), they cannot overflow */
3172 WCHAR CommandLine[116];
3173 WCHAR InstallEventName[73];
3174 WCHAR PipeName[74];
3175 WCHAR UuidString[39];
3176
3177 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
3178
3179 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
3180
3181 if (RegOpenKeyExW(hEnumKey,
3182 DeviceInstance,
3183 0,
3184 KEY_QUERY_VALUE,
3185 &DeviceKey) == ERROR_SUCCESS)
3186 {
3187 if (RegQueryValueExW(DeviceKey,
3188 L"Class",
3189 NULL,
3190 NULL,
3191 NULL,
3192 NULL) == ERROR_SUCCESS)
3193 {
3194 DPRINT("No need to install: %S\n", DeviceInstance);
3195 RegCloseKey(DeviceKey);
3196 return TRUE;
3197 }
3198
3199 BytesWritten = sizeof(DWORD);
3200 if (RegQueryValueExW(DeviceKey,
3201 L"ConfigFlags",
3202 NULL,
3203 NULL,
3204 (PBYTE)&Value,
3205 &BytesWritten) == ERROR_SUCCESS)
3206 {
3207 if (Value & CONFIGFLAG_FAILEDINSTALL)
3208 {
3209 DPRINT("No need to install: %S\n", DeviceInstance);
3210 RegCloseKey(DeviceKey);
3211 return TRUE;
3212 }
3213 }
3214
3215 RegCloseKey(DeviceKey);
3216 }
3217
3218 DPRINT1("Installing: %S\n", DeviceInstance);
3219
3220 /* Create a random UUID for the named pipe & event*/
3221 UuidCreate(&RandomUuid);
3222 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
3223 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
3224 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
3225 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
3226 RandomUuid.Data4[6], RandomUuid.Data4[7]);
3227
3228 /* Create the event */
3229 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
3230 wcscat(InstallEventName, UuidString);
3231 hInstallEvent = CreateEventW(NULL, TRUE, FALSE, InstallEventName);
3232 if (!hInstallEvent)
3233 {
3234 DPRINT1("CreateEventW('%ls') failed with error %lu\n", InstallEventName, GetLastError());
3235 goto cleanup;
3236 }
3237
3238 /* Create the named pipe */
3239 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
3240 wcscat(PipeName, UuidString);
3241 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
3242 if (hPipe == INVALID_HANDLE_VALUE)
3243 {
3244 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
3245 goto cleanup;
3246 }
3247
3248 /* Launch rundll32 to call ClientSideInstallW */
3249 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
3250 wcscat(CommandLine, PipeName);
3251
3252 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
3253 StartupInfo.cb = sizeof(StartupInfo);
3254
3255 if (hUserToken)
3256 {
3257 /* newdev has to run under the environment of the current user */
3258 if (!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
3259 {
3260 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
3261 goto cleanup;
3262 }
3263
3264 if (!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
3265 {
3266 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
3267 goto cleanup;
3268 }
3269 }
3270 else
3271 {
3272 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
3273
3274 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
3275 (ShowWizard is only set to FALSE for these two modes) */
3276 ASSERT(!ShowWizard);
3277
3278 if (!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
3279 {
3280 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
3281 goto cleanup;
3282 }
3283 }
3284
3285 /* Wait for the function to connect to our pipe */
3286 if (!ConnectNamedPipe(hPipe, NULL))
3287 {
3288 if (GetLastError() != ERROR_PIPE_CONNECTED)
3289 {
3290 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
3291 goto cleanup;
3292 }
3293 }
3294
3295 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
3296 Value = sizeof(InstallEventName);
3297 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
3298 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
3299
3300 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
3301 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
3302 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
3303
3304 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
3305 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
3306 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
3307
3308 /* Wait for newdev.dll to finish processing */
3309 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
3310
3311 /* If the event got signalled, this is success */
3312 DeviceInstalled = WaitForSingleObject(hInstallEvent, 0) == WAIT_OBJECT_0;
3313
3314 cleanup:
3315 if (hInstallEvent)
3316 CloseHandle(hInstallEvent);
3317
3318 if (hPipe != INVALID_HANDLE_VALUE)
3319 CloseHandle(hPipe);
3320
3321 if (Environment)
3322 DestroyEnvironmentBlock(Environment);
3323
3324 if (ProcessInfo.hProcess)
3325 CloseHandle(ProcessInfo.hProcess);
3326
3327 if (ProcessInfo.hThread)
3328 CloseHandle(ProcessInfo.hThread);
3329
3330 if (!DeviceInstalled)
3331 {
3332 DPRINT1("InstallDevice failed for DeviceInstance '%ws'\n", DeviceInstance);
3333 }
3334
3335 return DeviceInstalled;
3336 }
3337
3338
3339 static LONG
3340 ReadRegSzKey(
3341 IN HKEY hKey,
3342 IN LPCWSTR pszKey,
3343 OUT LPWSTR* pValue)
3344 {
3345 LONG rc;
3346 DWORD dwType;
3347 DWORD cbData = 0;
3348 LPWSTR Value;
3349
3350 if (!pValue)
3351 return ERROR_INVALID_PARAMETER;
3352
3353 *pValue = NULL;
3354 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
3355 if (rc != ERROR_SUCCESS)
3356 return rc;
3357 if (dwType != REG_SZ)
3358 return ERROR_FILE_NOT_FOUND;
3359 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
3360 if (!Value)
3361 return ERROR_NOT_ENOUGH_MEMORY;
3362 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
3363 if (rc != ERROR_SUCCESS)
3364 {
3365 HeapFree(GetProcessHeap(), 0, Value);
3366 return rc;
3367 }
3368 /* NULL-terminate the string */
3369 Value[cbData / sizeof(WCHAR)] = '\0';
3370
3371 *pValue = Value;
3372 return ERROR_SUCCESS;
3373 }
3374
3375
3376 static BOOL
3377 SetupIsActive(VOID)
3378 {
3379 HKEY hKey = NULL;
3380 DWORD regType, active, size;
3381 LONG rc;
3382 BOOL ret = FALSE;
3383
3384 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
3385 if (rc != ERROR_SUCCESS)
3386 goto cleanup;
3387
3388 size = sizeof(DWORD);
3389 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
3390 if (rc != ERROR_SUCCESS)
3391 goto cleanup;
3392 if (regType != REG_DWORD || size != sizeof(DWORD))
3393 goto cleanup;
3394
3395 ret = (active != 0);
3396
3397 cleanup:
3398 if (hKey != NULL)
3399 RegCloseKey(hKey);
3400
3401 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
3402
3403 return ret;
3404 }
3405
3406
3407 static BOOL
3408 IsConsoleBoot(VOID)
3409 {
3410 HKEY ControlKey = NULL;
3411 LPWSTR SystemStartOptions = NULL;
3412 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
3413 BOOL ConsoleBoot = FALSE;
3414 LONG rc;
3415
3416 rc = RegOpenKeyExW(
3417 HKEY_LOCAL_MACHINE,
3418 L"SYSTEM\\CurrentControlSet\\Control",
3419 0,
3420 KEY_QUERY_VALUE,
3421 &ControlKey);
3422
3423 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
3424 if (rc != ERROR_SUCCESS)
3425 goto cleanup;
3426
3427 /* Check for CONSOLE switch in SystemStartOptions */
3428 CurrentOption = SystemStartOptions;
3429 while (CurrentOption)
3430 {
3431 NextOption = wcschr(CurrentOption, L' ');
3432 if (NextOption)
3433 *NextOption = L'\0';
3434 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
3435 {
3436 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
3437 ConsoleBoot = TRUE;
3438 goto cleanup;
3439 }
3440 CurrentOption = NextOption ? NextOption + 1 : NULL;
3441 }
3442
3443 cleanup:
3444 if (ControlKey != NULL)
3445 RegCloseKey(ControlKey);
3446 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
3447 return ConsoleBoot;
3448 }
3449
3450
3451 /* Loop to install all queued devices installations */
3452 static DWORD WINAPI
3453 DeviceInstallThread(LPVOID lpParameter)
3454 {
3455 PSLIST_ENTRY ListEntry;
3456 DeviceInstallParams* Params;
3457 BOOL showWizard;
3458
3459 UNREFERENCED_PARAMETER(lpParameter);
3460
3461 WaitForSingleObject(hInstallEvent, INFINITE);
3462
3463 showWizard = !SetupIsActive() && !IsConsoleBoot();
3464
3465 while (TRUE)
3466 {
3467 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
3468
3469 if (ListEntry == NULL)
3470 {
3471 SetEvent(hNoPendingInstalls);
3472 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
3473 }
3474 else
3475 {
3476 ResetEvent(hNoPendingInstalls);
3477 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
3478 InstallDevice(Params->DeviceIds, showWizard);
3479 }
3480 }
3481
3482 return 0;
3483 }
3484
3485
3486 static DWORD WINAPI
3487 PnpEventThread(LPVOID lpParameter)
3488 {
3489 PPLUGPLAY_EVENT_BLOCK PnpEvent;
3490 ULONG PnpEventSize;
3491 NTSTATUS Status;
3492 RPC_STATUS RpcStatus;
3493
3494 UNREFERENCED_PARAMETER(lpParameter);
3495
3496 PnpEventSize = 0x1000;
3497 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
3498 if (PnpEvent == NULL)
3499 return ERROR_OUTOFMEMORY;
3500
3501 for (;;)
3502 {
3503 DPRINT("Calling NtGetPlugPlayEvent()\n");
3504
3505 /* Wait for the next pnp event */
3506 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
3507
3508 /* Resize the buffer for the PnP event if it's too small. */
3509 if (Status == STATUS_BUFFER_TOO_SMALL)
3510 {
3511 PnpEventSize += 0x400;
3512 HeapFree(GetProcessHeap(), 0, PnpEvent);
3513 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
3514 if (PnpEvent == NULL)
3515 return ERROR_OUTOFMEMORY;
3516 continue;
3517 }
3518
3519 if (!NT_SUCCESS(Status))
3520 {
3521 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
3522 break;
3523 }
3524
3525 /* Process the pnp event */
3526 DPRINT("Received PnP Event\n");
3527 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
3528 {
3529 DeviceInstallParams* Params;
3530 DWORD len;
3531 DWORD DeviceIdLength;
3532
3533 DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
3534
3535 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
3536 if (DeviceIdLength)
3537 {
3538 /* Queue device install (will be dequeued by DeviceInstallThread) */
3539 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
3540 Params = HeapAlloc(GetProcessHeap(), 0, len);
3541 if (Params)
3542 {
3543 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
3544 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
3545 SetEvent(hDeviceInstallListNotEmpty);
3546 }
3547 }
3548 }
3549 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
3550 {
3551 // DWORD dwRecipient;
3552
3553 DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
3554
3555 // dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
3556 // BroadcastSystemMessageW(BSF_POSTMESSAGE,
3557 // &dwRecipient,
3558 // WM_DEVICECHANGE,
3559 // DBT_DEVNODES_CHANGED,
3560 // 0);
3561 SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
3562 }
3563 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
3564 {
3565 DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
3566 }
3567 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
3568 {
3569 DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
3570 }
3571 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
3572 {
3573 // DWORD dwRecipient;
3574
3575 DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
3576
3577 // dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
3578 // BroadcastSystemMessageW(BSF_POSTMESSAGE,
3579 // &dwRecipient,
3580 // WM_DEVICECHANGE,
3581 // DBT_DEVNODES_CHANGED,
3582 // 0);
3583 SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
3584 }
3585 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
3586 {
3587 // DWORD dwRecipient;
3588
3589 DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
3590
3591 // dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
3592 // BroadcastSystemMessageW(BSF_POSTMESSAGE,
3593 // &dwRecipient,
3594 // WM_DEVICECHANGE,
3595 // DBT_DEVNODES_CHANGED,
3596 // 0);
3597 SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
3598 }
3599 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
3600 {
3601 DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
3602 }
3603 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
3604 {
3605 DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
3606 }
3607 else
3608 {
3609 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
3610 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
3611 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
3612 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
3613 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
3614 }
3615
3616 /* Dequeue the current pnp event and signal the next one */
3617 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
3618 }
3619
3620 HeapFree(GetProcessHeap(), 0, PnpEvent);
3621
3622 return ERROR_SUCCESS;
3623 }
3624
3625
3626 static VOID
3627 UpdateServiceStatus(DWORD dwState)
3628 {
3629 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
3630 ServiceStatus.dwCurrentState = dwState;
3631 ServiceStatus.dwControlsAccepted = 0;
3632 ServiceStatus.dwWin32ExitCode = 0;
3633 ServiceStatus.dwServiceSpecificExitCode = 0;
3634 ServiceStatus.dwCheckPoint = 0;
3635
3636 if (dwState == SERVICE_START_PENDING ||
3637 dwState == SERVICE_STOP_PENDING ||
3638 dwState == SERVICE_PAUSE_PENDING ||
3639 dwState == SERVICE_CONTINUE_PENDING)
3640 ServiceStatus.dwWaitHint = 10000;
3641 else
3642 ServiceStatus.dwWaitHint = 0;
3643
3644 SetServiceStatus(ServiceStatusHandle,
3645 &ServiceStatus);
3646 }
3647
3648
3649 static DWORD WINAPI
3650 ServiceControlHandler(DWORD dwControl,
3651 DWORD dwEventType,
3652 LPVOID lpEventData,
3653 LPVOID lpContext)
3654 {
3655 DPRINT1("ServiceControlHandler() called\n");
3656
3657 switch (dwControl)
3658 {
3659 case SERVICE_CONTROL_STOP:
3660 DPRINT1(" SERVICE_CONTROL_STOP received\n");
3661 /* Stop listening to RPC Messages */
3662 RpcMgmtStopServerListening(NULL);
3663 UpdateServiceStatus(SERVICE_STOPPED);
3664 return ERROR_SUCCESS;
3665
3666 case SERVICE_CONTROL_PAUSE:
3667 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
3668 UpdateServiceStatus(SERVICE_PAUSED);
3669 return ERROR_SUCCESS;
3670
3671 case SERVICE_CONTROL_CONTINUE:
3672 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
3673 UpdateServiceStatus(SERVICE_RUNNING);
3674 return ERROR_SUCCESS;
3675
3676 case SERVICE_CONTROL_INTERROGATE:
3677 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
3678 SetServiceStatus(ServiceStatusHandle,
3679 &ServiceStatus);
3680 return ERROR_SUCCESS;
3681
3682 case SERVICE_CONTROL_SHUTDOWN:
3683 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
3684 /* Stop listening to RPC Messages */
3685 RpcMgmtStopServerListening(NULL);
3686 UpdateServiceStatus(SERVICE_STOPPED);
3687 return ERROR_SUCCESS;
3688
3689 default :
3690 DPRINT1(" Control %lu received\n", dwControl);
3691 return ERROR_CALL_NOT_IMPLEMENTED;
3692 }
3693 }
3694
3695
3696 VOID WINAPI
3697 ServiceMain(DWORD argc, LPTSTR *argv)
3698 {
3699 HANDLE hThread;
3700 DWORD dwThreadId;
3701
3702 UNREFERENCED_PARAMETER(argc);
3703 UNREFERENCED_PARAMETER(argv);
3704
3705 DPRINT("ServiceMain() called\n");
3706
3707 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
3708 ServiceControlHandler,
3709 NULL);
3710 if (!ServiceStatusHandle)
3711 {
3712 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
3713 return;
3714 }
3715
3716 UpdateServiceStatus(SERVICE_START_PENDING);
3717
3718 hThread = CreateThread(NULL,
3719 0,
3720 PnpEventThread,
3721 NULL,
3722 0,
3723 &dwThreadId);
3724 if (hThread != NULL)
3725 CloseHandle(hThread);
3726
3727 hThread = CreateThread(NULL,
3728 0,
3729 RpcServerThread,
3730 NULL,
3731 0,
3732 &dwThreadId);
3733 if (hThread != NULL)
3734 CloseHandle(hThread);
3735
3736 hThread = CreateThread(NULL,
3737 0,
3738 DeviceInstallThread,
3739 NULL,
3740 0,
3741 &dwThreadId);
3742 if (hThread != NULL)
3743 CloseHandle(hThread);
3744
3745 UpdateServiceStatus(SERVICE_RUNNING);
3746
3747 DPRINT("ServiceMain() done\n");
3748 }
3749
3750 static DWORD
3751 InitializePnPManager(VOID)
3752 {
3753 BOOLEAN OldValue;
3754 DWORD dwError;
3755
3756 DPRINT("UMPNPMGR: InitializePnPManager() started\n");
3757
3758 /* We need this privilege for using CreateProcessAsUserW */
3759 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
3760
3761 hInstallEvent = CreateEventW(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
3762 if (hInstallEvent == NULL)
3763 {
3764 dwError = GetLastError();
3765 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
3766 return dwError;
3767 }
3768
3769 hDeviceInstallListNotEmpty = CreateEventW(NULL, FALSE, FALSE, NULL);
3770 if (hDeviceInstallListNotEmpty == NULL)
3771 {
3772 dwError = GetLastError();
3773 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3774 return dwError;
3775 }
3776
3777 hNoPendingInstalls = CreateEventW(NULL,
3778 TRUE,
3779 FALSE,
3780 L"Global\\PnP_No_Pending_Install_Events");
3781 if (hNoPendingInstalls == NULL)
3782 {
3783 dwError = GetLastError();
3784 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3785 return dwError;
3786 }
3787
3788 InitializeSListHead(&DeviceInstallListHead);
3789
3790 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3791 L"System\\CurrentControlSet\\Enum",
3792 0,
3793 KEY_ALL_ACCESS,
3794 &hEnumKey);
3795 if (dwError != ERROR_SUCCESS)
3796 {
3797 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
3798 return dwError;
3799 }
3800
3801 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3802 L"System\\CurrentControlSet\\Control\\Class",
3803 0,
3804 KEY_ALL_ACCESS,
3805 &hClassKey);
3806 if (dwError != ERROR_SUCCESS)
3807 {
3808 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
3809 return dwError;
3810 }
3811
3812 DPRINT("UMPNPMGR: InitializePnPManager() done\n");
3813
3814 return 0;
3815 }
3816
3817 BOOL WINAPI
3818 DllMain(HINSTANCE hinstDLL,
3819 DWORD fdwReason,
3820 LPVOID lpvReserved)
3821 {
3822 switch (fdwReason)
3823 {
3824 case DLL_PROCESS_ATTACH:
3825 DisableThreadLibraryCalls(hinstDLL);
3826 InitializePnPManager();
3827 break;
3828
3829 case DLL_PROCESS_DETACH:
3830 break;
3831 }
3832
3833 return TRUE;
3834 }
3835
3836 /* EOF */