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