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