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