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