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