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