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