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