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