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