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