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