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