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