03fd855c94632532c4771d03310019c6209659d3
[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 <stdio.h>
41 #include <cmfuncs.h>
42 #include <rtlfuncs.h>
43 #include <setypes.h>
44 #include <umpnpmgr/sysguid.h>
45 #include <cfgmgr32.h>
46 #include <regstr.h>
47 #include <userenv.h>
48 #include <shlwapi.h>
49 #include <pnp_s.h>
50
51 #define NDEBUG
52 #include <debug.h>
53
54 /* GLOBALS ******************************************************************/
55
56 static WCHAR ServiceName[] = L"PlugPlay";
57
58 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
59 static SERVICE_STATUS ServiceStatus;
60
61 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
62
63 static HKEY hEnumKey = NULL;
64 static HKEY hClassKey = NULL;
65
66 static HANDLE hUserToken = NULL;
67 static HANDLE hInstallEvent = NULL;
68 static HANDLE hNoPendingInstalls = NULL;
69
70 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
71 static SLIST_HEADER DeviceInstallListHead;
72 #else
73 static LIST_ENTRY DeviceInstallListHead;
74 #endif
75 static HANDLE hDeviceInstallListNotEmpty;
76
77 typedef struct
78 {
79 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
80 SLIST_ENTRY ListEntry;
81 #else
82 LIST_ENTRY ListEntry;
83 #endif
84 WCHAR DeviceIds[1];
85 } DeviceInstallParams;
86
87 /* FUNCTIONS *****************************************************************/
88
89 static DWORD WINAPI
90 RpcServerThread(LPVOID lpParameter)
91 {
92 RPC_STATUS Status;
93 BOOLEAN RegisteredProtSeq = FALSE;
94
95 UNREFERENCED_PARAMETER(lpParameter);
96
97 DPRINT("RpcServerThread() called\n");
98
99 #if 0
100 /* 2k/XP/2k3-compatible protocol sequence/endpoint */
101 Status = RpcServerUseProtseqEpW(L"ncacn_np",
102 20,
103 L"\\pipe\\ntsvcs",
104 NULL); // Security descriptor
105 if (Status == RPC_S_OK)
106 RegisteredProtSeq = TRUE;
107 else
108 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
109 #endif
110
111 /* Vista/7-compatible protocol sequence/endpoint */
112 Status = RpcServerUseProtseqEpW(L"ncacn_np",
113 20,
114 L"\\pipe\\plugplay",
115 NULL); // Security descriptor
116 if (Status == RPC_S_OK)
117 RegisteredProtSeq = TRUE;
118 else
119 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
120
121 /* Make sure there's a usable endpoint */
122 if (RegisteredProtSeq == FALSE)
123 return 0;
124
125 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
126 NULL,
127 NULL);
128 if (Status != RPC_S_OK)
129 {
130 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
131 return 0;
132 }
133
134 Status = RpcServerListen(1,
135 20,
136 FALSE);
137 if (Status != RPC_S_OK)
138 {
139 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
140 return 0;
141 }
142
143 /* ROS HACK (this should never happen...) */
144 DPRINT1("*** Other devices won't be installed correctly. If something\n");
145 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
146
147 DPRINT("RpcServerThread() done\n");
148
149 return 0;
150 }
151
152
153 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
154 {
155 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
156 }
157
158
159 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
160 {
161 HeapFree(GetProcessHeap(), 0, ptr);
162 }
163
164
165 static CONFIGRET WINAPI
166 NtStatusToCrError(NTSTATUS Status)
167 {
168 switch (Status)
169 {
170 case STATUS_NO_SUCH_DEVICE:
171 return CR_NO_SUCH_DEVINST;
172 case STATUS_NOT_IMPLEMENTED:
173 return CR_CALL_NOT_IMPLEMENTED;
174
175 default:
176 /* FIXME: add more mappings */
177 DPRINT1("Unable to map status 0x%08lx\n", Status);
178 return CR_FAILURE;
179 }
180 }
181
182
183 /* Function 0 */
184 DWORD
185 WINAPI
186 PNP_Disconnect(
187 handle_t hBinding)
188 {
189 UNREFERENCED_PARAMETER(hBinding);
190 return CR_SUCCESS;
191 }
192
193
194 /* Function 1 */
195 DWORD
196 WINAPI
197 PNP_Connect(
198 handle_t hBinding)
199 {
200 UNREFERENCED_PARAMETER(hBinding);
201 return CR_SUCCESS;
202 }
203
204
205 /* Function 2 */
206 DWORD
207 WINAPI
208 PNP_GetVersion(
209 handle_t hBinding,
210 WORD *pVersion)
211 {
212 UNREFERENCED_PARAMETER(hBinding);
213
214 *pVersion = 0x0400;
215 return CR_SUCCESS;
216 }
217
218
219 /* Function 3 */
220 DWORD
221 WINAPI
222 PNP_GetGlobalState(
223 handle_t hBinding,
224 DWORD *pulState,
225 DWORD ulFlags)
226 {
227 UNREFERENCED_PARAMETER(hBinding);
228 UNREFERENCED_PARAMETER(ulFlags);
229
230 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
231 return CR_SUCCESS;
232 }
233
234
235 /* Function 4 */
236 DWORD
237 WINAPI
238 PNP_InitDetection(
239 handle_t hBinding)
240 {
241 UNREFERENCED_PARAMETER(hBinding);
242
243 DPRINT("PNP_InitDetection() called\n");
244 return CR_SUCCESS;
245 }
246
247
248 /* Function 5 */
249 DWORD
250 WINAPI
251 PNP_ReportLogOn(
252 handle_t hBinding,
253 BOOL Admin,
254 DWORD ProcessId)
255 {
256 DWORD ReturnValue = CR_FAILURE;
257 HANDLE hProcess;
258
259 UNREFERENCED_PARAMETER(hBinding);
260 UNREFERENCED_PARAMETER(Admin);
261
262 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
263
264 /* Get the users token */
265 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
266
267 if (!hProcess)
268 {
269 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
270 goto cleanup;
271 }
272
273 if (hUserToken)
274 {
275 CloseHandle(hUserToken);
276 hUserToken = NULL;
277 }
278
279 if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
280 {
281 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
282 goto cleanup;
283 }
284
285 /* Trigger the installer thread */
286 if (hInstallEvent)
287 SetEvent(hInstallEvent);
288
289 ReturnValue = CR_SUCCESS;
290
291 cleanup:
292 if (hProcess)
293 CloseHandle(hProcess);
294
295 return ReturnValue;
296 }
297
298
299 /* Function 6 */
300 DWORD
301 WINAPI
302 PNP_ValidateDeviceInstance(
303 handle_t hBinding,
304 LPWSTR pDeviceID,
305 DWORD ulFlags)
306 {
307 CONFIGRET ret = CR_SUCCESS;
308 HKEY hDeviceKey = NULL;
309
310 UNREFERENCED_PARAMETER(hBinding);
311 UNREFERENCED_PARAMETER(ulFlags);
312
313 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
314 pDeviceID, ulFlags);
315
316 if (RegOpenKeyExW(hEnumKey,
317 pDeviceID,
318 0,
319 KEY_READ,
320 &hDeviceKey))
321 {
322 DPRINT("Could not open the Device Key!\n");
323 ret = CR_NO_SUCH_DEVNODE;
324 goto Done;
325 }
326
327 /* FIXME: add more tests */
328
329 Done:
330 if (hDeviceKey != NULL)
331 RegCloseKey(hDeviceKey);
332
333 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
334
335 return ret;
336 }
337
338
339 /* Function 7 */
340 DWORD
341 WINAPI
342 PNP_GetRootDeviceInstance(
343 handle_t hBinding,
344 LPWSTR pDeviceID,
345 PNP_RPC_STRING_LEN ulLength)
346 {
347 CONFIGRET ret = CR_SUCCESS;
348
349 UNREFERENCED_PARAMETER(hBinding);
350
351 DPRINT("PNP_GetRootDeviceInstance() called\n");
352
353 if (!pDeviceID)
354 {
355 ret = CR_INVALID_POINTER;
356 goto Done;
357 }
358 if (ulLength < lstrlenW(szRootDeviceId) + 1)
359 {
360 ret = CR_BUFFER_SMALL;
361 goto Done;
362 }
363
364 lstrcpyW(pDeviceID,
365 szRootDeviceId);
366
367 Done:
368 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
369
370 return ret;
371 }
372
373
374 /* Function 8 */
375 DWORD
376 WINAPI
377 PNP_GetRelatedDeviceInstance(
378 handle_t hBinding,
379 DWORD ulRelationship,
380 LPWSTR pDeviceID,
381 LPWSTR pRelatedDeviceId,
382 PNP_RPC_STRING_LEN *pulLength,
383 DWORD ulFlags)
384 {
385 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
386 CONFIGRET ret = CR_SUCCESS;
387 NTSTATUS Status;
388
389 UNREFERENCED_PARAMETER(hBinding);
390 UNREFERENCED_PARAMETER(ulFlags);
391
392 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
393 DPRINT(" Relationship %ld\n", ulRelationship);
394 DPRINT(" DeviceId %S\n", pDeviceID);
395
396 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
397 pDeviceID);
398
399 PlugPlayData.Relation = ulRelationship;
400
401 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
402 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
403
404 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
405 (PVOID)&PlugPlayData,
406 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
407 if (!NT_SUCCESS(Status))
408 {
409 ret = NtStatusToCrError(Status);
410 }
411
412 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
413 if (ret == CR_SUCCESS)
414 {
415 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
416 }
417
418 return ret;
419 }
420
421
422 /* Function 9 */
423 DWORD
424 WINAPI
425 PNP_EnumerateSubKeys(
426 handle_t hBinding,
427 DWORD ulBranch,
428 DWORD ulIndex,
429 LPWSTR Buffer,
430 PNP_RPC_STRING_LEN ulLength,
431 PNP_RPC_STRING_LEN *pulRequiredLen,
432 DWORD ulFlags)
433 {
434 CONFIGRET ret = CR_SUCCESS;
435 HKEY hKey;
436 DWORD dwError;
437
438 UNREFERENCED_PARAMETER(hBinding);
439 UNREFERENCED_PARAMETER(ulFlags);
440
441 DPRINT("PNP_EnumerateSubKeys() called\n");
442
443 switch (ulBranch)
444 {
445 case PNP_ENUMERATOR_SUBKEYS:
446 hKey = hEnumKey;
447 break;
448
449 case PNP_CLASS_SUBKEYS:
450 hKey = hClassKey;
451 break;
452
453 default:
454 return CR_FAILURE;
455 }
456
457 *pulRequiredLen = ulLength;
458 dwError = RegEnumKeyExW(hKey,
459 ulIndex,
460 Buffer,
461 pulRequiredLen,
462 NULL,
463 NULL,
464 NULL,
465 NULL);
466 if (dwError != ERROR_SUCCESS)
467 {
468 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
469 }
470 else
471 {
472 (*pulRequiredLen)++;
473 }
474
475 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
476
477 return ret;
478 }
479
480
481 /* Function 10 */
482 DWORD
483 WINAPI
484 PNP_GetDeviceList(
485 handle_t hBinding,
486 LPWSTR pszFilter,
487 LPWSTR Buffer,
488 PNP_RPC_STRING_LEN *pulLength,
489 DWORD ulFlags)
490 {
491 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
492 CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
493 NTSTATUS Status;
494
495 DPRINT("PNP_GetDeviceList() called\n");
496
497 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
498 return CR_INVALID_FLAG;
499
500 if (pulLength == NULL || pszFilter == NULL)
501 return CR_INVALID_POINTER;
502
503 // if (Buffer == NULL)
504 // return
505
506 *pulLength = 0;
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 /* FIXME */
523 PlugPlayData.Relations = 0;
524 }
525 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
526 {
527 PlugPlayData.Relations = 1;
528 }
529 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
530 {
531 PlugPlayData.Relations = 0;
532 }
533
534 PlugPlayData.BufferSize = *pulLength;
535 PlugPlayData.Buffer = Buffer;
536
537 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
538 (PVOID)&PlugPlayData,
539 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
540 if (NT_SUCCESS(Status))
541 {
542 *pulLength = PlugPlayData.BufferSize;
543 }
544 else
545 {
546 ret = NtStatusToCrError(Status);
547 }
548 }
549 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
550 {
551
552 }
553 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
554 {
555
556 }
557 else /* CM_GETIDLIST_FILTER_NONE */
558 {
559
560 }
561
562 return ret;
563 }
564
565
566 /* Function 11 */
567 DWORD
568 WINAPI
569 PNP_GetDeviceListSize(
570 handle_t hBinding,
571 LPWSTR pszFilter,
572 PNP_RPC_BUFFER_SIZE *pulLength,
573 DWORD ulFlags)
574 {
575 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
576 CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
577 NTSTATUS Status;
578
579 DPRINT("PNP_GetDeviceListSize() called\n");
580
581 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
582 return CR_INVALID_FLAG;
583
584 if (pulLength == NULL || pszFilter == NULL)
585 return CR_INVALID_POINTER;
586
587 *pulLength = 0;
588
589 if (ulFlags &
590 (CM_GETIDLIST_FILTER_BUSRELATIONS |
591 CM_GETIDLIST_FILTER_POWERRELATIONS |
592 CM_GETIDLIST_FILTER_REMOVALRELATIONS |
593 CM_GETIDLIST_FILTER_EJECTRELATIONS))
594 {
595 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
596 pszFilter);
597 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
598 {
599 PlugPlayData.Relations = 3;
600 }
601 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
602 {
603 /* FIXME */
604 PlugPlayData.Relations = 0;
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;
624 }
625 else
626 {
627 ret = NtStatusToCrError(Status);
628 }
629 }
630 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
631 {
632
633 }
634 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
635 {
636
637 }
638 else /* CM_GETIDLIST_FILTER_NONE */
639 {
640
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 lpValueName = NULL;
777 break;
778
779 case CM_DRP_CAPABILITIES:
780 lpValueName = L"Capabilities";
781 break;
782
783 case CM_DRP_UI_NUMBER:
784 lpValueName = NULL;
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 lpValueName = NULL;
797 break;
798
799 case CM_DRP_LEGACYBUSTYPE:
800 lpValueName = NULL;
801 break;
802
803 case CM_DRP_BUSNUMBER:
804 lpValueName = NULL;
805 break;
806
807 case CM_DRP_ENUMERATOR_NAME:
808 lpValueName = NULL;
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 lpValueName = NULL;
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 lpValueName = NULL;
837 break;
838
839 case CM_DRP_REMOVAL_POLICY:
840 lpValueName = NULL;
841 break;
842
843 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
844 lpValueName = NULL;
845 break;
846
847 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
848 lpValueName = L"RemovalPolicy";
849 break;
850
851 case CM_DRP_INSTALL_STATE:
852 lpValueName = NULL;
853 break;
854
855 #if (WINVER >= _WIN32_WINNT_WS03)
856 case CM_DRP_LOCATION_PATHS:
857 lpValueName = NULL;
858 break;
859 #endif
860
861 #if (WINVER >= _WIN32_WINNT_WIN7)
862 case CM_DRP_BASE_CONTAINERID:
863 lpValueName = NULL;
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 switch (ulProperty)
918 {
919 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
920 PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName;
921 break;
922
923 case CM_DRP_UI_NUMBER:
924 PlugPlayData.Property = 0x11; // DevicePropertyUINumber;
925 break;
926
927 case CM_DRP_BUSTYPEGUID:
928 PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid;
929 break;
930
931 case CM_DRP_LEGACYBUSTYPE:
932 PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType;
933 break;
934
935 case CM_DRP_BUSNUMBER:
936 PlugPlayData.Property = 0xe; // DevicePropertyBusNumber;
937 break;
938
939 case CM_DRP_ENUMERATOR_NAME:
940 PlugPlayData.Property = 0xf; // DevicePropertyEnumeratorName;
941 break;
942
943 case CM_DRP_ADDRESS:
944 PlugPlayData.Property = 0x10; // DevicePropertyAddress;
945 break;
946
947 #if 0
948 /* FIXME: This property is not supported by IoGetDeviceProperty */
949 case CM_DRP_DEVICE_POWER_DATA:
950 #endif
951
952 case CM_DRP_REMOVAL_POLICY:
953 PlugPlayData.Property = 0x12; // DevicePropertyRemovalPolicy
954 break;
955
956 #if 0
957 /* FIXME: This property is not supported by IoGetDeviceProperty */
958 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
959 #endif
960
961 case CM_DRP_INSTALL_STATE:
962 PlugPlayData.Property = 0x12; // DevicePropertyInstallState;
963 break;
964
965 #if 0
966 /* FIXME: This property is not supported by IoGetDeviceProperty */
967 #if (WINVER >= _WIN32_WINNT_WS03)
968 case CM_DRP_LOCATION_PATHS:
969 #endif
970 #endif
971
972 #if (WINVER >= _WIN32_WINNT_WIN7)
973 case CM_DRP_BASE_CONTAINERID:
974 PlugPlayData.Property = 0x16; // DevicePropertyContainerID;
975 break;
976 #endif
977
978 default:
979 return CR_INVALID_PROPERTY;
980 }
981
982 Status = NtPlugPlayControl(PlugPlayControlProperty,
983 (PVOID)&PlugPlayData,
984 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
985 if (NT_SUCCESS(Status))
986 {
987 *pulLength = PlugPlayData.BufferSize;
988 }
989 else
990 {
991 ret = NtStatusToCrError(Status);
992 }
993 }
994
995 done:
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 DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
3569 /* FIXME: ? */
3570 }
3571 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
3572 {
3573 DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
3574 }
3575 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
3576 {
3577 DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
3578 }
3579 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
3580 {
3581 DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
3582 }
3583 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
3584 {
3585 DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
3586 }
3587 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
3588 {
3589 DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
3590 }
3591 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
3592 {
3593 DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
3594 }
3595 else
3596 {
3597 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
3598 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
3599 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
3600 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
3601 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
3602 }
3603
3604 /* Dequeue the current pnp event and signal the next one */
3605 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
3606 }
3607
3608 HeapFree(GetProcessHeap(), 0, PnpEvent);
3609
3610 return ERROR_SUCCESS;
3611 }
3612
3613
3614 static VOID
3615 UpdateServiceStatus(DWORD dwState)
3616 {
3617 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
3618 ServiceStatus.dwCurrentState = dwState;
3619 ServiceStatus.dwControlsAccepted = 0;
3620 ServiceStatus.dwWin32ExitCode = 0;
3621 ServiceStatus.dwServiceSpecificExitCode = 0;
3622 ServiceStatus.dwCheckPoint = 0;
3623
3624 if (dwState == SERVICE_START_PENDING ||
3625 dwState == SERVICE_STOP_PENDING ||
3626 dwState == SERVICE_PAUSE_PENDING ||
3627 dwState == SERVICE_CONTINUE_PENDING)
3628 ServiceStatus.dwWaitHint = 10000;
3629 else
3630 ServiceStatus.dwWaitHint = 0;
3631
3632 SetServiceStatus(ServiceStatusHandle,
3633 &ServiceStatus);
3634 }
3635
3636
3637 static DWORD WINAPI
3638 ServiceControlHandler(DWORD dwControl,
3639 DWORD dwEventType,
3640 LPVOID lpEventData,
3641 LPVOID lpContext)
3642 {
3643 DPRINT1("ServiceControlHandler() called\n");
3644
3645 switch (dwControl)
3646 {
3647 case SERVICE_CONTROL_STOP:
3648 DPRINT1(" SERVICE_CONTROL_STOP received\n");
3649 /* Stop listening to RPC Messages */
3650 RpcMgmtStopServerListening(NULL);
3651 UpdateServiceStatus(SERVICE_STOPPED);
3652 return ERROR_SUCCESS;
3653
3654 case SERVICE_CONTROL_PAUSE:
3655 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
3656 UpdateServiceStatus(SERVICE_PAUSED);
3657 return ERROR_SUCCESS;
3658
3659 case SERVICE_CONTROL_CONTINUE:
3660 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
3661 UpdateServiceStatus(SERVICE_RUNNING);
3662 return ERROR_SUCCESS;
3663
3664 case SERVICE_CONTROL_INTERROGATE:
3665 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
3666 SetServiceStatus(ServiceStatusHandle,
3667 &ServiceStatus);
3668 return ERROR_SUCCESS;
3669
3670 case SERVICE_CONTROL_SHUTDOWN:
3671 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
3672 /* Stop listening to RPC Messages */
3673 RpcMgmtStopServerListening(NULL);
3674 UpdateServiceStatus(SERVICE_STOPPED);
3675 return ERROR_SUCCESS;
3676
3677 default :
3678 DPRINT1(" Control %lu received\n", dwControl);
3679 return ERROR_CALL_NOT_IMPLEMENTED;
3680 }
3681 }
3682
3683
3684 VOID WINAPI
3685 ServiceMain(DWORD argc, LPTSTR *argv)
3686 {
3687 HANDLE hThread;
3688 DWORD dwThreadId;
3689
3690 UNREFERENCED_PARAMETER(argc);
3691 UNREFERENCED_PARAMETER(argv);
3692
3693 DPRINT("ServiceMain() called\n");
3694
3695 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
3696 ServiceControlHandler,
3697 NULL);
3698 if (!ServiceStatusHandle)
3699 {
3700 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
3701 return;
3702 }
3703
3704 UpdateServiceStatus(SERVICE_START_PENDING);
3705
3706 hThread = CreateThread(NULL,
3707 0,
3708 PnpEventThread,
3709 NULL,
3710 0,
3711 &dwThreadId);
3712 if (hThread != NULL)
3713 CloseHandle(hThread);
3714
3715 hThread = CreateThread(NULL,
3716 0,
3717 RpcServerThread,
3718 NULL,
3719 0,
3720 &dwThreadId);
3721 if (hThread != NULL)
3722 CloseHandle(hThread);
3723
3724 hThread = CreateThread(NULL,
3725 0,
3726 DeviceInstallThread,
3727 NULL,
3728 0,
3729 &dwThreadId);
3730 if (hThread != NULL)
3731 CloseHandle(hThread);
3732
3733 UpdateServiceStatus(SERVICE_RUNNING);
3734
3735 DPRINT("ServiceMain() done\n");
3736 }
3737
3738 static DWORD
3739 InitializePnPManager(VOID)
3740 {
3741 BOOLEAN OldValue;
3742 DWORD dwError;
3743
3744 DPRINT("UMPNPMGR: InitializePnPManager() started\n");
3745
3746 /* We need this privilege for using CreateProcessAsUserW */
3747 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
3748
3749 hInstallEvent = CreateEventW(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
3750 if (hInstallEvent == NULL)
3751 {
3752 dwError = GetLastError();
3753 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
3754 return dwError;
3755 }
3756
3757 hDeviceInstallListNotEmpty = CreateEventW(NULL, FALSE, FALSE, NULL);
3758 if (hDeviceInstallListNotEmpty == NULL)
3759 {
3760 dwError = GetLastError();
3761 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3762 return dwError;
3763 }
3764
3765 hNoPendingInstalls = CreateEventW(NULL,
3766 TRUE,
3767 FALSE,
3768 L"Global\\PnP_No_Pending_Install_Events");
3769 if (hNoPendingInstalls == NULL)
3770 {
3771 dwError = GetLastError();
3772 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3773 return dwError;
3774 }
3775
3776 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
3777 InitializeSListHead(&DeviceInstallListHead);
3778 #else
3779 InitializeListHead(&DeviceInstallListHead);
3780 #endif
3781
3782 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3783 L"System\\CurrentControlSet\\Enum",
3784 0,
3785 KEY_ALL_ACCESS,
3786 &hEnumKey);
3787 if (dwError != ERROR_SUCCESS)
3788 {
3789 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
3790 return dwError;
3791 }
3792
3793 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3794 L"System\\CurrentControlSet\\Control\\Class",
3795 0,
3796 KEY_ALL_ACCESS,
3797 &hClassKey);
3798 if (dwError != ERROR_SUCCESS)
3799 {
3800 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
3801 return dwError;
3802 }
3803
3804 DPRINT("UMPNPMGR: InitializePnPManager() done\n");
3805
3806 return 0;
3807 }
3808
3809 BOOL WINAPI
3810 DllMain(HINSTANCE hinstDLL,
3811 DWORD fdwReason,
3812 LPVOID lpvReserved)
3813 {
3814 switch (fdwReason)
3815 {
3816 case DLL_PROCESS_ATTACH:
3817 DisableThreadLibraryCalls(hinstDLL);
3818 InitializePnPManager();
3819 break;
3820
3821 case DLL_PROCESS_DETACH:
3822 break;
3823 }
3824
3825 return TRUE;
3826 }
3827
3828 /* EOF */