[SETUPAPI][UMPNPMGR] Improve CMP_RegisterNotification/PNP_RegisterNotification
[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 WCHAR szClassGuid[40];
1747 WCHAR szClassInstance[5];
1748 HKEY hDeviceClassKey = NULL;
1749 HKEY hClassInstanceKey;
1750 ULONG ulTransferLength, ulDataLength;
1751 DWORD dwDataType, dwDisposition, i;
1752 DWORD dwError;
1753 CONFIGRET ret = CR_SUCCESS;
1754
1755 DPRINT("PNP_GetClassInstance(%p %S %p %lu)\n",
1756 hBinding, pDeviceId, pszClassInstance, ulLength);
1757
1758 ulTransferLength = ulLength;
1759 ret = PNP_GetDeviceRegProp(hBinding,
1760 pDeviceId,
1761 CM_DRP_DRIVER,
1762 &dwDataType,
1763 (BYTE *)pszClassInstance,
1764 &ulTransferLength,
1765 &ulLength,
1766 0);
1767 if (ret == CR_SUCCESS)
1768 return ret;
1769
1770 ulTransferLength = sizeof(szClassGuid);
1771 ulDataLength = sizeof(szClassGuid);
1772 ret = PNP_GetDeviceRegProp(hBinding,
1773 pDeviceId,
1774 CM_DRP_CLASSGUID,
1775 &dwDataType,
1776 (BYTE *)szClassGuid,
1777 &ulTransferLength,
1778 &ulDataLength,
1779 0);
1780 if (ret != CR_SUCCESS)
1781 {
1782 DPRINT1("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret);
1783 goto done;
1784 }
1785
1786 dwError = RegOpenKeyExW(hClassKey,
1787 szClassGuid,
1788 0,
1789 KEY_READ,
1790 &hDeviceClassKey);
1791 if (dwError != ERROR_SUCCESS)
1792 {
1793 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
1794 ret = CR_FAILURE;
1795 goto done;
1796 }
1797
1798 for (i = 0; i < 10000; i++)
1799 {
1800 wsprintf(szClassInstance, L"%04lu", i);
1801
1802 dwError = RegCreateKeyExW(hDeviceClassKey,
1803 szClassInstance,
1804 0,
1805 NULL,
1806 REG_OPTION_NON_VOLATILE,
1807 KEY_ALL_ACCESS,
1808 NULL,
1809 &hClassInstanceKey,
1810 &dwDisposition);
1811 if (dwError == ERROR_SUCCESS)
1812 {
1813 RegCloseKey(hClassInstanceKey);
1814
1815 if (dwDisposition == REG_CREATED_NEW_KEY)
1816 {
1817 wsprintf(pszClassInstance,
1818 L"%s\\%s",
1819 szClassGuid,
1820 szClassInstance);
1821
1822 ulDataLength = (wcslen(pszClassInstance) + 1) * sizeof(WCHAR);
1823 ret = PNP_SetDeviceRegProp(hBinding,
1824 pDeviceId,
1825 CM_DRP_DRIVER,
1826 REG_SZ,
1827 (BYTE *)pszClassInstance,
1828 ulDataLength,
1829 0);
1830 if (ret != CR_SUCCESS)
1831 {
1832 DPRINT1("PNP_SetDeviceRegProp() failed (Error %lu)\n", ret);
1833 RegDeleteKeyW(hDeviceClassKey,
1834 szClassInstance);
1835 }
1836
1837 break;
1838 }
1839 }
1840 }
1841
1842 done:
1843 if (hDeviceClassKey != NULL)
1844 RegCloseKey(hDeviceClassKey);
1845
1846 return ret;
1847 }
1848
1849
1850 /* Function 16 */
1851 DWORD
1852 WINAPI
1853 PNP_CreateKey(
1854 handle_t hBinding,
1855 LPWSTR pszSubKey,
1856 DWORD samDesired,
1857 DWORD ulFlags)
1858 {
1859 HKEY hKey = 0;
1860
1861 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1862 pszSubKey,
1863 0,
1864 NULL,
1865 0,
1866 KEY_ALL_ACCESS,
1867 NULL,
1868 &hKey,
1869 NULL))
1870 return CR_REGISTRY_ERROR;
1871
1872 /* FIXME: Set security key */
1873
1874 RegCloseKey(hKey);
1875
1876 return CR_SUCCESS;
1877 }
1878
1879
1880 /* Function 17 */
1881 DWORD
1882 WINAPI
1883 PNP_DeleteRegistryKey(
1884 handle_t hBinding,
1885 LPWSTR pszDeviceID,
1886 LPWSTR pszParentKey,
1887 LPWSTR pszChildKey,
1888 DWORD ulFlags)
1889 {
1890 UNIMPLEMENTED;
1891 return CR_CALL_NOT_IMPLEMENTED;
1892 }
1893
1894
1895 /* Function 18 */
1896 DWORD
1897 WINAPI
1898 PNP_GetClassCount(
1899 handle_t hBinding,
1900 DWORD *pulClassCount,
1901 DWORD ulFlags)
1902 {
1903 HKEY hKey;
1904 DWORD dwError;
1905
1906 UNREFERENCED_PARAMETER(hBinding);
1907 UNREFERENCED_PARAMETER(ulFlags);
1908
1909 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1910 REGSTR_PATH_CLASS,
1911 0,
1912 KEY_QUERY_VALUE,
1913 &hKey);
1914 if (dwError != ERROR_SUCCESS)
1915 return CR_INVALID_DATA;
1916
1917 dwError = RegQueryInfoKeyW(hKey,
1918 NULL,
1919 NULL,
1920 NULL,
1921 pulClassCount,
1922 NULL,
1923 NULL,
1924 NULL,
1925 NULL,
1926 NULL,
1927 NULL,
1928 NULL);
1929 RegCloseKey(hKey);
1930 if (dwError != ERROR_SUCCESS)
1931 return CR_INVALID_DATA;
1932
1933 return CR_SUCCESS;
1934 }
1935
1936
1937 /* Function 19 */
1938 DWORD
1939 WINAPI
1940 PNP_GetClassName(
1941 handle_t hBinding,
1942 LPWSTR pszClassGuid,
1943 LPWSTR Buffer,
1944 PNP_RPC_STRING_LEN *pulLength,
1945 DWORD ulFlags)
1946 {
1947 WCHAR szKeyName[MAX_PATH];
1948 CONFIGRET ret = CR_SUCCESS;
1949 HKEY hKey;
1950 DWORD dwSize;
1951
1952 UNREFERENCED_PARAMETER(hBinding);
1953 UNREFERENCED_PARAMETER(ulFlags);
1954
1955 DPRINT("PNP_GetClassName() called\n");
1956
1957 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
1958 if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
1959 lstrcatW(szKeyName, pszClassGuid);
1960 else
1961 return CR_INVALID_DATA;
1962
1963 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1964 szKeyName,
1965 0,
1966 KEY_QUERY_VALUE,
1967 &hKey))
1968 return CR_REGISTRY_ERROR;
1969
1970 dwSize = *pulLength * sizeof(WCHAR);
1971 if (RegQueryValueExW(hKey,
1972 L"Class",
1973 NULL,
1974 NULL,
1975 (LPBYTE)Buffer,
1976 &dwSize))
1977 {
1978 *pulLength = 0;
1979 ret = CR_REGISTRY_ERROR;
1980 }
1981 else
1982 {
1983 *pulLength = dwSize / sizeof(WCHAR);
1984 }
1985
1986 RegCloseKey(hKey);
1987
1988 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
1989
1990 return ret;
1991 }
1992
1993
1994 /* Function 20 */
1995 DWORD
1996 WINAPI
1997 PNP_DeleteClassKey(
1998 handle_t hBinding,
1999 LPWSTR pszClassGuid,
2000 DWORD ulFlags)
2001 {
2002 CONFIGRET ret = CR_SUCCESS;
2003
2004 UNREFERENCED_PARAMETER(hBinding);
2005
2006 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
2007
2008 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
2009 {
2010 if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2011 ret = CR_REGISTRY_ERROR;
2012 }
2013 else
2014 {
2015 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2016 ret = CR_REGISTRY_ERROR;
2017 }
2018
2019 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
2020
2021 return ret;
2022 }
2023
2024
2025 /* Function 21 */
2026 DWORD
2027 WINAPI
2028 PNP_GetInterfaceDeviceAlias(
2029 handle_t hBinding,
2030 LPWSTR pszInterfaceDevice,
2031 GUID *AliasInterfaceGuid,
2032 LPWSTR pszAliasInterfaceDevice,
2033 PNP_RPC_STRING_LEN *pulLength,
2034 PNP_RPC_STRING_LEN *pulTransferLen,
2035 DWORD ulFlags)
2036 {
2037 UNIMPLEMENTED;
2038 return CR_CALL_NOT_IMPLEMENTED;
2039 }
2040
2041
2042 /* Function 22 */
2043 DWORD
2044 WINAPI
2045 PNP_GetInterfaceDeviceList(
2046 handle_t hBinding,
2047 GUID *InterfaceGuid,
2048 LPWSTR pszDeviceID,
2049 BYTE *Buffer,
2050 PNP_RPC_BUFFER_SIZE *pulLength,
2051 DWORD ulFlags)
2052 {
2053 NTSTATUS Status;
2054 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
2055 DWORD ret = CR_SUCCESS;
2056
2057 UNREFERENCED_PARAMETER(hBinding);
2058
2059 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2060 pszDeviceID);
2061
2062 PlugPlayData.Flags = ulFlags;
2063 PlugPlayData.FilterGuid = InterfaceGuid;
2064 PlugPlayData.Buffer = Buffer;
2065 PlugPlayData.BufferSize = *pulLength;
2066
2067 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
2068 (PVOID)&PlugPlayData,
2069 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
2070 if (NT_SUCCESS(Status))
2071 {
2072 *pulLength = PlugPlayData.BufferSize;
2073 }
2074 else
2075 {
2076 ret = NtStatusToCrError(Status);
2077 }
2078
2079 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
2080 return ret;
2081 }
2082
2083
2084 /* Function 23 */
2085 DWORD
2086 WINAPI
2087 PNP_GetInterfaceDeviceListSize(
2088 handle_t hBinding,
2089 PNP_RPC_BUFFER_SIZE *pulLen,
2090 GUID *InterfaceGuid,
2091 LPWSTR pszDeviceID,
2092 DWORD ulFlags)
2093 {
2094 NTSTATUS Status;
2095 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
2096 DWORD ret = CR_SUCCESS;
2097
2098 UNREFERENCED_PARAMETER(hBinding);
2099
2100 DPRINT("PNP_GetInterfaceDeviceListSize() called\n");
2101
2102 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2103 pszDeviceID);
2104
2105 PlugPlayData.FilterGuid = InterfaceGuid;
2106 PlugPlayData.Buffer = NULL;
2107 PlugPlayData.BufferSize = 0;
2108 PlugPlayData.Flags = ulFlags;
2109
2110 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
2111 (PVOID)&PlugPlayData,
2112 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
2113 if (NT_SUCCESS(Status))
2114 {
2115 *pulLen = PlugPlayData.BufferSize;
2116 }
2117 else
2118 {
2119 ret = NtStatusToCrError(Status);
2120 }
2121
2122 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
2123 return ret;
2124 }
2125
2126
2127 /* Function 24 */
2128 DWORD
2129 WINAPI
2130 PNP_RegisterDeviceClassAssociation(
2131 handle_t hBinding,
2132 LPWSTR pszDeviceID,
2133 GUID *InterfaceGuid,
2134 LPWSTR pszReference,
2135 LPWSTR pszSymLink,
2136 PNP_RPC_STRING_LEN *pulLength,
2137 PNP_RPC_STRING_LEN *pulTransferLen,
2138 DWORD ulFlags)
2139 {
2140 UNIMPLEMENTED;
2141 return CR_CALL_NOT_IMPLEMENTED;
2142 }
2143
2144
2145 /* Function 25 */
2146 DWORD
2147 WINAPI
2148 PNP_UnregisterDeviceClassAssociation(
2149 handle_t hBinding,
2150 LPWSTR pszInterfaceDevice,
2151 DWORD ulFlags)
2152 {
2153 UNIMPLEMENTED;
2154 return CR_CALL_NOT_IMPLEMENTED;
2155 }
2156
2157
2158 /* Function 26 */
2159 DWORD
2160 WINAPI
2161 PNP_GetClassRegProp(
2162 handle_t hBinding,
2163 LPWSTR pszClassGuid,
2164 DWORD ulProperty,
2165 DWORD *pulRegDataType,
2166 BYTE *Buffer,
2167 PNP_RPC_STRING_LEN *pulTransferLen,
2168 PNP_RPC_STRING_LEN *pulLength,
2169 DWORD ulFlags)
2170 {
2171 CONFIGRET ret = CR_SUCCESS;
2172 LPWSTR lpValueName = NULL;
2173 HKEY hInstKey = NULL;
2174 HKEY hPropKey = NULL;
2175 LONG lError;
2176
2177 UNREFERENCED_PARAMETER(hBinding);
2178
2179 DPRINT("PNP_GetClassRegProp() called\n");
2180
2181 if (pulTransferLen == NULL || pulLength == NULL)
2182 {
2183 ret = CR_INVALID_POINTER;
2184 goto done;
2185 }
2186
2187 if (ulFlags != 0)
2188 {
2189 ret = CR_INVALID_FLAG;
2190 goto done;
2191 }
2192
2193 if (*pulLength < *pulTransferLen)
2194 *pulLength = *pulTransferLen;
2195
2196 *pulTransferLen = 0;
2197
2198 switch (ulProperty)
2199 {
2200 case CM_CRP_SECURITY:
2201 lpValueName = L"Security";
2202 break;
2203
2204 case CM_CRP_DEVTYPE:
2205 lpValueName = L"DeviceType";
2206 break;
2207
2208 case CM_CRP_EXCLUSIVE:
2209 lpValueName = L"Exclusive";
2210 break;
2211
2212 case CM_CRP_CHARACTERISTICS:
2213 lpValueName = L"DeviceCharacteristics";
2214 break;
2215
2216 default:
2217 ret = CR_INVALID_PROPERTY;
2218 goto done;
2219 }
2220
2221 DPRINT("Value name: %S\n", lpValueName);
2222
2223 lError = RegOpenKeyExW(hClassKey,
2224 pszClassGuid,
2225 0,
2226 KEY_READ,
2227 &hInstKey);
2228 if (lError != ERROR_SUCCESS)
2229 {
2230 *pulLength = 0;
2231 ret = CR_NO_SUCH_REGISTRY_KEY;
2232 goto done;
2233 }
2234
2235 lError = RegOpenKeyExW(hInstKey,
2236 L"Properties",
2237 0,
2238 KEY_READ,
2239 &hPropKey);
2240 if (lError != ERROR_SUCCESS)
2241 {
2242 *pulLength = 0;
2243 ret = CR_NO_SUCH_REGISTRY_KEY;
2244 goto done;
2245 }
2246
2247 lError = RegQueryValueExW(hPropKey,
2248 lpValueName,
2249 NULL,
2250 pulRegDataType,
2251 Buffer,
2252 pulLength);
2253 if (lError != ERROR_SUCCESS)
2254 {
2255 if (lError == ERROR_MORE_DATA)
2256 {
2257 ret = CR_BUFFER_SMALL;
2258 }
2259 else
2260 {
2261 *pulLength = 0;
2262 ret = CR_NO_SUCH_VALUE;
2263 }
2264 }
2265
2266 done:
2267 if (ret == CR_SUCCESS)
2268 *pulTransferLen = *pulLength;
2269
2270 if (hPropKey != NULL)
2271 RegCloseKey(hPropKey);
2272
2273 if (hInstKey != NULL)
2274 RegCloseKey(hInstKey);
2275
2276 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
2277
2278 return ret;
2279 }
2280
2281
2282 /* Function 27 */
2283 DWORD
2284 WINAPI
2285 PNP_SetClassRegProp(
2286 handle_t hBinding,
2287 LPWSTR pszClassGuid,
2288 DWORD ulProperty,
2289 DWORD ulDataType,
2290 BYTE *Buffer,
2291 PNP_PROP_SIZE ulLength,
2292 DWORD ulFlags)
2293 {
2294 CONFIGRET ret = CR_SUCCESS;
2295 LPWSTR lpValueName = NULL;
2296 HKEY hInstKey = 0;
2297 HKEY hPropKey = 0;
2298 LONG lError;
2299
2300 UNREFERENCED_PARAMETER(hBinding);
2301
2302 DPRINT("PNP_SetClassRegProp() called\n");
2303
2304 if (ulFlags != 0)
2305 return CR_INVALID_FLAG;
2306
2307 switch (ulProperty)
2308 {
2309 case CM_CRP_SECURITY:
2310 lpValueName = L"Security";
2311 break;
2312
2313 case CM_CRP_DEVTYPE:
2314 lpValueName = L"DeviceType";
2315 break;
2316
2317 case CM_CRP_EXCLUSIVE:
2318 lpValueName = L"Exclusive";
2319 break;
2320
2321 case CM_CRP_CHARACTERISTICS:
2322 lpValueName = L"DeviceCharacteristics";
2323 break;
2324
2325 default:
2326 return CR_INVALID_PROPERTY;
2327 }
2328
2329 lError = RegOpenKeyExW(hClassKey,
2330 pszClassGuid,
2331 0,
2332 KEY_WRITE,
2333 &hInstKey);
2334 if (lError != ERROR_SUCCESS)
2335 {
2336 ret = CR_NO_SUCH_REGISTRY_KEY;
2337 goto done;
2338 }
2339
2340 /* FIXME: Set security descriptor */
2341 lError = RegCreateKeyExW(hInstKey,
2342 L"Properties",
2343 0,
2344 NULL,
2345 REG_OPTION_NON_VOLATILE,
2346 KEY_ALL_ACCESS,
2347 NULL,
2348 &hPropKey,
2349 NULL);
2350 if (lError != ERROR_SUCCESS)
2351 {
2352 ret = CR_REGISTRY_ERROR;
2353 goto done;
2354 }
2355
2356 if (ulLength == 0)
2357 {
2358 if (RegDeleteValueW(hPropKey,
2359 lpValueName))
2360 ret = CR_REGISTRY_ERROR;
2361 }
2362 else
2363 {
2364 if (RegSetValueExW(hPropKey,
2365 lpValueName,
2366 0,
2367 ulDataType,
2368 Buffer,
2369 ulLength))
2370 ret = CR_REGISTRY_ERROR;
2371 }
2372
2373 done:
2374 if (hPropKey != NULL)
2375 RegCloseKey(hPropKey);
2376
2377 if (hInstKey != NULL)
2378 RegCloseKey(hInstKey);
2379
2380 return ret;
2381 }
2382
2383
2384 static CONFIGRET
2385 CreateDeviceInstance(LPWSTR pszDeviceID)
2386 {
2387 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
2388 WCHAR szDevice[MAX_DEVICE_ID_LEN];
2389 WCHAR szInstance[MAX_DEVICE_ID_LEN];
2390 HKEY hKeyEnumerator;
2391 HKEY hKeyDevice;
2392 HKEY hKeyInstance;
2393 HKEY hKeyControl;
2394 LONG lError;
2395
2396 /* Split the instance ID */
2397 SplitDeviceInstanceID(pszDeviceID,
2398 szEnumerator,
2399 szDevice,
2400 szInstance);
2401
2402 /* Open or create the enumerator key */
2403 lError = RegCreateKeyExW(hEnumKey,
2404 szEnumerator,
2405 0,
2406 NULL,
2407 REG_OPTION_NON_VOLATILE,
2408 KEY_ALL_ACCESS,
2409 NULL,
2410 &hKeyEnumerator,
2411 NULL);
2412 if (lError != ERROR_SUCCESS)
2413 {
2414 return CR_REGISTRY_ERROR;
2415 }
2416
2417 /* Open or create the device key */
2418 lError = RegCreateKeyExW(hKeyEnumerator,
2419 szDevice,
2420 0,
2421 NULL,
2422 REG_OPTION_NON_VOLATILE,
2423 KEY_ALL_ACCESS,
2424 NULL,
2425 &hKeyDevice,
2426 NULL);
2427
2428 /* Close the enumerator key */
2429 RegCloseKey(hKeyEnumerator);
2430
2431 if (lError != ERROR_SUCCESS)
2432 {
2433 return CR_REGISTRY_ERROR;
2434 }
2435
2436 /* Try to open the instance key and fail if it exists */
2437 lError = RegOpenKeyExW(hKeyDevice,
2438 szInstance,
2439 0,
2440 KEY_SET_VALUE,
2441 &hKeyInstance);
2442 if (lError == ERROR_SUCCESS)
2443 {
2444 DPRINT1("Instance %S already exists!\n", szInstance);
2445 RegCloseKey(hKeyInstance);
2446 RegCloseKey(hKeyDevice);
2447 return CR_ALREADY_SUCH_DEVINST;
2448 }
2449
2450 /* Create a new instance key */
2451 lError = RegCreateKeyExW(hKeyDevice,
2452 szInstance,
2453 0,
2454 NULL,
2455 REG_OPTION_NON_VOLATILE,
2456 KEY_ALL_ACCESS,
2457 NULL,
2458 &hKeyInstance,
2459 NULL);
2460
2461 /* Close the device key */
2462 RegCloseKey(hKeyDevice);
2463
2464 if (lError != ERROR_SUCCESS)
2465 {
2466 return CR_REGISTRY_ERROR;
2467 }
2468
2469 /* Create the 'Control' sub key */
2470 lError = RegCreateKeyExW(hKeyInstance,
2471 L"Control",
2472 0,
2473 NULL,
2474 REG_OPTION_NON_VOLATILE,
2475 KEY_ALL_ACCESS,
2476 NULL,
2477 &hKeyControl,
2478 NULL);
2479 if (lError == ERROR_SUCCESS)
2480 {
2481 RegCloseKey(hKeyControl);
2482 }
2483
2484 RegCloseKey(hKeyInstance);
2485
2486 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
2487 }
2488
2489
2490 /* Function 28 */
2491 DWORD
2492 WINAPI
2493 PNP_CreateDevInst(
2494 handle_t hBinding,
2495 LPWSTR pszDeviceID,
2496 LPWSTR pszParentDeviceID,
2497 PNP_RPC_STRING_LEN ulLength,
2498 DWORD ulFlags)
2499 {
2500 CONFIGRET ret = CR_SUCCESS;
2501
2502 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
2503
2504 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
2505 {
2506 WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN];
2507 DWORD dwInstanceNumber;
2508
2509 /* Generated ID is: Root\<Device ID>\<Instance number> */
2510 dwInstanceNumber = 0;
2511 do
2512 {
2513 swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu",
2514 pszDeviceID, dwInstanceNumber);
2515
2516 /* Try to create a device instance with this ID */
2517 ret = CreateDeviceInstance(szGeneratedInstance);
2518
2519 dwInstanceNumber++;
2520 }
2521 while (ret == CR_ALREADY_SUCH_DEVINST);
2522
2523 if (ret == CR_SUCCESS)
2524 {
2525 /* pszDeviceID is an out parameter too for generated IDs */
2526 if (wcslen(szGeneratedInstance) > ulLength)
2527 {
2528 ret = CR_BUFFER_SMALL;
2529 }
2530 else
2531 {
2532 wcscpy(pszDeviceID, szGeneratedInstance);
2533 }
2534 }
2535 }
2536 else
2537 {
2538 /* Create the device instance */
2539 ret = CreateDeviceInstance(pszDeviceID);
2540 }
2541
2542 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
2543
2544 return ret;
2545 }
2546
2547
2548 static CONFIGRET
2549 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
2550 LPWSTR pszDeviceInstanceSource)
2551 {
2552 DPRINT("MoveDeviceInstance: not implemented\n");
2553 /* FIXME */
2554 return CR_CALL_NOT_IMPLEMENTED;
2555 }
2556
2557
2558 static CONFIGRET
2559 SetupDeviceInstance(LPWSTR pszDeviceInstance,
2560 DWORD ulFlags)
2561 {
2562 DPRINT("SetupDeviceInstance: not implemented\n");
2563 /* FIXME */
2564 return CR_CALL_NOT_IMPLEMENTED;
2565 }
2566
2567
2568 static CONFIGRET
2569 EnableDeviceInstance(LPWSTR pszDeviceInstance)
2570 {
2571 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
2572 CONFIGRET ret = CR_SUCCESS;
2573 NTSTATUS Status;
2574
2575 DPRINT("Enable device instance %S\n", pszDeviceInstance);
2576
2577 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
2578 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
2579 if (!NT_SUCCESS(Status))
2580 ret = NtStatusToCrError(Status);
2581
2582 return ret;
2583 }
2584
2585
2586 static CONFIGRET
2587 DisableDeviceInstance(LPWSTR pszDeviceInstance)
2588 {
2589 DPRINT("DisableDeviceInstance: not implemented\n");
2590 /* FIXME */
2591 return CR_CALL_NOT_IMPLEMENTED;
2592 }
2593
2594
2595 static CONFIGRET
2596 ReenumerateDeviceInstance(
2597 _In_ LPWSTR pszDeviceInstance,
2598 _In_ ULONG ulFlags)
2599 {
2600 PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
2601 CONFIGRET ret = CR_SUCCESS;
2602 NTSTATUS Status;
2603
2604 DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
2605 pszDeviceInstance, ulFlags);
2606
2607 if (ulFlags & ~CM_REENUMERATE_BITS)
2608 return CR_INVALID_FLAG;
2609
2610 if (ulFlags & CM_REENUMERATE_RETRY_INSTALLATION)
2611 {
2612 DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
2613 }
2614
2615 RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance,
2616 pszDeviceInstance);
2617 EnumerateDeviceData.Flags = 0;
2618
2619 Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice,
2620 &EnumerateDeviceData,
2621 sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA));
2622 if (!NT_SUCCESS(Status))
2623 ret = NtStatusToCrError(Status);
2624
2625 return ret;
2626 }
2627
2628
2629 /* Function 29 */
2630 DWORD
2631 WINAPI
2632 PNP_DeviceInstanceAction(
2633 handle_t hBinding,
2634 DWORD ulAction,
2635 DWORD ulFlags,
2636 LPWSTR pszDeviceInstance1,
2637 LPWSTR pszDeviceInstance2)
2638 {
2639 CONFIGRET ret = CR_SUCCESS;
2640
2641 UNREFERENCED_PARAMETER(hBinding);
2642
2643 DPRINT("PNP_DeviceInstanceAction() called\n");
2644
2645 switch (ulAction)
2646 {
2647 case PNP_DEVINST_MOVE:
2648 ret = MoveDeviceInstance(pszDeviceInstance1,
2649 pszDeviceInstance2);
2650 break;
2651
2652 case PNP_DEVINST_SETUP:
2653 ret = SetupDeviceInstance(pszDeviceInstance1,
2654 ulFlags);
2655 break;
2656
2657 case PNP_DEVINST_ENABLE:
2658 ret = EnableDeviceInstance(pszDeviceInstance1);
2659 break;
2660
2661 case PNP_DEVINST_DISABLE:
2662 ret = DisableDeviceInstance(pszDeviceInstance1);
2663 break;
2664
2665 case PNP_DEVINST_REENUMERATE:
2666 ret = ReenumerateDeviceInstance(pszDeviceInstance1,
2667 ulFlags);
2668 break;
2669
2670 default:
2671 DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
2672 ret = CR_CALL_NOT_IMPLEMENTED;
2673 }
2674
2675 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
2676
2677 return ret;
2678 }
2679
2680
2681 /* Function 30 */
2682 DWORD
2683 WINAPI
2684 PNP_GetDeviceStatus(
2685 handle_t hBinding,
2686 LPWSTR pDeviceID,
2687 DWORD *pulStatus,
2688 DWORD *pulProblem,
2689 DWORD ulFlags)
2690 {
2691 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
2692 CONFIGRET ret = CR_SUCCESS;
2693 NTSTATUS Status;
2694
2695 UNREFERENCED_PARAMETER(hBinding);
2696 UNREFERENCED_PARAMETER(ulFlags);
2697
2698 DPRINT("PNP_GetDeviceStatus() called\n");
2699
2700 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2701 pDeviceID);
2702 PlugPlayData.Operation = 0; /* Get status */
2703
2704 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
2705 (PVOID)&PlugPlayData,
2706 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
2707 if (NT_SUCCESS(Status))
2708 {
2709 *pulStatus = PlugPlayData.DeviceStatus;
2710 *pulProblem = PlugPlayData.DeviceProblem;
2711 }
2712 else
2713 {
2714 ret = NtStatusToCrError(Status);
2715 }
2716
2717 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
2718
2719 return ret;
2720 }
2721
2722
2723 /* Function 31 */
2724 DWORD
2725 WINAPI
2726 PNP_SetDeviceProblem(
2727 handle_t hBinding,
2728 LPWSTR pDeviceID,
2729 DWORD ulProblem,
2730 DWORD ulFlags)
2731 {
2732 UNIMPLEMENTED;
2733 return CR_CALL_NOT_IMPLEMENTED;
2734 }
2735
2736
2737 /* Function 32 */
2738 DWORD
2739 WINAPI
2740 PNP_DisableDevInst(
2741 handle_t hBinding,
2742 LPWSTR pDeviceID,
2743 PPNP_VETO_TYPE pVetoType,
2744 LPWSTR pszVetoName,
2745 DWORD ulNameLength,
2746 DWORD ulFlags)
2747 {
2748 UNIMPLEMENTED;
2749 return CR_CALL_NOT_IMPLEMENTED;
2750 }
2751
2752 /* Function 33 */
2753 DWORD
2754 WINAPI
2755 PNP_UninstallDevInst(
2756 handle_t hBinding,
2757 LPWSTR pDeviceID,
2758 DWORD ulFlags)
2759 {
2760 UNIMPLEMENTED;
2761 return CR_CALL_NOT_IMPLEMENTED;
2762 }
2763
2764
2765 static BOOL
2766 CheckForDeviceId(LPWSTR lpDeviceIdList,
2767 LPWSTR lpDeviceId)
2768 {
2769 LPWSTR lpPtr;
2770 DWORD dwLength;
2771
2772 lpPtr = lpDeviceIdList;
2773 while (*lpPtr != 0)
2774 {
2775 dwLength = wcslen(lpPtr);
2776 if (0 == _wcsicmp(lpPtr, lpDeviceId))
2777 return TRUE;
2778
2779 lpPtr += (dwLength + 1);
2780 }
2781
2782 return FALSE;
2783 }
2784
2785
2786 static VOID
2787 AppendDeviceId(LPWSTR lpDeviceIdList,
2788 LPDWORD lpDeviceIdListSize,
2789 LPWSTR lpDeviceId)
2790 {
2791 DWORD dwLen;
2792 DWORD dwPos;
2793
2794 dwLen = wcslen(lpDeviceId);
2795 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
2796
2797 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
2798
2799 dwPos += (dwLen + 1);
2800
2801 lpDeviceIdList[dwPos] = 0;
2802
2803 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
2804 }
2805
2806
2807 /* Function 34 */
2808 DWORD
2809 WINAPI
2810 PNP_AddID(
2811 handle_t hBinding,
2812 LPWSTR pszDeviceID,
2813 LPWSTR pszID,
2814 DWORD ulFlags)
2815 {
2816 CONFIGRET ret = CR_SUCCESS;
2817 HKEY hDeviceKey;
2818 LPWSTR pszSubKey;
2819 DWORD dwDeviceIdListSize;
2820 DWORD dwNewDeviceIdSize;
2821 WCHAR * pszDeviceIdList = NULL;
2822
2823 UNREFERENCED_PARAMETER(hBinding);
2824
2825 DPRINT("PNP_AddID() called\n");
2826 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
2827 DPRINT(" DeviceId: %S\n", pszID);
2828 DPRINT(" Flags: %lx\n", ulFlags);
2829
2830 if (RegOpenKeyExW(hEnumKey,
2831 pszDeviceID,
2832 0,
2833 KEY_QUERY_VALUE | KEY_SET_VALUE,
2834 &hDeviceKey) != ERROR_SUCCESS)
2835 {
2836 DPRINT("Failed to open the device key!\n");
2837 return CR_INVALID_DEVNODE;
2838 }
2839
2840 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
2841
2842 if (RegQueryValueExW(hDeviceKey,
2843 pszSubKey,
2844 NULL,
2845 NULL,
2846 NULL,
2847 &dwDeviceIdListSize) != ERROR_SUCCESS)
2848 {
2849 DPRINT("Failed to query the desired ID string!\n");
2850 ret = CR_REGISTRY_ERROR;
2851 goto Done;
2852 }
2853
2854 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
2855 if (!dwNewDeviceIdSize)
2856 {
2857 ret = CR_INVALID_POINTER;
2858 goto Done;
2859 }
2860
2861 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
2862
2863 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
2864 if (!pszDeviceIdList)
2865 {
2866 DPRINT("Failed to allocate memory for the desired ID string!\n");
2867 ret = CR_OUT_OF_MEMORY;
2868 goto Done;
2869 }
2870
2871 if (RegQueryValueExW(hDeviceKey,
2872 pszSubKey,
2873 NULL,
2874 NULL,
2875 (LPBYTE)pszDeviceIdList,
2876 &dwDeviceIdListSize) != ERROR_SUCCESS)
2877 {
2878 DPRINT("Failed to query the desired ID string!\n");
2879 ret = CR_REGISTRY_ERROR;
2880 goto Done;
2881 }
2882
2883 /* Check whether the device ID is already in use */
2884 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
2885 {
2886 DPRINT("Device ID was found in the ID string!\n");
2887 ret = CR_SUCCESS;
2888 goto Done;
2889 }
2890
2891 /* Append the Device ID */
2892 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
2893
2894 if (RegSetValueExW(hDeviceKey,
2895 pszSubKey,
2896 0,
2897 REG_MULTI_SZ,
2898 (LPBYTE)pszDeviceIdList,
2899 dwDeviceIdListSize) != ERROR_SUCCESS)
2900 {
2901 DPRINT("Failed to set the desired ID string!\n");
2902 ret = CR_REGISTRY_ERROR;
2903 }
2904
2905 Done:
2906 RegCloseKey(hDeviceKey);
2907 if (pszDeviceIdList)
2908 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
2909
2910 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
2911
2912 return ret;
2913 }
2914
2915
2916 /* Function 35 */
2917 DWORD
2918 WINAPI
2919 PNP_RegisterDriver(
2920 handle_t hBinding,
2921 LPWSTR pszDeviceID,
2922 DWORD ulFlags)
2923 {
2924 UNIMPLEMENTED;
2925 return CR_CALL_NOT_IMPLEMENTED;
2926 }
2927
2928
2929 /* Function 36 */
2930 DWORD
2931 WINAPI
2932 PNP_QueryRemove(
2933 handle_t hBinding,
2934 LPWSTR pszDeviceID,
2935 PPNP_VETO_TYPE pVetoType,
2936 LPWSTR pszVetoName,
2937 DWORD ulNameLength,
2938 DWORD ulFlags)
2939 {
2940 UNIMPLEMENTED;
2941 return CR_CALL_NOT_IMPLEMENTED;
2942 }
2943
2944
2945 /* Function 37 */
2946 DWORD
2947 WINAPI
2948 PNP_RequestDeviceEject(
2949 handle_t hBinding,
2950 LPWSTR pszDeviceID,
2951 PPNP_VETO_TYPE pVetoType,
2952 LPWSTR pszVetoName,
2953 DWORD ulNameLength,
2954 DWORD ulFlags)
2955 {
2956 UNIMPLEMENTED;
2957 return CR_CALL_NOT_IMPLEMENTED;
2958 }
2959
2960
2961 /* Function 38 */
2962 CONFIGRET
2963 WINAPI
2964 PNP_IsDockStationPresent(
2965 handle_t hBinding,
2966 BOOL *Present)
2967 {
2968 HKEY hKey;
2969 DWORD dwType;
2970 DWORD dwValue;
2971 DWORD dwSize;
2972 CONFIGRET ret = CR_SUCCESS;
2973
2974 UNREFERENCED_PARAMETER(hBinding);
2975
2976 DPRINT1("PNP_IsDockStationPresent() called\n");
2977
2978 *Present = FALSE;
2979
2980 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
2981 L"CurrentDockInfo",
2982 0,
2983 KEY_READ,
2984 &hKey) != ERROR_SUCCESS)
2985 return CR_REGISTRY_ERROR;
2986
2987 dwSize = sizeof(DWORD);
2988 if (RegQueryValueExW(hKey,
2989 L"DockingState",
2990 NULL,
2991 &dwType,
2992 (LPBYTE)&dwValue,
2993 &dwSize) != ERROR_SUCCESS)
2994 ret = CR_REGISTRY_ERROR;
2995
2996 RegCloseKey(hKey);
2997
2998 if (ret == CR_SUCCESS)
2999 {
3000 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
3001 {
3002 ret = CR_REGISTRY_ERROR;
3003 }
3004 else if (dwValue != 0)
3005 {
3006 *Present = TRUE;
3007 }
3008 }
3009
3010 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
3011
3012 return ret;
3013 }
3014
3015
3016 /* Function 39 */
3017 DWORD
3018 WINAPI
3019 PNP_RequestEjectPC(
3020 handle_t hBinding)
3021 {
3022 UNIMPLEMENTED;
3023 return CR_CALL_NOT_IMPLEMENTED;
3024 }
3025
3026
3027 /* Function 40 */
3028 DWORD
3029 WINAPI
3030 PNP_HwProfFlags(
3031 handle_t hBinding,
3032 DWORD ulAction,
3033 LPWSTR pDeviceID,
3034 DWORD ulConfig,
3035 DWORD *pulValue,
3036 PPNP_VETO_TYPE pVetoType,
3037 LPWSTR pszVetoName,
3038 DWORD ulNameLength,
3039 DWORD ulFlags)
3040 {
3041 CONFIGRET ret = CR_SUCCESS;
3042 WCHAR szKeyName[MAX_PATH];
3043 HKEY hKey;
3044 HKEY hDeviceKey;
3045 DWORD dwSize;
3046
3047 UNREFERENCED_PARAMETER(hBinding);
3048
3049 DPRINT("PNP_HwProfFlags() called\n");
3050
3051 if (ulConfig == 0)
3052 {
3053 wcscpy(szKeyName,
3054 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
3055 }
3056 else
3057 {
3058 swprintf(szKeyName,
3059 L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum",
3060 ulConfig);
3061 }
3062
3063 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3064 szKeyName,
3065 0,
3066 KEY_QUERY_VALUE,
3067 &hKey) != ERROR_SUCCESS)
3068 return CR_REGISTRY_ERROR;
3069
3070 if (ulAction == PNP_GET_HWPROFFLAGS)
3071 {
3072 if (RegOpenKeyExW(hKey,
3073 pDeviceID,
3074 0,
3075 KEY_QUERY_VALUE,
3076 &hDeviceKey) != ERROR_SUCCESS)
3077 {
3078 *pulValue = 0;
3079 }
3080 else
3081 {
3082 dwSize = sizeof(DWORD);
3083 if (RegQueryValueExW(hDeviceKey,
3084 L"CSConfigFlags",
3085 NULL,
3086 NULL,
3087 (LPBYTE)pulValue,
3088 &dwSize) != ERROR_SUCCESS)
3089 {
3090 *pulValue = 0;
3091 }
3092
3093 RegCloseKey(hDeviceKey);
3094 }
3095 }
3096 else if (ulAction == PNP_SET_HWPROFFLAGS)
3097 {
3098 /* FIXME: not implemented yet */
3099 ret = CR_CALL_NOT_IMPLEMENTED;
3100 }
3101
3102 RegCloseKey(hKey);
3103
3104 return ret;
3105 }
3106
3107
3108 /* Function 41 */
3109 DWORD
3110 WINAPI
3111 PNP_GetHwProfInfo(
3112 handle_t hBinding,
3113 DWORD ulIndex,
3114 HWPROFILEINFO *pHWProfileInfo,
3115 DWORD ulProfileInfoSize,
3116 DWORD ulFlags)
3117 {
3118 WCHAR szProfileName[5];
3119 HKEY hKeyConfig = NULL;
3120 HKEY hKeyProfiles = NULL;
3121 HKEY hKeyProfile = NULL;
3122 DWORD dwDisposition;
3123 DWORD dwSize;
3124 LONG lError;
3125 CONFIGRET ret = CR_SUCCESS;
3126
3127 UNREFERENCED_PARAMETER(hBinding);
3128
3129 DPRINT("PNP_GetHwProfInfo() called\n");
3130
3131 if (ulProfileInfoSize == 0)
3132 {
3133 ret = CR_INVALID_DATA;
3134 goto done;
3135 }
3136
3137 if (ulFlags != 0)
3138 {
3139 ret = CR_INVALID_FLAG;
3140 goto done;
3141 }
3142
3143 /* Initialize the profile information */
3144 pHWProfileInfo->HWPI_ulHWProfile = 0;
3145 pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
3146 pHWProfileInfo->HWPI_dwFlags = 0;
3147
3148 /* Open the 'IDConfigDB' key */
3149 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3150 L"System\\CurrentControlSet\\Control\\IDConfigDB",
3151 0,
3152 NULL,
3153 REG_OPTION_NON_VOLATILE,
3154 KEY_QUERY_VALUE,
3155 NULL,
3156 &hKeyConfig,
3157 &dwDisposition);
3158 if (lError != ERROR_SUCCESS)
3159 {
3160 ret = CR_REGISTRY_ERROR;
3161 goto done;
3162 }
3163
3164 /* Open the 'Hardware Profiles' subkey */
3165 lError = RegCreateKeyExW(hKeyConfig,
3166 L"Hardware Profiles",
3167 0,
3168 NULL,
3169 REG_OPTION_NON_VOLATILE,
3170 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
3171 NULL,
3172 &hKeyProfiles,
3173 &dwDisposition);
3174 if (lError != ERROR_SUCCESS)
3175 {
3176 ret = CR_REGISTRY_ERROR;
3177 goto done;
3178 }
3179
3180 if (ulIndex == (ULONG)-1)
3181 {
3182 dwSize = sizeof(ULONG);
3183 lError = RegQueryValueExW(hKeyConfig,
3184 L"CurrentConfig",
3185 NULL,
3186 NULL,
3187 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
3188 &dwSize);
3189 if (lError != ERROR_SUCCESS)
3190 {
3191 pHWProfileInfo->HWPI_ulHWProfile = 0;
3192 ret = CR_REGISTRY_ERROR;
3193 goto done;
3194 }
3195 }
3196 else
3197 {
3198 /* FIXME: not implemented yet */
3199 ret = CR_CALL_NOT_IMPLEMENTED;
3200 goto done;
3201 }
3202
3203 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
3204
3205 lError = RegOpenKeyExW(hKeyProfiles,
3206 szProfileName,
3207 0,
3208 KEY_QUERY_VALUE,
3209 &hKeyProfile);
3210 if (lError != ERROR_SUCCESS)
3211 {
3212 ret = CR_REGISTRY_ERROR;
3213 goto done;
3214 }
3215
3216 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
3217 lError = RegQueryValueExW(hKeyProfile,
3218 L"FriendlyName",
3219 NULL,
3220 NULL,
3221 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
3222 &dwSize);
3223 if (lError != ERROR_SUCCESS)
3224 {
3225 ret = CR_REGISTRY_ERROR;
3226 goto done;
3227 }
3228
3229 done:
3230 if (hKeyProfile != NULL)
3231 RegCloseKey(hKeyProfile);
3232
3233 if (hKeyProfiles != NULL)
3234 RegCloseKey(hKeyProfiles);
3235
3236 if (hKeyConfig != NULL)
3237 RegCloseKey(hKeyConfig);
3238
3239 return ret;
3240 }
3241
3242
3243 /* Function 42 */
3244 DWORD
3245 WINAPI
3246 PNP_AddEmptyLogConf(
3247 handle_t hBinding,
3248 LPWSTR pDeviceID,
3249 DWORD ulPriority,
3250 DWORD *pulLogConfTag,
3251 DWORD ulFlags)
3252 {
3253 UNIMPLEMENTED;
3254 return CR_CALL_NOT_IMPLEMENTED;
3255 }
3256
3257
3258 /* Function 43 */
3259 DWORD
3260 WINAPI
3261 PNP_FreeLogConf(
3262 handle_t hBinding,
3263 LPWSTR pDeviceID,
3264 DWORD ulLogConfType,
3265 DWORD ulLogConfTag,
3266 DWORD ulFlags)
3267 {
3268 UNIMPLEMENTED;
3269 return CR_CALL_NOT_IMPLEMENTED;
3270 }
3271
3272
3273 /* Function 44 */
3274 DWORD
3275 WINAPI
3276 PNP_GetFirstLogConf(
3277 handle_t hBinding,
3278 LPWSTR pDeviceID,
3279 DWORD ulLogConfType,
3280 DWORD *pulLogConfTag,
3281 DWORD ulFlags)
3282 {
3283 UNIMPLEMENTED;
3284 return CR_CALL_NOT_IMPLEMENTED;
3285 }
3286
3287
3288 /* Function 45 */
3289 DWORD
3290 WINAPI
3291 PNP_GetNextLogConf(
3292 handle_t hBinding,
3293 LPWSTR pDeviceID,
3294 DWORD ulLogConfType,
3295 DWORD ulCurrentTag,
3296 DWORD *pulNextTag,
3297 DWORD ulFlags)
3298 {
3299 UNIMPLEMENTED;
3300 return CR_CALL_NOT_IMPLEMENTED;
3301 }
3302
3303
3304 /* Function 46 */
3305 DWORD
3306 WINAPI
3307 PNP_GetLogConfPriority(
3308 handle_t hBinding,
3309 LPWSTR pDeviceID,
3310 DWORD ulType,
3311 DWORD ulTag,
3312 DWORD *pPriority,
3313 DWORD ulFlags)
3314 {
3315 UNIMPLEMENTED;
3316 return CR_CALL_NOT_IMPLEMENTED;
3317 }
3318
3319
3320 /* Function 47 */
3321 DWORD
3322 WINAPI
3323 PNP_AddResDes(
3324 handle_t hBinding,
3325 LPWSTR pDeviceID,
3326 DWORD ulLogConfTag,
3327 DWORD ulLogConfType,
3328 RESOURCEID ResourceID,
3329 DWORD *pulResourceTag,
3330 BYTE *ResourceData,
3331 PNP_RPC_BUFFER_SIZE ResourceLen,
3332 DWORD ulFlags)
3333 {
3334 UNIMPLEMENTED;
3335 return CR_CALL_NOT_IMPLEMENTED;
3336 }
3337
3338
3339 /* Function 48 */
3340 DWORD
3341 WINAPI
3342 PNP_FreeResDes(
3343 handle_t hBinding,
3344 LPWSTR pDeviceID,
3345 DWORD ulLogConfTag,
3346 DWORD ulLogConfType,
3347 RESOURCEID ResourceID,
3348 DWORD ulResourceTag,
3349 DWORD *pulPreviousResType,
3350 DWORD *pulPreviousResTag,
3351 DWORD ulFlags)
3352 {
3353 UNIMPLEMENTED;
3354 return CR_CALL_NOT_IMPLEMENTED;
3355 }
3356
3357
3358 /* Function 49 */
3359 DWORD
3360 WINAPI
3361 PNP_GetNextResDes(
3362 handle_t hBinding,
3363 LPWSTR pDeviceID,
3364 DWORD ulLogConfTag,
3365 DWORD ulLogConfType,
3366 RESOURCEID ResourceID,
3367 DWORD ulResourceTag,
3368 DWORD *pulNextResType,
3369 DWORD *pulNextResTag,
3370 DWORD ulFlags)
3371 {
3372 UNIMPLEMENTED;
3373 return CR_CALL_NOT_IMPLEMENTED;
3374 }
3375
3376
3377 /* Function 50 */
3378 DWORD
3379 WINAPI
3380 PNP_GetResDesData(
3381 handle_t hBinding,
3382 LPWSTR pDeviceID,
3383 DWORD ulLogConfTag,
3384 DWORD ulLogConfType,
3385 RESOURCEID ResourceID,
3386 DWORD ulResourceTag,
3387 BYTE *Buffer,
3388 PNP_RPC_BUFFER_SIZE BufferLen,
3389 DWORD ulFlags)
3390 {
3391 UNIMPLEMENTED;
3392 return CR_CALL_NOT_IMPLEMENTED;
3393 }
3394
3395
3396 /* Function 51 */
3397 DWORD
3398 WINAPI
3399 PNP_GetResDesDataSize(
3400 handle_t hBinding,
3401 LPWSTR pDeviceID,
3402 DWORD ulLogConfTag,
3403 DWORD ulLogConfType,
3404 RESOURCEID ResourceID,
3405 DWORD ulResourceTag,
3406 DWORD *pulSize,
3407 DWORD ulFlags)
3408 {
3409 UNIMPLEMENTED;
3410 return CR_CALL_NOT_IMPLEMENTED;
3411 }
3412
3413
3414 /* Function 52 */
3415 DWORD
3416 WINAPI
3417 PNP_ModifyResDes(
3418 handle_t hBinding,
3419 LPWSTR pDeviceID,
3420 DWORD ulLogConfTag,
3421 DWORD ulLogConfType,
3422 RESOURCEID CurrentResourceID,
3423 RESOURCEID NewResourceID,
3424 DWORD ulResourceTag,
3425 BYTE *ResourceData,
3426 PNP_RPC_BUFFER_SIZE ResourceLen,
3427 DWORD ulFlags)
3428 {
3429 UNIMPLEMENTED;
3430 return CR_CALL_NOT_IMPLEMENTED;
3431 }
3432
3433
3434 /* Function 53 */
3435 DWORD
3436 WINAPI
3437 PNP_DetectResourceConflict(
3438 handle_t hBinding,
3439 LPWSTR pDeviceID,
3440 RESOURCEID ResourceID,
3441 BYTE *ResourceData,
3442 PNP_RPC_BUFFER_SIZE ResourceLen,
3443 BOOL *pbConflictDetected,
3444 DWORD ulFlags)
3445 {
3446 DPRINT("PNP_DetectResourceConflict()\n");
3447
3448 if (pbConflictDetected != NULL)
3449 *pbConflictDetected = FALSE;
3450
3451 return CR_CALL_NOT_IMPLEMENTED;
3452 }
3453
3454
3455 /* Function 54 */
3456 DWORD
3457 WINAPI
3458 PNP_QueryResConfList(
3459 handle_t hBinding,
3460 LPWSTR pDeviceID,
3461 RESOURCEID ResourceID,
3462 BYTE *ResourceData,
3463 PNP_RPC_BUFFER_SIZE ResourceLen,
3464 BYTE *Buffer,
3465 PNP_RPC_BUFFER_SIZE BufferLen,
3466 DWORD ulFlags)
3467 {
3468 UNIMPLEMENTED;
3469 return CR_CALL_NOT_IMPLEMENTED;
3470 }
3471
3472
3473 /* Function 55 */
3474 DWORD
3475 WINAPI
3476 PNP_SetHwProf(
3477 handle_t hBinding,
3478 DWORD ulHardwareProfile,
3479 DWORD ulFlags)
3480 {
3481 return CR_CALL_NOT_IMPLEMENTED;
3482 }
3483
3484
3485 /* Function 56 */
3486 DWORD
3487 WINAPI
3488 PNP_QueryArbitratorFreeData(
3489 handle_t hBinding,
3490 BYTE *pData,
3491 DWORD DataLen,
3492 LPWSTR pDeviceID,
3493 RESOURCEID ResourceID,
3494 DWORD ulFlags)
3495 {
3496 return CR_CALL_NOT_IMPLEMENTED;
3497 }
3498
3499
3500 /* Function 57 */
3501 DWORD
3502 WINAPI
3503 PNP_QueryArbitratorFreeSize(
3504 handle_t hBinding,
3505 DWORD *pulSize,
3506 LPWSTR pDeviceID,
3507 RESOURCEID ResourceID,
3508 DWORD ulFlags)
3509 {
3510 if (pulSize != NULL)
3511 *pulSize = 0;
3512
3513 return CR_CALL_NOT_IMPLEMENTED;
3514 }
3515
3516
3517 /* Function 58 */
3518 CONFIGRET
3519 WINAPI
3520 PNP_RunDetection(
3521 handle_t hBinding,
3522 DWORD ulFlags)
3523 {
3524 return CR_CALL_NOT_IMPLEMENTED;
3525 }
3526
3527
3528 /* Function 59 */
3529 DWORD
3530 WINAPI
3531 PNP_RegisterNotification(
3532 handle_t hBinding,
3533 BYTE *pNotificationFilter,
3534 DWORD ulNotificationFilterSize,
3535 DWORD ulFlags,
3536 DWORD *pulNotify)
3537 {
3538 #if 0
3539 PNOTIFY_DATA pNotifyData;
3540 #endif
3541
3542 DPRINT1("PNP_RegisterNotification(%p %p %lu 0x%lx %p)\n",
3543 hBinding, pNotificationFilter, ulNotificationFilterSize, ulFlags, pulNotify);
3544
3545 #if 0
3546 pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA));
3547 if (pNotifyData == NULL)
3548 return CR_OUT_OF_MEMORY;
3549
3550 *pulNotify = (DWORD)pNotifyData;
3551 #endif
3552
3553 *pulNotify = 1;
3554
3555 return CR_SUCCESS;
3556 }
3557
3558
3559 /* Function 60 */
3560 DWORD
3561 WINAPI
3562 PNP_UnregisterNotification(
3563 handle_t hBinding,
3564 DWORD ulNotify)
3565 {
3566 DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n",
3567 hBinding, ulNotify);
3568
3569 #if 0
3570 UNIMPLEMENTED;
3571 return CR_CALL_NOT_IMPLEMENTED;
3572 #endif
3573
3574 return CR_SUCCESS;
3575 }
3576
3577
3578 /* Function 61 */
3579 DWORD
3580 WINAPI
3581 PNP_GetCustomDevProp(
3582 handle_t hBinding,
3583 LPWSTR pDeviceID,
3584 LPWSTR CustomPropName,
3585 DWORD *pulRegDataType,
3586 BYTE *Buffer,
3587 PNP_RPC_STRING_LEN *pulTransferLen,
3588 PNP_RPC_STRING_LEN *pulLength,
3589 DWORD ulFlags)
3590 {
3591 HKEY hDeviceKey = NULL;
3592 HKEY hParamKey = NULL;
3593 LONG lError;
3594 CONFIGRET ret = CR_SUCCESS;
3595
3596 UNREFERENCED_PARAMETER(hBinding);
3597
3598 DPRINT("PNP_GetCustomDevProp() called\n");
3599
3600 if (pulTransferLen == NULL || pulLength == NULL)
3601 {
3602 ret = CR_INVALID_POINTER;
3603 goto done;
3604 }
3605
3606 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
3607 {
3608 ret = CR_INVALID_FLAG;
3609 goto done;
3610 }
3611
3612 if (*pulLength < *pulTransferLen)
3613 *pulLength = *pulTransferLen;
3614
3615 *pulTransferLen = 0;
3616
3617 lError = RegOpenKeyExW(hEnumKey,
3618 pDeviceID,
3619 0,
3620 KEY_READ,
3621 &hDeviceKey);
3622 if (lError != ERROR_SUCCESS)
3623 {
3624 ret = CR_REGISTRY_ERROR;
3625 goto done;
3626 }
3627
3628 lError = RegOpenKeyExW(hDeviceKey,
3629 L"Device Parameters",
3630 0,
3631 KEY_READ,
3632 &hParamKey);
3633 if (lError != ERROR_SUCCESS)
3634 {
3635 ret = CR_REGISTRY_ERROR;
3636 goto done;
3637 }
3638
3639 lError = RegQueryValueExW(hParamKey,
3640 CustomPropName,
3641 NULL,
3642 pulRegDataType,
3643 Buffer,
3644 pulLength);
3645 if (lError != ERROR_SUCCESS)
3646 {
3647 if (lError == ERROR_MORE_DATA)
3648 {
3649 ret = CR_BUFFER_SMALL;
3650 }
3651 else
3652 {
3653 *pulLength = 0;
3654 ret = CR_NO_SUCH_VALUE;
3655 }
3656 }
3657
3658 done:
3659 if (ret == CR_SUCCESS)
3660 *pulTransferLen = *pulLength;
3661
3662 if (hParamKey != NULL)
3663 RegCloseKey(hParamKey);
3664
3665 if (hDeviceKey != NULL)
3666 RegCloseKey(hDeviceKey);
3667
3668 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
3669
3670 return ret;
3671 }
3672
3673
3674 /* Function 62 */
3675 DWORD
3676 WINAPI
3677 PNP_GetVersionInternal(
3678 handle_t hBinding,
3679 WORD *pwVersion)
3680 {
3681 UNREFERENCED_PARAMETER(hBinding);
3682
3683 *pwVersion = 0x501;
3684 return CR_SUCCESS;
3685 }
3686
3687
3688 /* Function 63 */
3689 DWORD
3690 WINAPI
3691 PNP_GetBlockedDriverInfo(
3692 handle_t hBinding,
3693 BYTE *Buffer,
3694 PNP_RPC_BUFFER_SIZE *pulTransferLen,
3695 PNP_RPC_BUFFER_SIZE *pulLength,
3696 DWORD ulFlags)
3697 {
3698 UNIMPLEMENTED;
3699 return CR_CALL_NOT_IMPLEMENTED;
3700 }
3701
3702
3703 /* Function 64 */
3704 DWORD
3705 WINAPI
3706 PNP_GetServerSideDeviceInstallFlags(
3707 handle_t hBinding,
3708 DWORD *pulSSDIFlags,
3709 DWORD ulFlags)
3710 {
3711 UNREFERENCED_PARAMETER(hBinding);
3712
3713 DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n",
3714 hBinding, pulSSDIFlags, ulFlags);
3715
3716 if (pulSSDIFlags == NULL)
3717 return CR_INVALID_POINTER;
3718
3719 if (ulFlags != 0)
3720 return CR_INVALID_FLAG;
3721
3722 /* FIXME */
3723 *pulSSDIFlags = 0;
3724
3725 return CR_SUCCESS;
3726 }
3727
3728
3729 /* Function 65 */
3730 DWORD
3731 WINAPI
3732 PNP_GetObjectPropKeys(
3733 handle_t hBinding,
3734 LPWSTR ObjectName,
3735 DWORD ObjectType,
3736 LPWSTR PropertyCultureName,
3737 PNP_PROP_COUNT *PropertyCount,
3738 PNP_PROP_COUNT *TransferLen,
3739 DEVPROPKEY *PropertyKeys,
3740 DWORD Flags)
3741 {
3742 UNIMPLEMENTED;
3743 return CR_CALL_NOT_IMPLEMENTED;
3744 }
3745
3746
3747 /* Function 66 */
3748 DWORD
3749 WINAPI
3750 PNP_GetObjectProp(
3751 handle_t hBinding,
3752 LPWSTR ObjectName,
3753 DWORD ObjectType,
3754 LPWSTR PropertyCultureName,
3755 const DEVPROPKEY *PropertyKey,
3756 DEVPROPTYPE *PropertyType,
3757 PNP_PROP_SIZE *PropertySize,
3758 PNP_PROP_SIZE *TransferLen,
3759 BYTE *PropertyBuffer,
3760 DWORD Flags)
3761 {
3762 UNIMPLEMENTED;
3763 return CR_CALL_NOT_IMPLEMENTED;
3764 }
3765
3766
3767 /* Function 67 */
3768 DWORD
3769 WINAPI
3770 PNP_SetObjectProp(
3771 handle_t hBinding,
3772 LPWSTR ObjectName,
3773 DWORD ObjectType,
3774 LPWSTR PropertyCultureName,
3775 const DEVPROPKEY *PropertyKey,
3776 DEVPROPTYPE PropertyType,
3777 PNP_PROP_SIZE PropertySize,
3778 BYTE *PropertyBuffer,
3779 DWORD Flags)
3780 {
3781 UNIMPLEMENTED;
3782 return CR_CALL_NOT_IMPLEMENTED;
3783 }
3784
3785
3786 /* Function 68 */
3787 DWORD
3788 WINAPI
3789 PNP_InstallDevInst(
3790 handle_t hBinding)
3791 {
3792 UNIMPLEMENTED;
3793 return CR_CALL_NOT_IMPLEMENTED;
3794 }
3795
3796
3797 /* Function 69 */
3798 DWORD
3799 WINAPI
3800 PNP_ApplyPowerSettings(
3801 handle_t hBinding)
3802 {
3803 UNIMPLEMENTED;
3804 return CR_CALL_NOT_IMPLEMENTED;
3805 }
3806
3807
3808 /* Function 70 */
3809 DWORD
3810 WINAPI
3811 PNP_DriverStoreAddDriverPackage(
3812 handle_t hBinding)
3813 {
3814 UNIMPLEMENTED;
3815 return CR_CALL_NOT_IMPLEMENTED;
3816 }
3817
3818
3819 /* Function 71 */
3820 DWORD
3821 WINAPI
3822 PNP_DriverStoreDeleteDriverPackage(
3823 handle_t hBinding)
3824 {
3825 UNIMPLEMENTED;
3826 return CR_CALL_NOT_IMPLEMENTED;
3827 }
3828
3829
3830 /* Function 72 */
3831 DWORD
3832 WINAPI
3833 PNP_RegisterServiceNotification(
3834 handle_t hBinding)
3835 {
3836 UNIMPLEMENTED;
3837 return CR_CALL_NOT_IMPLEMENTED;
3838 }
3839
3840
3841 /* Function 73 */
3842 DWORD
3843 WINAPI
3844 PNP_SetActiveService(
3845 handle_t hBinding,
3846 LPWSTR pszFilter,
3847 DWORD ulFlags)
3848 {
3849 UNIMPLEMENTED;
3850 return CR_CALL_NOT_IMPLEMENTED;
3851 }
3852
3853
3854 /* Function 74 */
3855 DWORD
3856 WINAPI
3857 PNP_DeleteServiceDevices(
3858 handle_t hBinding)
3859 {
3860 UNIMPLEMENTED;
3861 return CR_CALL_NOT_IMPLEMENTED;
3862 }