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