[SETUPAPI] Fix broken control definition.
[reactos.git] / dll / win32 / setupapi / cfgmgr.c
1 /*
2 * Configuration manager functions
3 *
4 * Copyright 2000 James Hatheway
5 * Copyright 2005, 2006 Eric Kohl
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "setupapi_private.h"
23
24 #include <dbt.h>
25 #include <pnp_c.h>
26
27 #include "rpc_private.h"
28
29 /* Registry key and value names */
30 static const WCHAR Backslash[] = {'\\', 0};
31 static const WCHAR Class[] = {'C','l','a','s','s',0};
32
33 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
34 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
35 'C','o','n','t','r','o','l','\\',
36 'C','l','a','s','s',0};
37
38 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
39 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
40 'C','o','n','t','r','o','l','\\',
41 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
42
43 typedef struct _MACHINE_INFO
44 {
45 WCHAR szMachineName[SP_MAX_MACHINENAME_LENGTH];
46 RPC_BINDING_HANDLE BindingHandle;
47 HSTRING_TABLE StringTable;
48 BOOL bLocal;
49 } MACHINE_INFO, *PMACHINE_INFO;
50
51
52 typedef struct _LOG_CONF_INFO
53 {
54 ULONG ulMagic;
55 DEVINST dnDevInst;
56 ULONG ulFlags;
57 ULONG ulTag;
58 } LOG_CONF_INFO, *PLOG_CONF_INFO;
59
60 #define LOG_CONF_MAGIC 0x464E434C /* "LCNF" */
61
62
63 typedef struct _NOTIFY_DATA
64 {
65 ULONG ulMagic;
66 ULONG ulNotifyData;
67 } NOTIFY_DATA, *PNOTIFY_DATA;
68
69 #define NOTIFY_MAGIC 0x44556677
70
71
72 typedef struct _INTERNAL_RANGE
73 {
74 LIST_ENTRY ListEntry;
75 DWORDLONG ullStart;
76 DWORDLONG ullEnd;
77 } INTERNAL_RANGE, *PINTERNAL_RANGE;
78
79 typedef struct _INTERNAL_RANGE_LIST
80 {
81 ULONG ulMagic;
82 HANDLE hMutex;
83 LIST_ENTRY ListHead;
84 } INTERNAL_RANGE_LIST, *PINTERNAL_RANGE_LIST;
85
86 #define RANGE_LIST_MAGIC 0x33445566
87
88 typedef struct _CONFLICT_DATA
89 {
90 ULONG ulMagic;
91 PPNP_CONFLICT_LIST pConflictList;
92 } CONFLICT_DATA, *PCONFLICT_DATA;
93
94 #define CONFLICT_MAGIC 0x11225588
95
96
97 /* FUNCTIONS ****************************************************************/
98
99 static
100 BOOL
101 GuidToString(
102 _In_ LPGUID Guid,
103 _Out_ LPWSTR String)
104 {
105 LPWSTR lpString;
106
107 if (UuidToStringW(Guid, &lpString) != RPC_S_OK)
108 return FALSE;
109
110 lstrcpyW(&String[1], lpString);
111
112 String[0] = '{';
113 String[MAX_GUID_STRING_LEN - 2] = '}';
114 String[MAX_GUID_STRING_LEN - 1] = UNICODE_NULL;
115
116 RpcStringFreeW(&lpString);
117
118 return TRUE;
119 }
120
121
122 static
123 CONFIGRET
124 RpcStatusToCmStatus(
125 _In_ RPC_STATUS Status)
126 {
127 return CR_FAILURE;
128 }
129
130
131 static
132 ULONG
133 GetRegistryPropertyType(
134 _In_ ULONG ulProperty)
135 {
136 switch (ulProperty)
137 {
138 case CM_DRP_DEVICEDESC:
139 case CM_DRP_SERVICE:
140 case CM_DRP_CLASS:
141 case CM_DRP_CLASSGUID:
142 case CM_DRP_DRIVER:
143 case CM_DRP_MFG:
144 case CM_DRP_FRIENDLYNAME:
145 case CM_DRP_LOCATION_INFORMATION:
146 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
147 case CM_DRP_ENUMERATOR_NAME:
148 case CM_DRP_SECURITY_SDS:
149 case CM_DRP_UI_NUMBER_DESC_FORMAT:
150 return REG_SZ;
151
152 case CM_DRP_HARDWAREID:
153 case CM_DRP_COMPATIBLEIDS:
154 case CM_DRP_UPPERFILTERS:
155 case CM_DRP_LOWERFILTERS:
156 return REG_MULTI_SZ;
157
158 case CM_DRP_CONFIGFLAGS:
159 case CM_DRP_CAPABILITIES:
160 case CM_DRP_UI_NUMBER:
161 case CM_DRP_LEGACYBUSTYPE:
162 case CM_DRP_BUSNUMBER:
163 case CM_DRP_DEVTYPE:
164 case CM_DRP_EXCLUSIVE:
165 case CM_DRP_CHARACTERISTICS:
166 case CM_DRP_ADDRESS:
167 case CM_DRP_REMOVAL_POLICY:
168 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
169 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
170 case CM_DRP_INSTALL_STATE:
171 return REG_DWORD;
172
173 case CM_DRP_BUSTYPEGUID:
174 case CM_DRP_SECURITY:
175 case CM_DRP_DEVICE_POWER_DATA:
176 default:
177 return REG_BINARY;
178 }
179
180 return REG_NONE;
181 }
182
183
184 static
185 VOID
186 SplitDeviceInstanceId(
187 _In_ PWSTR pszDeviceInstanceId,
188 _Out_ PWSTR pszDeviceId,
189 _Out_ PWSTR pszInstanceId)
190 {
191 PWCHAR ptr;
192
193 wcscpy(pszDeviceId, pszDeviceInstanceId);
194
195 ptr = wcschr(pszDeviceId, L'\\');
196 if (ptr != NULL)
197 {
198 *ptr = UNICODE_NULL;
199 ptr++;
200
201 wcscpy(pszInstanceId, ptr);
202 }
203 else
204 {
205 *pszInstanceId = UNICODE_NULL;
206 }
207 }
208
209
210 static
211 CONFIGRET
212 GetDeviceInstanceKeyPath(
213 _In_ RPC_BINDING_HANDLE BindingHandle,
214 _In_ PWSTR pszDeviceInst,
215 _Out_ PWSTR pszKeyPath,
216 _Out_ PWSTR pszInstancePath,
217 _In_ ULONG ulHardwareProfile,
218 _In_ ULONG ulFlags)
219 {
220 PWSTR pszBuffer = NULL;
221 ULONG ulType = 0;
222 ULONG ulTransferLength, ulLength;
223 CONFIGRET ret = CR_SUCCESS;
224
225 TRACE("GetDeviceInstanceKeyPath()\n");
226
227 /* Allocate a buffer for the device id */
228 pszBuffer = MyMalloc(300 * sizeof(WCHAR));
229 if (pszBuffer == NULL)
230 {
231 ERR("MyMalloc() failed\n");
232 return CR_OUT_OF_MEMORY;
233 }
234
235 if (ulFlags & CM_REGISTRY_SOFTWARE)
236 {
237 /* Software Key Path */
238
239 if (ulFlags & CM_REGISTRY_CONFIG)
240 {
241 SplitDeviceInstanceId(pszDeviceInst,
242 pszBuffer,
243 pszInstancePath);
244
245 if (ulHardwareProfile == 0)
246 {
247 wsprintfW(pszKeyPath,
248 L"%s\\%s\\%s\\%s",
249 L"System\\CurrentControlSet\\Hardware Profiles",
250 L"Current",
251 L"System\\CurrentControlSet\\Enum",
252 pszBuffer);
253 }
254 else
255 {
256 wsprintfW(pszKeyPath,
257 L"%s\\%04lu\\%s\\%s",
258 L"System\\CurrentControlSet\\Hardware Profiles",
259 ulHardwareProfile,
260 L"System\\CurrentControlSet\\Enum",
261 pszBuffer);
262 }
263 }
264 else if (ulFlags & CM_REGISTRY_USER)
265 {
266 wsprintfW(pszKeyPath,
267 L"%s\\%s",
268 L"System\\CurrentControlSet\\Enum",
269 pszDeviceInst);
270
271 wcscpy(pszInstancePath,
272 L"Device Parameters");
273 }
274 else
275 {
276 SplitDeviceInstanceId(pszDeviceInst,
277 pszBuffer,
278 pszInstancePath);
279
280 wsprintfW(pszKeyPath,
281 L"%s\\%s",
282 L"System\\CurrentControlSet\\Enum",
283 pszBuffer);
284 }
285 }
286 else
287 {
288 /* Hardware Key Path */
289
290 ulTransferLength = 300 * sizeof(WCHAR);
291 ulLength = 300 * sizeof(WCHAR);
292 ret = PNP_GetDeviceRegProp(BindingHandle,
293 pszDeviceInst,
294 CM_DRP_DRIVER,
295 &ulType,
296 (PVOID)pszBuffer,
297 &ulTransferLength,
298 &ulLength,
299 0);
300 if (ret != CR_SUCCESS)
301 {
302 ERR("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret);
303 goto done;
304 }
305
306 TRACE("szBuffer: %S\n", pszBuffer);
307
308 SplitDeviceInstanceId(pszBuffer,
309 pszBuffer,
310 pszInstancePath);
311
312 TRACE("szBuffer: %S\n", pszBuffer);
313
314 if (ulFlags & CM_REGISTRY_CONFIG)
315 {
316 if (ulHardwareProfile == 0)
317 {
318 wsprintfW(pszKeyPath,
319 L"%s\\%s\\%s\\%s",
320 L"System\\CurrentControlSet\\Hardware Profiles",
321 L"Current",
322 L"System\\CurrentControlSet\\Control\\Class",
323 pszBuffer);
324 }
325 else
326 {
327 wsprintfW(pszKeyPath,
328 L"%s\\%04lu\\%s\\%s",
329 L"System\\CurrentControlSet\\Hardware Profiles",
330 ulHardwareProfile,
331 L"System\\CurrentControlSet\\Control\\Class",
332 pszBuffer);
333 }
334 }
335 else
336 {
337 wsprintfW(pszKeyPath,
338 L"%s\\%s",
339 L"System\\CurrentControlSet\\Control\\Class",
340 pszBuffer);
341 }
342 }
343
344 done:
345 if (pszBuffer != NULL)
346 MyFree(pszBuffer);
347
348 return ret;
349 }
350
351
352 BOOL
353 IsValidRangeList(
354 _In_opt_ PINTERNAL_RANGE_LIST pRangeList)
355 {
356 BOOL bValid = TRUE;
357
358 if (pRangeList == NULL)
359 return FALSE;
360
361 _SEH2_TRY
362 {
363 if (pRangeList->ulMagic != RANGE_LIST_MAGIC)
364 bValid = FALSE;
365 }
366 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
367 {
368 bValid = FALSE;
369 }
370 _SEH2_END;
371
372 return bValid;
373 }
374
375
376 BOOL
377 IsValidLogConf(
378 _In_opt_ PLOG_CONF_INFO pLogConfInfo)
379 {
380 BOOL bValid = TRUE;
381
382 if (pLogConfInfo == NULL)
383 return FALSE;
384
385 _SEH2_TRY
386 {
387 if (pLogConfInfo->ulMagic != LOG_CONF_MAGIC)
388 bValid = FALSE;
389 }
390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
391 {
392 bValid = FALSE;
393 }
394 _SEH2_END;
395
396 return bValid;
397 }
398
399
400 BOOL
401 IsValidConflictData(
402 _In_opt_ PCONFLICT_DATA pConflictData)
403 {
404 BOOL bValid = TRUE;
405
406 if (pConflictData == NULL)
407 return FALSE;
408
409 _SEH2_TRY
410 {
411 if (pConflictData->ulMagic != CONFLICT_MAGIC)
412 bValid = FALSE;
413 }
414 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
415 {
416 bValid = FALSE;
417 }
418 _SEH2_END;
419
420 return bValid;
421 }
422
423
424 /***********************************************************************
425 * CMP_GetBlockedDriverInfo [SETUPAPI.@]
426 */
427 CONFIGRET
428 WINAPI
429 CMP_GetBlockedDriverInfo(
430 _Out_opt_ LPWSTR pszNames,
431 _Inout_ PULONG pulLength,
432 _In_ ULONG ulFlags,
433 _In_opt_ HMACHINE hMachine)
434 {
435 RPC_BINDING_HANDLE BindingHandle = NULL;
436 ULONG ulTransferLength;
437 CONFIGRET ret;
438
439 TRACE("CMP_GetBlockedDriverInfo(%p %p %lx %p)\n",
440 pszNames, pulLength, ulFlags, hMachine);
441
442 if (hMachine != NULL)
443 {
444 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
445 if (BindingHandle == NULL)
446 return CR_FAILURE;
447 }
448 else
449 {
450 if (!PnpGetLocalHandles(&BindingHandle, NULL))
451 return CR_FAILURE;
452 }
453
454 ulTransferLength = *pulLength;
455
456 RpcTryExcept
457 {
458 ret = PNP_GetBlockedDriverInfo(BindingHandle,
459 (PBYTE)pszNames,
460 &ulTransferLength,
461 pulLength,
462 ulFlags);
463 }
464 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
465 {
466 ret = RpcStatusToCmStatus(RpcExceptionCode());
467 }
468 RpcEndExcept;
469
470 return ret;
471 }
472
473
474 /***********************************************************************
475 * CMP_GetServerSideDeviceInstallFlags [SETUPAPI.@]
476 */
477 CONFIGRET
478 WINAPI
479 CMP_GetServerSideDeviceInstallFlags(
480 _Out_ PULONG pulSSDIFlags,
481 _In_ ULONG ulFlags,
482 _In_opt_ HMACHINE hMachine)
483 {
484 RPC_BINDING_HANDLE BindingHandle = NULL;
485 CONFIGRET ret;
486
487 TRACE("CMP_GetServerSideDeviceInstallFlags(%p %lx %p)\n",
488 pulSSDIFlags, ulFlags, hMachine);
489
490 if (pulSSDIFlags == NULL)
491 return CR_INVALID_POINTER;
492
493 if (ulFlags != 0)
494 return CR_INVALID_FLAG;
495
496 if (hMachine != NULL)
497 {
498 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
499 if (BindingHandle == NULL)
500 return CR_FAILURE;
501 }
502 else
503 {
504 if (!PnpGetLocalHandles(&BindingHandle, NULL))
505 return CR_FAILURE;
506 }
507
508 RpcTryExcept
509 {
510 ret = PNP_GetServerSideDeviceInstallFlags(BindingHandle,
511 pulSSDIFlags,
512 ulFlags);
513 }
514 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
515 {
516 ret = RpcStatusToCmStatus(RpcExceptionCode());
517 }
518 RpcEndExcept;
519
520 return ret;
521 }
522
523
524 /***********************************************************************
525 * CMP_Init_Detection [SETUPAPI.@]
526 */
527 CONFIGRET
528 WINAPI
529 CMP_Init_Detection(
530 _In_ ULONG ulMagic)
531 {
532 RPC_BINDING_HANDLE BindingHandle = NULL;
533 CONFIGRET ret;
534
535 TRACE("CMP_Init_Detection(%lu)\n", ulMagic);
536
537 if (ulMagic != CMP_MAGIC)
538 return CR_INVALID_DATA;
539
540 if (!PnpGetLocalHandles(&BindingHandle, NULL))
541 return CR_FAILURE;
542
543 RpcTryExcept
544 {
545 ret = PNP_InitDetection(BindingHandle);
546 }
547 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
548 {
549 ret = RpcStatusToCmStatus(RpcExceptionCode());
550 }
551 RpcEndExcept;
552
553 return ret;
554 }
555
556
557 /***********************************************************************
558 * CMP_RegisterNotification [SETUPAPI.@]
559 */
560 CONFIGRET
561 WINAPI
562 CMP_RegisterNotification(
563 _In_ HANDLE hRecipient,
564 _In_ LPVOID lpvNotificationFilter,
565 _In_ ULONG ulFlags,
566 _Out_ PHDEVNOTIFY phDevNotify)
567 {
568 RPC_BINDING_HANDLE BindingHandle = NULL;
569 PNOTIFY_DATA pNotifyData = NULL;
570 CONFIGRET ret = CR_SUCCESS;
571
572 TRACE("CMP_RegisterNotification(%p %p %lu %p)\n",
573 hRecipient, lpvNotificationFilter, ulFlags, phDevNotify);
574
575 if ((hRecipient == NULL) ||
576 (lpvNotificationFilter == NULL) ||
577 (phDevNotify == NULL))
578 return CR_INVALID_POINTER;
579
580 if (ulFlags & ~0x7)
581 return CR_INVALID_FLAG;
582
583 if (((PDEV_BROADCAST_HDR)lpvNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR))
584 return CR_INVALID_DATA;
585
586 if (!PnpGetLocalHandles(&BindingHandle, NULL))
587 return CR_FAILURE;
588
589 pNotifyData = HeapAlloc(GetProcessHeap(),
590 HEAP_ZERO_MEMORY,
591 sizeof(NOTIFY_DATA));
592 if (pNotifyData == NULL)
593 return CR_OUT_OF_MEMORY;
594
595 pNotifyData->ulMagic = NOTIFY_MAGIC;
596
597 /*
598 if (dwFlags & DEVICE_NOTIFY_SERVICE_HANDLE == DEVICE_NOTYFY_WINDOW_HANDLE)
599 {
600
601 }
602 else if (dwFlags & DEVICE_NOTIFY_SERVICE_HANDLE == DEVICE_NOTYFY_SERVICE_HANDLE)
603 {
604
605 }
606 */
607
608 RpcTryExcept
609 {
610 ret = PNP_RegisterNotification(BindingHandle,
611 ulFlags,
612 &pNotifyData->ulNotifyData);
613 }
614 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
615 {
616 ret = RpcStatusToCmStatus(RpcExceptionCode());
617 }
618 RpcEndExcept;
619
620 if (ret == CR_SUCCESS)
621 {
622 *phDevNotify = (HDEVNOTIFY)pNotifyData;
623 }
624 else
625 {
626 if (pNotifyData != NULL)
627 HeapFree(GetProcessHeap(), 0, pNotifyData);
628
629 *phDevNotify = (HDEVNOTIFY)NULL;
630 }
631
632 return ret;
633 }
634
635
636 /***********************************************************************
637 * CMP_Report_LogOn [SETUPAPI.@]
638 */
639 CONFIGRET
640 WINAPI
641 CMP_Report_LogOn(
642 _In_ DWORD dwMagic,
643 _In_ DWORD dwProcessId)
644 {
645 RPC_BINDING_HANDLE BindingHandle = NULL;
646 CONFIGRET ret = CR_SUCCESS;
647 BOOL bAdmin;
648 DWORD i;
649
650 TRACE("CMP_Report_LogOn(%lu %lu)\n", dwMagic, dwProcessId);
651
652 if (dwMagic != CMP_MAGIC)
653 return CR_INVALID_DATA;
654
655 if (!PnpGetLocalHandles(&BindingHandle, NULL))
656 return CR_FAILURE;
657
658 bAdmin = pSetupIsUserAdmin();
659
660 for (i = 0; i < 30; i++)
661 {
662 RpcTryExcept
663 {
664 ret = PNP_ReportLogOn(BindingHandle,
665 bAdmin,
666 dwProcessId);
667 }
668 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
669 {
670 ret = RpcStatusToCmStatus(RpcExceptionCode());
671 }
672 RpcEndExcept;
673
674 if (ret == CR_SUCCESS)
675 break;
676
677 Sleep(5000);
678 }
679
680 return ret;
681 }
682
683
684 /***********************************************************************
685 * CMP_UnregisterNotification [SETUPAPI.@]
686 */
687 CONFIGRET
688 WINAPI
689 CMP_UnregisterNotification(
690 _In_ HDEVNOTIFY hDevNotify)
691 {
692 RPC_BINDING_HANDLE BindingHandle = NULL;
693 PNOTIFY_DATA pNotifyData;
694 CONFIGRET ret = CR_SUCCESS;
695
696 TRACE("CMP_UnregisterNotification(%p)\n", hDevNotify);
697
698 pNotifyData = (PNOTIFY_DATA)hDevNotify;
699
700 if ((pNotifyData == NULL) ||
701 (pNotifyData->ulMagic != NOTIFY_MAGIC))
702 return CR_INVALID_POINTER;
703
704 if (!PnpGetLocalHandles(&BindingHandle, NULL))
705 return CR_FAILURE;
706
707 RpcTryExcept
708 {
709 ret = PNP_UnregisterNotification(BindingHandle,
710 pNotifyData->ulNotifyData);
711 }
712 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
713 {
714 ret = RpcStatusToCmStatus(RpcExceptionCode());
715 }
716 RpcEndExcept;
717
718 if (ret == CR_SUCCESS)
719 HeapFree(GetProcessHeap(), 0, pNotifyData);
720
721 return ret;
722 }
723
724
725 /***********************************************************************
726 * CMP_WaitNoPendingInstallEvents [SETUPAPI.@]
727 */
728 DWORD
729 WINAPI
730 CMP_WaitNoPendingInstallEvents(
731 _In_ DWORD dwTimeout)
732 {
733 HANDLE hEvent;
734 DWORD ret;
735
736 TRACE("CMP_WaitNoPendingInstallEvents(%lu)\n", dwTimeout);
737
738 hEvent = OpenEventW(SYNCHRONIZE, FALSE, L"Global\\PnP_No_Pending_Install_Events");
739 if (hEvent == NULL)
740 return WAIT_FAILED;
741
742 ret = WaitForSingleObject(hEvent, dwTimeout);
743 CloseHandle(hEvent);
744 return ret;
745 }
746
747
748 /***********************************************************************
749 * CMP_WaitServicesAvailable [SETUPAPI.@]
750 */
751 CONFIGRET
752 WINAPI
753 CMP_WaitServicesAvailable(
754 _In_opt_ HMACHINE hMachine)
755 {
756 RPC_BINDING_HANDLE BindingHandle = NULL;
757 CONFIGRET ret = CR_SUCCESS;
758 WORD Version;
759
760 TRACE("CMP_WaitServicesAvailable(%p)\n", hMachine);
761
762 if (hMachine != NULL)
763 {
764 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
765 if (BindingHandle == NULL)
766 return CR_FAILURE;
767 }
768 else
769 {
770 if (!PnpGetLocalHandles(&BindingHandle, NULL))
771 return CR_FAILURE;
772 }
773
774 RpcTryExcept
775 {
776 ret = PNP_GetVersion(BindingHandle, &Version);
777 }
778 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
779 {
780 ret = RpcStatusToCmStatus(RpcExceptionCode());
781 }
782 RpcEndExcept;
783
784 return ret;
785 }
786
787
788 /***********************************************************************
789 * CM_Add_Empty_Log_Conf [SETUPAPI.@]
790 */
791 CONFIGRET
792 WINAPI
793 CM_Add_Empty_Log_Conf(
794 _Out_ PLOG_CONF plcLogConf,
795 _In_ DEVINST dnDevInst,
796 _In_ PRIORITY Priority,
797 _In_ ULONG ulFlags)
798 {
799 TRACE("CM_Add_Empty_Log_Conf(%p %p %lu %lx)\n",
800 plcLogConf, dnDevInst, Priority, ulFlags);
801
802 return CM_Add_Empty_Log_Conf_Ex(plcLogConf, dnDevInst, Priority,
803 ulFlags, NULL);
804 }
805
806
807 /***********************************************************************
808 * CM_Add_Empty_Log_Conf_Ex [SETUPAPI.@]
809 */
810 CONFIGRET
811 WINAPI CM_Add_Empty_Log_Conf_Ex(
812 _Out_ PLOG_CONF plcLogConf,
813 _In_ DEVINST dnDevInst,
814 _In_ PRIORITY Priority,
815 _In_ ULONG ulFlags,
816 _In_opt_ HMACHINE hMachine)
817 {
818 RPC_BINDING_HANDLE BindingHandle = NULL;
819 HSTRING_TABLE StringTable = NULL;
820 ULONG ulLogConfTag = 0;
821 LPWSTR lpDevInst;
822 PLOG_CONF_INFO pLogConfInfo;
823 CONFIGRET ret = CR_SUCCESS;
824
825 FIXME("CM_Add_Empty_Log_Conf_Ex(%p %p %lu %lx %p)\n",
826 plcLogConf, dnDevInst, Priority, ulFlags, hMachine);
827
828 if (!pSetupIsUserAdmin())
829 return CR_ACCESS_DENIED;
830
831 if (plcLogConf == NULL)
832 return CR_INVALID_POINTER;
833
834 if (dnDevInst == 0)
835 return CR_INVALID_DEVINST;
836
837 if (Priority > 0xFFFF)
838 return CR_INVALID_PRIORITY;
839
840 if (ulFlags & ~(LOG_CONF_BITS | PRIORITY_BIT))
841 return CR_INVALID_FLAG;
842
843 if (hMachine != NULL)
844 {
845 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
846 if (BindingHandle == NULL)
847 return CR_FAILURE;
848
849 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
850 if (StringTable == 0)
851 return CR_FAILURE;
852 }
853 else
854 {
855 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
856 return CR_FAILURE;
857 }
858
859 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
860 if (lpDevInst == NULL)
861 return CR_INVALID_DEVNODE;
862
863 RpcTryExcept
864 {
865 ret = PNP_AddEmptyLogConf(BindingHandle, lpDevInst, Priority,
866 &ulLogConfTag, ulFlags);
867 }
868 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
869 {
870 ret = RpcStatusToCmStatus(RpcExceptionCode());
871 }
872 RpcEndExcept;
873
874 if (ret == CR_SUCCESS)
875 {
876 pLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
877 if (pLogConfInfo == NULL)
878 {
879 ret = CR_OUT_OF_MEMORY;
880 }
881 else
882 {
883 pLogConfInfo->ulMagic = LOG_CONF_MAGIC;
884 pLogConfInfo->dnDevInst = dnDevInst;
885 pLogConfInfo->ulFlags = ulFlags;
886 pLogConfInfo->ulTag = ulLogConfTag;
887
888 *plcLogConf = (LOG_CONF)pLogConfInfo;
889
890 ret = CR_SUCCESS;
891 }
892 }
893
894 return ret;
895 }
896
897
898 /***********************************************************************
899 * CM_Add_IDA [SETUPAPI.@]
900 */
901 CONFIGRET
902 WINAPI
903 CM_Add_IDA(
904 _In_ DEVINST dnDevInst,
905 _In_ PSTR pszID,
906 _In_ ULONG ulFlags)
907 {
908 TRACE("CM_Add_IDA(%p %s %lx)\n",
909 dnDevInst, debugstr_a(pszID), ulFlags);
910
911 return CM_Add_ID_ExA(dnDevInst, pszID, ulFlags, NULL);
912 }
913
914
915 /***********************************************************************
916 * CM_Add_IDW [SETUPAPI.@]
917 */
918 CONFIGRET
919 WINAPI
920 CM_Add_IDW(
921 _In_ DEVINST dnDevInst,
922 _In_ PWSTR pszID,
923 _In_ ULONG ulFlags)
924 {
925 TRACE("CM_Add_IDW(%p %s %lx)\n",
926 dnDevInst, debugstr_w(pszID), ulFlags);
927
928 return CM_Add_ID_ExW(dnDevInst, pszID, ulFlags, NULL);
929 }
930
931
932 /***********************************************************************
933 * CM_Add_ID_ExA [SETUPAPI.@]
934 */
935 CONFIGRET
936 WINAPI
937 CM_Add_ID_ExA(
938 _In_ DEVINST dnDevInst,
939 _In_ PSTR pszID,
940 _In_ ULONG ulFlags,
941 _In_opt_ HMACHINE hMachine)
942 {
943 PWSTR pszIDW;
944 CONFIGRET ret;
945
946 TRACE("CM_Add_ID_ExA(%p %s %lx %p)\n",
947 dnDevInst, debugstr_a(pszID), ulFlags, hMachine);
948
949 if (pSetupCaptureAndConvertAnsiArg(pszID, &pszIDW))
950 return CR_INVALID_DATA;
951
952 ret = CM_Add_ID_ExW(dnDevInst, pszIDW, ulFlags, hMachine);
953
954 MyFree(pszIDW);
955
956 return ret;
957 }
958
959
960 /***********************************************************************
961 * CM_Add_ID_ExW [SETUPAPI.@]
962 */
963 CONFIGRET
964 WINAPI
965 CM_Add_ID_ExW(
966 _In_ DEVINST dnDevInst,
967 _In_ PWSTR pszID,
968 _In_ ULONG ulFlags,
969 _In_opt_ HMACHINE hMachine)
970 {
971 RPC_BINDING_HANDLE BindingHandle = NULL;
972 HSTRING_TABLE StringTable = NULL;
973 LPWSTR lpDevInst;
974 CONFIGRET ret;
975
976 TRACE("CM_Add_ID_ExW(%p %s %lx %p)\n",
977 dnDevInst, debugstr_w(pszID), ulFlags, hMachine);
978
979 if (!pSetupIsUserAdmin())
980 return CR_ACCESS_DENIED;
981
982 if (dnDevInst == 0)
983 return CR_INVALID_DEVINST;
984
985 if (pszID == NULL)
986 return CR_INVALID_POINTER;
987
988 if (ulFlags & ~CM_ADD_ID_BITS)
989 return CR_INVALID_FLAG;
990
991 if (hMachine != NULL)
992 {
993 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
994 if (BindingHandle == NULL)
995 return CR_FAILURE;
996
997 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
998 if (StringTable == 0)
999 return CR_FAILURE;
1000 }
1001 else
1002 {
1003 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1004 return CR_FAILURE;
1005 }
1006
1007 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1008 if (lpDevInst == NULL)
1009 return CR_INVALID_DEVNODE;
1010
1011 RpcTryExcept
1012 {
1013 ret = PNP_AddID(BindingHandle,
1014 lpDevInst,
1015 pszID,
1016 ulFlags);
1017 }
1018 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1019 {
1020 ret = RpcStatusToCmStatus(RpcExceptionCode());
1021 }
1022 RpcEndExcept;
1023
1024 return ret;
1025 }
1026
1027
1028 /***********************************************************************
1029 * CM_Add_Range [SETUPAPI.@]
1030 */
1031 CONFIGRET
1032 WINAPI
1033 CM_Add_Range(
1034 _In_ DWORDLONG ullStartValue,
1035 _In_ DWORDLONG ullEndValue,
1036 _In_ RANGE_LIST rlh,
1037 _In_ ULONG ulFlags)
1038 {
1039 PINTERNAL_RANGE_LIST pRangeList;
1040 PINTERNAL_RANGE pRange;
1041 CONFIGRET ret = CR_SUCCESS;
1042
1043 FIXME("CM_Add_Range(%I64u %I64u %p %lx)\n",
1044 ullStartValue, ullEndValue, rlh, ulFlags);
1045
1046 pRangeList = (PINTERNAL_RANGE_LIST)rlh;
1047
1048 if (!IsValidRangeList(pRangeList))
1049 return CR_INVALID_RANGE_LIST;
1050
1051 if (ulFlags & ~CM_ADD_RANGE_BITS)
1052 return CR_INVALID_FLAG;
1053
1054 if (ullEndValue < ullStartValue)
1055 return CR_INVALID_RANGE;
1056
1057 /* Lock the range list */
1058 WaitForSingleObject(pRangeList->hMutex, INFINITE);
1059
1060 /* Allocate the new range */
1061 pRange = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNAL_RANGE));
1062 if (pRange == NULL)
1063 {
1064 ret = CR_OUT_OF_MEMORY;
1065 goto done;
1066 }
1067
1068 pRange->ullStart = ullStartValue;
1069 pRange->ullEnd = ullEndValue;
1070
1071 /* Insert the range */
1072 if (IsListEmpty(&pRangeList->ListHead))
1073 {
1074 InsertTailList(&pRangeList->ListHead, &pRange->ListEntry);
1075 }
1076 else
1077 {
1078
1079 }
1080
1081 done:
1082 /* Unlock the range list */
1083 ReleaseMutex(pRangeList->hMutex);
1084
1085 return ret;
1086 }
1087
1088
1089 /***********************************************************************
1090 * CM_Add_Res_Des [SETUPAPI.@]
1091 */
1092 CONFIGRET
1093 WINAPI
1094 CM_Add_Res_Des(
1095 _Out_opt_ PRES_DES prdResDes,
1096 _In_ LOG_CONF lcLogConf,
1097 _In_ RESOURCEID ResourceID,
1098 _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1099 _In_ ULONG ResourceLen,
1100 _In_ ULONG ulFlags)
1101 {
1102 TRACE("CM_Add_Res_Des(%p %p %lu %p %lu %lx)\n",
1103 prdResDes, lcLogConf, ResourceID, ResourceData, ResourceLen, ulFlags);
1104
1105 return CM_Add_Res_Des_Ex(prdResDes, lcLogConf, ResourceID, ResourceData,
1106 ResourceLen, ulFlags, NULL);
1107 }
1108
1109
1110 /***********************************************************************
1111 * CM_Add_Res_Des_Ex [SETUPAPI.@]
1112 */
1113 CONFIGRET
1114 WINAPI
1115 CM_Add_Res_Des_Ex(
1116 _Out_opt_ PRES_DES prdResDes,
1117 _In_ LOG_CONF lcLogConf,
1118 _In_ RESOURCEID ResourceID,
1119 _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1120 _In_ ULONG ResourceLen,
1121 _In_ ULONG ulFlags,
1122 _In_opt_ HMACHINE hMachine)
1123 {
1124 FIXME("CM_Add_Res_Des_Ex(%p %p %lu %p %lu %lx %p)\n",
1125 prdResDes, lcLogConf, ResourceID,
1126 ResourceData, ResourceLen, ulFlags, hMachine);
1127
1128 return CR_CALL_NOT_IMPLEMENTED;
1129 }
1130
1131
1132 /***********************************************************************
1133 * CM_Connect_MachineA [SETUPAPI.@]
1134 */
1135 CONFIGRET
1136 WINAPI
1137 CM_Connect_MachineA(
1138 _In_opt_ PCSTR UNCServerName,
1139 _Out_ PHMACHINE phMachine)
1140 {
1141 PWSTR pServerNameW;
1142 CONFIGRET ret;
1143
1144 TRACE("CM_Connect_MachineA(%s %p)\n",
1145 debugstr_a(UNCServerName), phMachine);
1146
1147 if (UNCServerName == NULL || *UNCServerName == 0)
1148 return CM_Connect_MachineW(NULL, phMachine);
1149
1150 if (pSetupCaptureAndConvertAnsiArg(UNCServerName, &pServerNameW))
1151 return CR_INVALID_DATA;
1152
1153 ret = CM_Connect_MachineW(pServerNameW, phMachine);
1154
1155 MyFree(pServerNameW);
1156
1157 return ret;
1158 }
1159
1160
1161 /***********************************************************************
1162 * CM_Connect_MachineW [SETUPAPI.@]
1163 */
1164 CONFIGRET
1165 WINAPI
1166 CM_Connect_MachineW(
1167 _In_opt_ PCWSTR UNCServerName,
1168 _Out_ PHMACHINE phMachine)
1169 {
1170 PMACHINE_INFO pMachine;
1171
1172 TRACE("CM_Connect_MachineW(%s %p)\n",
1173 debugstr_w(UNCServerName), phMachine);
1174
1175 if (phMachine == NULL)
1176 return CR_INVALID_POINTER;
1177
1178 *phMachine = NULL;
1179
1180 pMachine = HeapAlloc(GetProcessHeap(), 0, sizeof(MACHINE_INFO));
1181 if (pMachine == NULL)
1182 return CR_OUT_OF_MEMORY;
1183
1184 if (UNCServerName == NULL || *UNCServerName == 0)
1185 {
1186 pMachine->bLocal = TRUE;
1187
1188 /* FIXME: store the computers name in pMachine->szMachineName */
1189
1190 if (!PnpGetLocalHandles(&pMachine->BindingHandle,
1191 &pMachine->StringTable))
1192 {
1193 HeapFree(GetProcessHeap(), 0, pMachine);
1194 return CR_FAILURE;
1195 }
1196 }
1197 else
1198 {
1199 pMachine->bLocal = FALSE;
1200 if (wcslen(UNCServerName) >= SP_MAX_MACHINENAME_LENGTH - 1)
1201 {
1202 HeapFree(GetProcessHeap(), 0, pMachine);
1203 return CR_INVALID_MACHINENAME;
1204 }
1205 lstrcpyW(pMachine->szMachineName, UNCServerName);
1206
1207 pMachine->StringTable = pSetupStringTableInitialize();
1208 if (pMachine->StringTable == NULL)
1209 {
1210 HeapFree(GetProcessHeap(), 0, pMachine);
1211 return CR_FAILURE;
1212 }
1213
1214 pSetupStringTableAddString(pMachine->StringTable, L"PLT", 1);
1215
1216 if (!PnpBindRpc(UNCServerName, &pMachine->BindingHandle))
1217 {
1218 pSetupStringTableDestroy(pMachine->StringTable);
1219 HeapFree(GetProcessHeap(), 0, pMachine);
1220 return CR_INVALID_MACHINENAME;
1221 }
1222 }
1223
1224 *phMachine = (PHMACHINE)pMachine;
1225
1226 return CR_SUCCESS;
1227 }
1228
1229
1230 /***********************************************************************
1231 * CM_Create_DevNodeA [SETUPAPI.@]
1232 */
1233 CONFIGRET
1234 WINAPI
1235 CM_Create_DevNodeA(
1236 _Out_ PDEVINST pdnDevInst,
1237 _In_ DEVINSTID_A pDeviceID,
1238 _In_ DEVINST dnParent,
1239 _In_ ULONG ulFlags)
1240 {
1241 TRACE("CM_Create_DevNodeA(%p %s %p %lx)\n",
1242 pdnDevInst, debugstr_a(pDeviceID), dnParent, ulFlags);
1243
1244 return CM_Create_DevNode_ExA(pdnDevInst, pDeviceID, dnParent,
1245 ulFlags, NULL);
1246 }
1247
1248
1249 /***********************************************************************
1250 * CM_Create_DevNodeW [SETUPAPI.@]
1251 */
1252 CONFIGRET
1253 WINAPI
1254 CM_Create_DevNodeW(
1255 _Out_ PDEVINST pdnDevInst,
1256 _In_ DEVINSTID_W pDeviceID,
1257 _In_ DEVINST dnParent,
1258 _In_ ULONG ulFlags)
1259 {
1260 TRACE("CM_Create_DevNodeW(%p %s %p %lx)\n",
1261 pdnDevInst, debugstr_w(pDeviceID), dnParent, ulFlags);
1262
1263 return CM_Create_DevNode_ExW(pdnDevInst, pDeviceID, dnParent,
1264 ulFlags, NULL);
1265 }
1266
1267
1268 /***********************************************************************
1269 * CM_Create_DevNode_ExA [SETUPAPI.@]
1270 */
1271 CONFIGRET
1272 WINAPI
1273 CM_Create_DevNode_ExA(
1274 _Out_ PDEVINST pdnDevInst,
1275 _In_ DEVINSTID_A pDeviceID,
1276 _In_ DEVINST dnParent,
1277 _In_ ULONG ulFlags,
1278 _In_opt_ HANDLE hMachine)
1279 {
1280 DEVINSTID_W pDeviceIDW;
1281 CONFIGRET ret;
1282
1283 TRACE("CM_Create_DevNode_ExA(%p %s %p %lx %p)\n",
1284 pdnDevInst, debugstr_a(pDeviceID), dnParent, ulFlags, hMachine);
1285
1286 if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIDW))
1287 return CR_INVALID_DATA;
1288
1289 ret = CM_Create_DevNode_ExW(pdnDevInst, pDeviceIDW, dnParent, ulFlags,
1290 hMachine);
1291
1292 MyFree(pDeviceIDW);
1293
1294 return ret;
1295 }
1296
1297
1298 /***********************************************************************
1299 * CM_Create_DevNode_ExW [SETUPAPI.@]
1300 */
1301 CONFIGRET
1302 WINAPI
1303 CM_Create_DevNode_ExW(
1304 _Out_ PDEVINST pdnDevInst,
1305 _In_ DEVINSTID_W pDeviceID,
1306 _In_ DEVINST dnParent,
1307 _In_ ULONG ulFlags,
1308 _In_opt_ HANDLE hMachine)
1309 {
1310 RPC_BINDING_HANDLE BindingHandle = NULL;
1311 HSTRING_TABLE StringTable = NULL;
1312 LPWSTR lpParentDevInst;
1313 CONFIGRET ret = CR_SUCCESS;
1314 WCHAR szLocalDeviceID[MAX_DEVICE_ID_LEN];
1315
1316 TRACE("CM_Create_DevNode_ExW(%p %s %p %lx %p)\n",
1317 pdnDevInst, debugstr_w(pDeviceID), dnParent, ulFlags, hMachine);
1318
1319 if (!pSetupIsUserAdmin())
1320 return CR_ACCESS_DENIED;
1321
1322 if (pdnDevInst == NULL)
1323 return CR_INVALID_POINTER;
1324
1325 if (pDeviceID == NULL || wcslen(pDeviceID) == 0 || wcslen(pDeviceID) >= MAX_DEVICE_ID_LEN)
1326 return CR_INVALID_DEVICE_ID;
1327
1328 if (dnParent == 0)
1329 return CR_INVALID_DEVNODE;
1330
1331 if (ulFlags & ~CM_CREATE_DEVNODE_BITS)
1332 return CR_INVALID_FLAG;
1333
1334 if (hMachine != NULL)
1335 {
1336 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1337 if (BindingHandle == NULL)
1338 return CR_FAILURE;
1339
1340 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1341 if (StringTable == 0)
1342 return CR_FAILURE;
1343 }
1344 else
1345 {
1346 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1347 return CR_FAILURE;
1348 }
1349
1350 lpParentDevInst = pSetupStringTableStringFromId(StringTable, dnParent);
1351 if (lpParentDevInst == NULL)
1352 return CR_INVALID_DEVNODE;
1353
1354 wcscpy(szLocalDeviceID, pDeviceID);
1355
1356 RpcTryExcept
1357 {
1358 ret = PNP_CreateDevInst(BindingHandle,
1359 szLocalDeviceID,
1360 lpParentDevInst,
1361 MAX_DEVICE_ID_LEN,
1362 ulFlags);
1363 }
1364 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1365 {
1366 ret = RpcStatusToCmStatus(RpcExceptionCode());
1367 }
1368 RpcEndExcept;
1369
1370 if (ret == CR_SUCCESS)
1371 {
1372 /* If CM_CREATE_DEVINST_GENERATE_ID was passed in, PNP_CreateDevInst
1373 * will return the generated device ID in szLocalDeviceID */
1374 *pdnDevInst = pSetupStringTableAddString(StringTable, szLocalDeviceID, 1);
1375 if (*pdnDevInst == 0)
1376 ret = CR_NO_SUCH_DEVNODE;
1377 }
1378
1379 return ret;
1380 }
1381
1382
1383 /***********************************************************************
1384 * CM_Create_Range_List [SETUPAPI.@]
1385 */
1386 CONFIGRET
1387 WINAPI
1388 CM_Create_Range_List(
1389 _Out_ PRANGE_LIST prlh,
1390 _In_ ULONG ulFlags)
1391 {
1392 PINTERNAL_RANGE_LIST pRangeList = NULL;
1393
1394 FIXME("CM_Create_Range_List(%p %lx)\n",
1395 prlh, ulFlags);
1396
1397 if (ulFlags != 0)
1398 return CR_INVALID_FLAG;
1399
1400 if (prlh == NULL)
1401 return CR_INVALID_POINTER;
1402
1403 /* Allocate the range list */
1404 pRangeList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(INTERNAL_RANGE_LIST));
1405 if (pRangeList == NULL)
1406 return CR_OUT_OF_MEMORY;
1407
1408 /* Set the magic value */
1409 pRangeList->ulMagic = RANGE_LIST_MAGIC;
1410
1411 /* Initialize the mutex for synchonized access */
1412 pRangeList->hMutex = CreateMutex(NULL, FALSE, NULL);
1413 if (pRangeList->hMutex == NULL)
1414 {
1415 HeapFree(GetProcessHeap(), 0, pRangeList);
1416 return CR_FAILURE;
1417 }
1418
1419 InitializeListHead(&pRangeList->ListHead);
1420
1421 *prlh = (RANGE_LIST)pRangeList;
1422
1423 return CR_SUCCESS;
1424 }
1425
1426
1427 /***********************************************************************
1428 * CM_Delete_Class_Key [SETUPAPI.@]
1429 */
1430 CONFIGRET
1431 WINAPI
1432 CM_Delete_Class_Key(
1433 _In_ LPGUID ClassGuid,
1434 _In_ ULONG ulFlags)
1435 {
1436 TRACE("CM_Delete_Class_Key(%p %lx)\n",
1437 ClassGuid, ulFlags);
1438
1439 return CM_Delete_Class_Key_Ex(ClassGuid, ulFlags, NULL);
1440 }
1441
1442
1443 /***********************************************************************
1444 * CM_Delete_Class_Key_Ex [SETUPAPI.@]
1445 */
1446 CONFIGRET
1447 WINAPI
1448 CM_Delete_Class_Key_Ex(
1449 _In_ LPGUID ClassGuid,
1450 _In_ ULONG ulFlags,
1451 _In_opt_ HANDLE hMachine)
1452 {
1453 WCHAR szGuidString[MAX_GUID_STRING_LEN];
1454 RPC_BINDING_HANDLE BindingHandle = NULL;
1455 CONFIGRET ret;
1456
1457 TRACE("CM_Delete_Class_Key_Ex(%p %lx %p)\n",
1458 ClassGuid, ulFlags, hMachine);
1459
1460 if (ClassGuid == NULL)
1461 return CR_INVALID_POINTER;
1462
1463 if (ulFlags & ~CM_DELETE_CLASS_BITS)
1464 return CR_INVALID_FLAG;
1465
1466 if (!GuidToString(ClassGuid, szGuidString))
1467 return CR_INVALID_DATA;
1468
1469 if (hMachine != NULL)
1470 {
1471 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1472 if (BindingHandle == NULL)
1473 return CR_FAILURE;
1474 }
1475 else
1476 {
1477 if (!PnpGetLocalHandles(&BindingHandle, NULL))
1478 return CR_FAILURE;
1479 }
1480
1481 RpcTryExcept
1482 {
1483 ret = PNP_DeleteClassKey(BindingHandle,
1484 szGuidString,
1485 ulFlags);
1486 }
1487 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1488 {
1489 ret = RpcStatusToCmStatus(RpcExceptionCode());
1490 }
1491 RpcEndExcept;
1492
1493 return ret;
1494 }
1495
1496
1497 /***********************************************************************
1498 * CM_Delete_DevNode_Key [SETUPAPI.@]
1499 */
1500 CONFIGRET
1501 WINAPI
1502 CM_Delete_DevNode_Key(
1503 _In_ DEVNODE dnDevNode,
1504 _In_ ULONG ulHardwareProfile,
1505 _In_ ULONG ulFlags)
1506 {
1507 TRACE("CM_Delete_DevNode_Key(%p %lu %lx)\n",
1508 dnDevNode, ulHardwareProfile, ulFlags);
1509
1510 return CM_Delete_DevNode_Key_Ex(dnDevNode, ulHardwareProfile, ulFlags,
1511 NULL);
1512 }
1513
1514
1515 /***********************************************************************
1516 * CM_Delete_DevNode_Key_Ex [SETUPAPI.@]
1517 */
1518 CONFIGRET
1519 WINAPI
1520 CM_Delete_DevNode_Key_Ex(
1521 _In_ DEVNODE dnDevNode,
1522 _In_ ULONG ulHardwareProfile,
1523 _In_ ULONG ulFlags,
1524 _In_opt_ HANDLE hMachine)
1525 {
1526 FIXME("CM_Delete_DevNode_Key_Ex(%p %lu %lx %p)\n",
1527 dnDevNode, ulHardwareProfile, ulFlags, hMachine);
1528
1529 return CR_CALL_NOT_IMPLEMENTED;
1530 }
1531
1532
1533 /***********************************************************************
1534 * CM_Delete_Range [SETUPAPI.@]
1535 */
1536 CONFIGRET
1537 WINAPI
1538 CM_Delete_Range(
1539 _In_ DWORDLONG ullStartValue,
1540 _In_ DWORDLONG ullEndValue,
1541 _In_ RANGE_LIST rlh,
1542 _In_ ULONG ulFlags)
1543 {
1544 FIXME("CM_Delete_Range(%I64u %I64u %p %lx)\n",
1545 ullStartValue, ullEndValue, rlh, ulFlags);
1546
1547 return CR_CALL_NOT_IMPLEMENTED;
1548 }
1549
1550
1551 /***********************************************************************
1552 * CM_Detect_Resource_Conflict [SETUPAPI.@]
1553 */
1554 CONFIGRET
1555 WINAPI
1556 CM_Detect_Resource_Conflict(
1557 _In_ DEVINST dnDevInst,
1558 _In_ RESOURCEID ResourceID,
1559 _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1560 _In_ ULONG ResourceLen,
1561 _Out_ PBOOL pbConflictDetected,
1562 _In_ ULONG ulFlags)
1563 {
1564 TRACE("CM_Detect_Resource_Conflict(%p %lu %p %lu %p 0x%lx)\n",
1565 dnDevInst, ResourceID, ResourceData, ResourceLen,
1566 pbConflictDetected, ulFlags);
1567
1568 return CM_Detect_Resource_Conflict_Ex(dnDevInst,
1569 ResourceID,
1570 ResourceData,
1571 ResourceLen,
1572 pbConflictDetected,
1573 ulFlags,
1574 NULL);
1575 }
1576
1577
1578 /***********************************************************************
1579 * CM_Detect_Resource_Conflict_Ex [SETUPAPI.@]
1580 */
1581 CONFIGRET
1582 WINAPI
1583 CM_Detect_Resource_Conflict_Ex(
1584 _In_ DEVINST dnDevInst,
1585 _In_ RESOURCEID ResourceID,
1586 _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1587 _In_ ULONG ResourceLen,
1588 _Out_ PBOOL pbConflictDetected,
1589 _In_ ULONG ulFlags,
1590 _In_opt_ HMACHINE hMachine)
1591 {
1592 FIXME("CM_Detect_Resource_Conflict_Ex(%p %lu %p %lu %p 0x%lx %p)\n",
1593 dnDevInst, ResourceID, ResourceData, ResourceLen,
1594 pbConflictDetected, ulFlags, hMachine);
1595
1596 return CR_CALL_NOT_IMPLEMENTED;
1597 }
1598
1599
1600 /***********************************************************************
1601 * CM_Disable_DevNode [SETUPAPI.@]
1602 */
1603 CONFIGRET
1604 WINAPI
1605 CM_Disable_DevNode(
1606 _In_ DEVINST dnDevInst,
1607 _In_ ULONG ulFlags)
1608 {
1609 TRACE("CM_Disable_DevNode(%p %lx)\n",
1610 dnDevInst, ulFlags);
1611
1612 return CM_Disable_DevNode_Ex(dnDevInst, ulFlags, NULL);
1613 }
1614
1615
1616 /***********************************************************************
1617 * CM_Disable_DevNode_Ex [SETUPAPI.@]
1618 */
1619 CONFIGRET
1620 WINAPI
1621 CM_Disable_DevNode_Ex(
1622 _In_ DEVINST dnDevInst,
1623 _In_ ULONG ulFlags,
1624 _In_opt_ HMACHINE hMachine)
1625 {
1626 RPC_BINDING_HANDLE BindingHandle = NULL;
1627 HSTRING_TABLE StringTable = NULL;
1628 LPWSTR lpDevInst;
1629 CONFIGRET ret;
1630
1631 FIXME("CM_Disable_DevNode_Ex(%p %lx %p)\n",
1632 dnDevInst, ulFlags, hMachine);
1633
1634 if (!pSetupIsUserAdmin())
1635 return CR_ACCESS_DENIED;
1636
1637 if (dnDevInst == 0)
1638 return CR_INVALID_DEVINST;
1639
1640 if (ulFlags != 0)
1641 return CR_INVALID_FLAG;
1642
1643 if (hMachine != NULL)
1644 {
1645 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1646 if (BindingHandle == NULL)
1647 return CR_FAILURE;
1648
1649 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1650 if (StringTable == 0)
1651 return CR_FAILURE;
1652 }
1653 else
1654 {
1655 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1656 return CR_FAILURE;
1657 }
1658
1659 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1660 if (lpDevInst == NULL)
1661 return CR_INVALID_DEVNODE;
1662
1663 RpcTryExcept
1664 {
1665 ret = PNP_DeviceInstanceAction(BindingHandle,
1666 PNP_DEVINST_DISABLE,
1667 ulFlags,
1668 lpDevInst,
1669 NULL);
1670 }
1671 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1672 {
1673 ret = RpcStatusToCmStatus(RpcExceptionCode());
1674 }
1675 RpcEndExcept;
1676
1677 return ret;
1678 }
1679
1680
1681 /***********************************************************************
1682 * CM_Disconnect_Machine [SETUPAPI.@]
1683 */
1684 CONFIGRET
1685 WINAPI
1686 CM_Disconnect_Machine(
1687 _In_opt_ HMACHINE hMachine)
1688 {
1689 PMACHINE_INFO pMachine;
1690
1691 TRACE("CM_Disconnect_Machine(%p)\n", hMachine);
1692
1693 pMachine = (PMACHINE_INFO)hMachine;
1694 if (pMachine == NULL)
1695 return CR_SUCCESS;
1696
1697 if (pMachine->bLocal == FALSE)
1698 {
1699 if (pMachine->StringTable != NULL)
1700 pSetupStringTableDestroy(pMachine->StringTable);
1701
1702 if (!PnpUnbindRpc(pMachine->BindingHandle))
1703 return CR_ACCESS_DENIED;
1704 }
1705
1706 HeapFree(GetProcessHeap(), 0, pMachine);
1707
1708 return CR_SUCCESS;
1709 }
1710
1711
1712 /***********************************************************************
1713 * CM_Dup_Range_List [SETUPAPI.@]
1714 */
1715 CONFIGRET
1716 WINAPI
1717 CM_Dup_Range_List(
1718 _In_ RANGE_LIST rlhOld,
1719 _In_ RANGE_LIST rlhNew,
1720 _In_ ULONG ulFlags)
1721 {
1722 FIXME("CM_Dup_Range_List(%p %p %lx)\n",
1723 rlhOld, rlhNew, ulFlags);
1724
1725 return CR_CALL_NOT_IMPLEMENTED;
1726 }
1727
1728
1729 /***********************************************************************
1730 * CM_Enable_DevNode [SETUPAPI.@]
1731 */
1732 CONFIGRET
1733 WINAPI
1734 CM_Enable_DevNode(
1735 _In_ DEVINST dnDevInst,
1736 _In_ ULONG ulFlags)
1737 {
1738 TRACE("CM_Enable_DevNode(%p %lx)\n",
1739 dnDevInst, ulFlags);
1740
1741 return CM_Enable_DevNode_Ex(dnDevInst, ulFlags, NULL);
1742 }
1743
1744
1745 /***********************************************************************
1746 * CM_Enable_DevNode_Ex [SETUPAPI.@]
1747 */
1748 CONFIGRET
1749 WINAPI
1750 CM_Enable_DevNode_Ex(
1751 _In_ DEVINST dnDevInst,
1752 _In_ ULONG ulFlags,
1753 _In_opt_ HMACHINE hMachine)
1754 {
1755 RPC_BINDING_HANDLE BindingHandle = NULL;
1756 HSTRING_TABLE StringTable = NULL;
1757 LPWSTR lpDevInst;
1758 CONFIGRET ret;
1759
1760 TRACE("CM_Enable_DevNode_Ex(%p %lx %p)\n",
1761 dnDevInst, ulFlags, hMachine);
1762
1763 if (!pSetupIsUserAdmin())
1764 return CR_ACCESS_DENIED;
1765
1766 if (dnDevInst == 0)
1767 return CR_INVALID_DEVINST;
1768
1769 if (ulFlags != 0)
1770 return CR_INVALID_FLAG;
1771
1772 if (hMachine != NULL)
1773 {
1774 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1775 if (BindingHandle == NULL)
1776 return CR_FAILURE;
1777
1778 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1779 if (StringTable == 0)
1780 return CR_FAILURE;
1781 }
1782 else
1783 {
1784 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1785 return CR_FAILURE;
1786 }
1787
1788 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1789 if (lpDevInst == NULL)
1790 return CR_INVALID_DEVNODE;
1791
1792 RpcTryExcept
1793 {
1794 ret = PNP_DeviceInstanceAction(BindingHandle,
1795 PNP_DEVINST_ENABLE,
1796 ulFlags,
1797 lpDevInst,
1798 NULL);
1799 }
1800 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1801 {
1802 ret = RpcStatusToCmStatus(RpcExceptionCode());
1803 }
1804 RpcEndExcept;
1805
1806 return ret;
1807 }
1808
1809
1810 /***********************************************************************
1811 * CM_Enumerate_Classes [SETUPAPI.@]
1812 */
1813 CONFIGRET
1814 WINAPI
1815 CM_Enumerate_Classes(
1816 _In_ ULONG ulClassIndex,
1817 _Out_ LPGUID ClassGuid,
1818 _In_ ULONG ulFlags)
1819 {
1820 TRACE("CM_Enumerate_Classes(%lx %p %lx)\n",
1821 ulClassIndex, ClassGuid, ulFlags);
1822
1823 return CM_Enumerate_Classes_Ex(ulClassIndex, ClassGuid, ulFlags, NULL);
1824 }
1825
1826
1827 /***********************************************************************
1828 * CM_Enumerate_Classes_Ex [SETUPAPI.@]
1829 */
1830 CONFIGRET
1831 WINAPI
1832 CM_Enumerate_Classes_Ex(
1833 _In_ ULONG ulClassIndex,
1834 _Out_ LPGUID ClassGuid,
1835 _In_ ULONG ulFlags,
1836 _In_opt_ HMACHINE hMachine)
1837 {
1838 WCHAR szBuffer[MAX_GUID_STRING_LEN];
1839 RPC_BINDING_HANDLE BindingHandle = NULL;
1840 CONFIGRET ret = CR_SUCCESS;
1841 ULONG ulLength = MAX_GUID_STRING_LEN;
1842
1843 TRACE("CM_Enumerate_Classes_Ex(%lx %p %lx %p)\n",
1844 ulClassIndex, ClassGuid, ulFlags, hMachine);
1845
1846 if (ClassGuid == NULL)
1847 return CR_INVALID_POINTER;
1848
1849 if (ulFlags != 0)
1850 return CR_INVALID_FLAG;
1851
1852 if (hMachine != NULL)
1853 {
1854 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1855 if (BindingHandle == NULL)
1856 return CR_FAILURE;
1857 }
1858 else
1859 {
1860 if (!PnpGetLocalHandles(&BindingHandle, NULL))
1861 return CR_FAILURE;
1862 }
1863
1864 RpcTryExcept
1865 {
1866 ret = PNP_EnumerateSubKeys(BindingHandle,
1867 PNP_CLASS_SUBKEYS,
1868 ulClassIndex,
1869 szBuffer,
1870 MAX_GUID_STRING_LEN,
1871 &ulLength,
1872 ulFlags);
1873 }
1874 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1875 {
1876 ret = RpcStatusToCmStatus(RpcExceptionCode());
1877 }
1878 RpcEndExcept;
1879
1880 if (ret == CR_SUCCESS)
1881 {
1882 /* Remove the {} */
1883 szBuffer[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
1884
1885 /* Convert the buffer to a GUID */
1886 if (UuidFromStringW(&szBuffer[1], ClassGuid) != RPC_S_OK)
1887 return CR_FAILURE;
1888 }
1889
1890 return ret;
1891 }
1892
1893
1894 /***********************************************************************
1895 * CM_Enumerate_EnumeratorsA [SETUPAPI.@]
1896 */
1897 CONFIGRET
1898 WINAPI
1899 CM_Enumerate_EnumeratorsA(
1900 _In_ ULONG ulEnumIndex,
1901 _Out_writes_(*pulLength) PCHAR Buffer,
1902 _Inout_ PULONG pulLength,
1903 _In_ ULONG ulFlags)
1904 {
1905 TRACE("CM_Enumerate_EnumeratorsA(%lu %p %p %lx)\n",
1906 ulEnumIndex, Buffer, pulLength, ulFlags);
1907
1908 return CM_Enumerate_Enumerators_ExA(ulEnumIndex, Buffer, pulLength,
1909 ulFlags, NULL);
1910 }
1911
1912
1913 /***********************************************************************
1914 * CM_Enumerate_EnumeratorsW [SETUPAPI.@]
1915 */
1916 CONFIGRET
1917 WINAPI
1918 CM_Enumerate_EnumeratorsW(
1919 _In_ ULONG ulEnumIndex,
1920 _Out_writes_(*pulLength) PWCHAR Buffer,
1921 _Inout_ PULONG pulLength,
1922 _In_ ULONG ulFlags)
1923 {
1924 TRACE("CM_Enumerate_EnumeratorsW(%lu %p %p %lx)\n",
1925 ulEnumIndex, Buffer, pulLength, ulFlags);
1926
1927 return CM_Enumerate_Enumerators_ExW(ulEnumIndex, Buffer, pulLength,
1928 ulFlags, NULL);
1929 }
1930
1931
1932 /***********************************************************************
1933 * CM_Enumerate_Enumerators_ExA [SETUPAPI.@]
1934 */
1935 CONFIGRET
1936 WINAPI
1937 CM_Enumerate_Enumerators_ExA(
1938 _In_ ULONG ulEnumIndex,
1939 _Out_writes_(*pulLength) PCHAR Buffer,
1940 _Inout_ PULONG pulLength,
1941 _In_ ULONG ulFlags,
1942 _In_opt_ HMACHINE hMachine)
1943 {
1944 WCHAR szBuffer[MAX_DEVICE_ID_LEN];
1945 ULONG ulOrigLength;
1946 ULONG ulLength;
1947 CONFIGRET ret = CR_SUCCESS;
1948
1949 TRACE("CM_Enumerate_Enumerators_ExA(%lu %p %p %lx %p)\n",
1950 ulEnumIndex, Buffer, pulLength, ulFlags, hMachine);
1951
1952 if (Buffer == NULL || pulLength == NULL)
1953 return CR_INVALID_POINTER;
1954
1955 if (ulFlags != 0)
1956 return CR_INVALID_FLAG;
1957
1958 ulOrigLength = *pulLength;
1959 *pulLength = 0;
1960
1961 ulLength = MAX_DEVICE_ID_LEN;
1962 ret = CM_Enumerate_Enumerators_ExW(ulEnumIndex, szBuffer, &ulLength,
1963 ulFlags, hMachine);
1964 if (ret == CR_SUCCESS)
1965 {
1966 if (WideCharToMultiByte(CP_ACP,
1967 0,
1968 szBuffer,
1969 ulLength,
1970 Buffer,
1971 ulOrigLength,
1972 NULL,
1973 NULL) == 0)
1974 ret = CR_FAILURE;
1975 else
1976 *pulLength = lstrlenA(Buffer) + 1;
1977 }
1978
1979 return ret;
1980 }
1981
1982
1983 /***********************************************************************
1984 * CM_Enumerate_Enumerators_ExW [SETUPAPI.@]
1985 */
1986 CONFIGRET
1987 WINAPI
1988 CM_Enumerate_Enumerators_ExW(
1989 _In_ ULONG ulEnumIndex,
1990 _Out_writes_(*pulLength) PWCHAR Buffer,
1991 _Inout_ PULONG pulLength,
1992 _In_ ULONG ulFlags,
1993 _In_opt_ HMACHINE hMachine)
1994 {
1995 RPC_BINDING_HANDLE BindingHandle = NULL;
1996 CONFIGRET ret;
1997
1998 TRACE("CM_Enumerate_Enumerators_ExW(%lu %p %p %lx %p)\n",
1999 ulEnumIndex, Buffer, pulLength, ulFlags, hMachine);
2000
2001 if (Buffer == NULL || pulLength == NULL)
2002 return CR_INVALID_POINTER;
2003
2004 if (ulFlags != 0)
2005 return CR_INVALID_FLAG;
2006
2007 *Buffer = UNICODE_NULL;
2008
2009 if (hMachine != NULL)
2010 {
2011 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2012 if (BindingHandle == NULL)
2013 return CR_FAILURE;
2014 }
2015 else
2016 {
2017 if (!PnpGetLocalHandles(&BindingHandle, NULL))
2018 return CR_FAILURE;
2019 }
2020
2021 RpcTryExcept
2022 {
2023 ret = PNP_EnumerateSubKeys(BindingHandle,
2024 PNP_ENUMERATOR_SUBKEYS,
2025 ulEnumIndex,
2026 Buffer,
2027 *pulLength,
2028 pulLength,
2029 ulFlags);
2030 }
2031 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2032 {
2033 ret = RpcStatusToCmStatus(RpcExceptionCode());
2034 }
2035 RpcEndExcept;
2036
2037 return ret;
2038 }
2039
2040
2041 /***********************************************************************
2042 * CM_Find_Range [SETUPAPI.@]
2043 */
2044 CONFIGRET
2045 WINAPI
2046 CM_Find_Range(
2047 _Out_ PDWORDLONG pullStart,
2048 _In_ DWORDLONG ullStart,
2049 _In_ ULONG ulLength,
2050 _In_ DWORDLONG ullAlignment,
2051 _In_ DWORDLONG ullEnd,
2052 _In_ RANGE_LIST rlh,
2053 _In_ ULONG ulFlags)
2054 {
2055 FIXME("CM_Find_Range(%p %I64u %lu %I64u %I64u %p %lx)\n",
2056 pullStart, ullStart, ulLength, ullAlignment, ullEnd, rlh, ulFlags);
2057
2058 return CR_CALL_NOT_IMPLEMENTED;
2059 }
2060
2061
2062 /***********************************************************************
2063 * CM_First_Range [SETUPAPI.@]
2064 */
2065 CONFIGRET
2066 WINAPI
2067 CM_First_Range(
2068 _In_ RANGE_LIST rlh,
2069 _Out_ PDWORDLONG pullStart,
2070 _Out_ PDWORDLONG pullEnd,
2071 _Out_ PRANGE_ELEMENT preElement,
2072 _In_ ULONG ulFlags)
2073 {
2074 PINTERNAL_RANGE_LIST pRangeList;
2075 PINTERNAL_RANGE pRange;
2076 PLIST_ENTRY ListEntry;
2077 CONFIGRET ret = CR_SUCCESS;
2078
2079 FIXME("CM_First_Range(%p %p %p %p %lx)\n",
2080 rlh, pullStart, pullEnd, preElement, ulFlags);
2081
2082 pRangeList = (PINTERNAL_RANGE_LIST)rlh;
2083
2084 if (!IsValidRangeList(pRangeList))
2085 return CR_INVALID_RANGE_LIST;
2086
2087 if (pullStart == NULL || pullEnd == NULL || preElement == NULL)
2088 return CR_INVALID_POINTER;
2089
2090 if (ulFlags != 0)
2091 return CR_INVALID_FLAG;
2092
2093 /* Lock the range list */
2094 WaitForSingleObject(pRangeList->hMutex, INFINITE);
2095
2096 /* Fail, if the list is empty */
2097 if (IsListEmpty(&pRangeList->ListHead))
2098 {
2099 ret = CR_FAILURE;
2100 goto done;
2101 }
2102
2103 /* Get the first range */
2104 ListEntry = pRangeList->ListHead.Flink;
2105 pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
2106
2107 /* Return the range data */
2108 *pullStart = pRange->ullStart;
2109 *pullEnd = pRange->ullEnd;
2110 *preElement = (RANGE_ELEMENT)pRange;
2111
2112 done:
2113 /* Unlock the range list */
2114 ReleaseMutex(pRangeList->hMutex);
2115
2116 return ret;
2117 }
2118
2119
2120 /***********************************************************************
2121 * CM_Free_Log_Conf [SETUPAPI.@]
2122 */
2123 CONFIGRET
2124 WINAPI
2125 CM_Free_Log_Conf(
2126 _In_ LOG_CONF lcLogConfToBeFreed,
2127 _In_ ULONG ulFlags)
2128 {
2129 TRACE("CM_Free_Log_Conf(%lx %lx)\n",
2130 lcLogConfToBeFreed, ulFlags);
2131
2132 return CM_Free_Log_Conf_Ex(lcLogConfToBeFreed, ulFlags, NULL);
2133 }
2134
2135
2136 /***********************************************************************
2137 * CM_Free_Log_Conf_Ex [SETUPAPI.@]
2138 */
2139 CONFIGRET
2140 WINAPI
2141 CM_Free_Log_Conf_Ex(
2142 _In_ LOG_CONF lcLogConfToBeFreed,
2143 _In_ ULONG ulFlags,
2144 _In_opt_ HMACHINE hMachine)
2145 {
2146 RPC_BINDING_HANDLE BindingHandle = NULL;
2147 HSTRING_TABLE StringTable = NULL;
2148 LPWSTR lpDevInst;
2149 PLOG_CONF_INFO pLogConfInfo;
2150 CONFIGRET ret;
2151
2152 TRACE("CM_Free_Log_Conf_Ex(%lx %lx %p)\n",
2153 lcLogConfToBeFreed, ulFlags, hMachine);
2154
2155 if (!pSetupIsUserAdmin())
2156 return CR_ACCESS_DENIED;
2157
2158 pLogConfInfo = (PLOG_CONF_INFO)lcLogConfToBeFreed;
2159 if (!IsValidLogConf(pLogConfInfo))
2160 return CR_INVALID_LOG_CONF;
2161
2162 if (ulFlags != 0)
2163 return CR_INVALID_FLAG;
2164
2165 if (hMachine != NULL)
2166 {
2167 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2168 if (BindingHandle == NULL)
2169 return CR_FAILURE;
2170
2171 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
2172 if (StringTable == 0)
2173 return CR_FAILURE;
2174 }
2175 else
2176 {
2177 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
2178 return CR_FAILURE;
2179 }
2180
2181 lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
2182 if (lpDevInst == NULL)
2183 return CR_INVALID_DEVNODE;
2184
2185 RpcTryExcept
2186 {
2187 ret = PNP_FreeLogConf(BindingHandle, lpDevInst, pLogConfInfo->ulFlags,
2188 pLogConfInfo->ulTag, 0);
2189 }
2190 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2191 {
2192 ret = RpcStatusToCmStatus(RpcExceptionCode());
2193 }
2194 RpcEndExcept;
2195
2196 return ret;
2197 }
2198
2199
2200 /***********************************************************************
2201 * CM_Free_Log_Conf_Handle [SETUPAPI.@]
2202 */
2203 CONFIGRET
2204 WINAPI
2205 CM_Free_Log_Conf_Handle(
2206 _In_ LOG_CONF lcLogConf)
2207 {
2208 PLOG_CONF_INFO pLogConfInfo;
2209
2210 TRACE("CM_Free_Log_Conf_Handle(%lx)\n", lcLogConf);
2211
2212 pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
2213 if (!IsValidLogConf(pLogConfInfo))
2214 return CR_INVALID_LOG_CONF;
2215
2216 HeapFree(GetProcessHeap(), 0, pLogConfInfo);
2217
2218 return CR_SUCCESS;
2219 }
2220
2221
2222 /***********************************************************************
2223 * CM_Free_Range_List [SETUPAPI.@]
2224 */
2225 CONFIGRET
2226 WINAPI
2227 CM_Free_Range_List(
2228 _In_ RANGE_LIST RangeList,
2229 _In_ ULONG ulFlags)
2230 {
2231 PINTERNAL_RANGE_LIST pRangeList;
2232 PINTERNAL_RANGE pRange;
2233 PLIST_ENTRY ListEntry;
2234
2235 FIXME("CM_Free_Range_List(%p %lx)\n",
2236 RangeList, ulFlags);
2237
2238 pRangeList = (PINTERNAL_RANGE_LIST)RangeList;
2239
2240 if (!IsValidRangeList(pRangeList))
2241 return CR_INVALID_RANGE_LIST;
2242
2243 if (ulFlags != 0)
2244 return CR_INVALID_FLAG;
2245
2246 /* Lock the range list */
2247 WaitForSingleObject(pRangeList->hMutex, INFINITE);
2248
2249 /* Free the list of ranges */
2250 while (!IsListEmpty(&pRangeList->ListHead))
2251 {
2252 ListEntry = RemoveHeadList(&pRangeList->ListHead);
2253 pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
2254 HeapFree(GetProcessHeap(), 0, pRange);
2255 }
2256
2257 /* Unlock the range list */
2258 ReleaseMutex(pRangeList->hMutex);
2259
2260 /* Close the mutex */
2261 CloseHandle(pRangeList->hMutex);
2262
2263 /* Free the range list */
2264 HeapFree(GetProcessHeap(), 0, pRangeList);
2265
2266 return CR_SUCCESS;
2267 }
2268
2269
2270 /***********************************************************************
2271 * CM_Free_Res_Des [SETUPAPI.@]
2272 */
2273 CONFIGRET
2274 WINAPI
2275 CM_Free_Res_Des(
2276 _Out_ PRES_DES prdResDes,
2277 _In_ RES_DES rdResDes,
2278 _In_ ULONG ulFlags)
2279 {
2280 TRACE("CM_Free_Res_Des(%p %p %lx)\n",
2281 prdResDes, rdResDes, ulFlags);
2282
2283 return CM_Free_Res_Des_Ex(prdResDes, rdResDes, ulFlags, NULL);
2284 }
2285
2286
2287 /***********************************************************************
2288 * CM_Free_Res_Des_Ex [SETUPAPI.@]
2289 */
2290 CONFIGRET
2291 WINAPI
2292 CM_Free_Res_Des_Ex(
2293 _Out_ PRES_DES prdResDes,
2294 _In_ RES_DES rdResDes,
2295 _In_ ULONG ulFlags,
2296 _In_opt_ HMACHINE hMachine)
2297 {
2298 FIXME("CM_Free_Res_Des_Ex(%p %p %lx %p)\n",
2299 prdResDes, rdResDes, ulFlags, hMachine);
2300
2301 return CR_CALL_NOT_IMPLEMENTED;
2302 }
2303
2304
2305 /***********************************************************************
2306 * CM_Free_Res_Des_Handle [SETUPAPI.@]
2307 */
2308 CONFIGRET
2309 WINAPI
2310 CM_Free_Res_Des_Handle(
2311 _In_ RES_DES rdResDes)
2312 {
2313 FIXME("CM_Free_Res_Des_Handle(%p)\n", rdResDes);
2314
2315 return CR_CALL_NOT_IMPLEMENTED;
2316 }
2317
2318
2319 /***********************************************************************
2320 * CM_Free_Resource_Conflict_Handle [SETUPAPI.@]
2321 */
2322 CONFIGRET
2323 WINAPI
2324 CM_Free_Resource_Conflict_Handle(
2325 _In_ CONFLICT_LIST clConflictList)
2326 {
2327 PCONFLICT_DATA pConflictData;
2328
2329 FIXME("CM_Free_Resource_Conflict_Handle(%p)\n",
2330 clConflictList);
2331
2332 pConflictData = (PCONFLICT_DATA)clConflictList;
2333 if (!IsValidConflictData(pConflictData))
2334 return CR_INVALID_CONFLICT_LIST;
2335
2336 if (pConflictData->pConflictList != NULL)
2337 MyFree(pConflictData->pConflictList);
2338
2339 MyFree(pConflictData);
2340
2341 return CR_SUCCESS;
2342 }
2343
2344
2345 /***********************************************************************
2346 * CM_Get_Child [SETUPAPI.@]
2347 */
2348 CONFIGRET
2349 WINAPI
2350 CM_Get_Child(
2351 _Out_ PDEVINST pdnDevInst,
2352 _In_ DEVINST dnDevInst,
2353 _In_ ULONG ulFlags)
2354 {
2355 TRACE("CM_Get_Child(%p %p %lx)\n",
2356 pdnDevInst, dnDevInst, ulFlags);
2357
2358 return CM_Get_Child_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
2359 }
2360
2361
2362 /***********************************************************************
2363 * CM_Get_Child_Ex [SETUPAPI.@]
2364 */
2365 CONFIGRET
2366 WINAPI
2367 CM_Get_Child_Ex(
2368 _Out_ PDEVINST pdnDevInst,
2369 _In_ DEVINST dnDevInst,
2370 _In_ ULONG ulFlags,
2371 _In_opt_ HMACHINE hMachine)
2372 {
2373 WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
2374 RPC_BINDING_HANDLE BindingHandle = NULL;
2375 HSTRING_TABLE StringTable = NULL;
2376 LPWSTR lpDevInst;
2377 DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
2378 CONFIGRET ret;
2379
2380 TRACE("CM_Get_Child_Ex(%p %lx %lx %p)\n",
2381 pdnDevInst, dnDevInst, ulFlags, hMachine);
2382
2383 if (pdnDevInst == NULL)
2384 return CR_INVALID_POINTER;
2385
2386 if (dnDevInst == 0)
2387 return CR_INVALID_DEVINST;
2388
2389 if (ulFlags != 0)
2390 return CR_INVALID_FLAG;
2391
2392 *pdnDevInst = -1;
2393
2394 if (hMachine != NULL)
2395 {
2396 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2397 if (BindingHandle == NULL)
2398 return CR_FAILURE;
2399
2400 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
2401 if (StringTable == 0)
2402 return CR_FAILURE;
2403 }
2404 else
2405 {
2406 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
2407 return CR_FAILURE;
2408 }
2409
2410 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
2411 if (lpDevInst == NULL)
2412 return CR_INVALID_DEVNODE;
2413
2414 RpcTryExcept
2415 {
2416 ret = PNP_GetRelatedDeviceInstance(BindingHandle,
2417 PNP_GET_CHILD_DEVICE_INSTANCE,
2418 lpDevInst,
2419 szRelatedDevInst,
2420 &dwLength,
2421 0);
2422 }
2423 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2424 {
2425 ret = RpcStatusToCmStatus(RpcExceptionCode());
2426 }
2427 RpcEndExcept;
2428
2429 if (ret != CR_SUCCESS)
2430 return ret;
2431
2432 TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
2433
2434 dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
2435 if (dwIndex == -1)
2436 return CR_FAILURE;
2437
2438 *pdnDevInst = dwIndex;
2439
2440 return CR_SUCCESS;
2441 }
2442
2443
2444 /***********************************************************************
2445 * CM_Get_Class_Key_NameA [SETUPAPI.@]
2446 */
2447 CONFIGRET
2448 WINAPI
2449 CM_Get_Class_Key_NameA(
2450 _In_ LPGUID ClassGuid,
2451 _Out_writes_opt_(*pulLength) LPSTR pszKeyName,
2452 _Inout_ PULONG pulLength,
2453 _In_ ULONG ulFlags)
2454 {
2455 TRACE("CM_Get_Class_Key_NameA(%p %p %p %lx)\n",
2456 ClassGuid, pszKeyName, pulLength, ulFlags);
2457
2458 return CM_Get_Class_Key_Name_ExA(ClassGuid, pszKeyName, pulLength,
2459 ulFlags, NULL);
2460 }
2461
2462
2463 /***********************************************************************
2464 * CM_Get_Class_Key_NameW [SETUPAPI.@]
2465 */
2466 CONFIGRET
2467 WINAPI
2468 CM_Get_Class_Key_NameW(
2469 _In_ LPGUID ClassGuid,
2470 _Out_writes_opt_(*pulLength) LPWSTR pszKeyName,
2471 _Inout_ PULONG pulLength,
2472 _In_ ULONG ulFlags)
2473 {
2474 TRACE("CM_Get_Class_Key_NameW(%p %p %p %lx)\n",
2475 ClassGuid, pszKeyName, pulLength, ulFlags);
2476
2477 return CM_Get_Class_Key_Name_ExW(ClassGuid, pszKeyName, pulLength,
2478 ulFlags, NULL);
2479 }
2480
2481
2482 /***********************************************************************
2483 * CM_Get_Class_Key_Name_ExA [SETUPAPI.@]
2484 */
2485 CONFIGRET
2486 WINAPI
2487 CM_Get_Class_Key_Name_ExA(
2488 _In_ LPGUID ClassGuid,
2489 _Out_writes_opt_(*pulLength) LPSTR pszKeyName,
2490 _Inout_ PULONG pulLength,
2491 _In_ ULONG ulFlags,
2492 _In_opt_ HMACHINE hMachine)
2493 {
2494 WCHAR szBuffer[MAX_GUID_STRING_LEN];
2495 CONFIGRET ret = CR_SUCCESS;
2496 ULONG ulLength;
2497 ULONG ulOrigLength;
2498
2499 TRACE("CM_Get_Class_Key_Name_ExA(%p %p %p %lx %p)\n",
2500 ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
2501
2502 if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
2503 return CR_INVALID_POINTER;
2504
2505 ulOrigLength = *pulLength;
2506 *pulLength = 0;
2507
2508 ulLength = MAX_GUID_STRING_LEN;
2509 ret = CM_Get_Class_Key_Name_ExW(ClassGuid, szBuffer, &ulLength,
2510 ulFlags, hMachine);
2511 if (ret == CR_SUCCESS)
2512 {
2513 if (WideCharToMultiByte(CP_ACP,
2514 0,
2515 szBuffer,
2516 ulLength,
2517 pszKeyName,
2518 ulOrigLength,
2519 NULL,
2520 NULL) == 0)
2521 ret = CR_FAILURE;
2522 else
2523 *pulLength = lstrlenA(pszKeyName) + 1;
2524 }
2525
2526 return CR_SUCCESS;
2527 }
2528
2529
2530 /***********************************************************************
2531 * CM_Get_Class_Key_Name_ExW [SETUPAPI.@]
2532 */
2533 CONFIGRET
2534 WINAPI
2535 CM_Get_Class_Key_Name_ExW(
2536 _In_ LPGUID ClassGuid,
2537 _Out_writes_opt_(*pulLength) LPWSTR pszKeyName,
2538 _Inout_ PULONG pulLength,
2539 _In_ ULONG ulFlags,
2540 _In_opt_ HMACHINE hMachine)
2541 {
2542 TRACE("CM_Get_Class_Key_Name_ExW(%p %p %p %lx %p)\n",
2543 ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
2544
2545 if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
2546 return CR_INVALID_POINTER;
2547
2548 if (ulFlags != 0)
2549 return CR_INVALID_FLAG;
2550
2551 if (*pulLength < MAX_GUID_STRING_LEN)
2552 {
2553 *pulLength = 0;
2554 return CR_BUFFER_SMALL;
2555 }
2556
2557 if (!GuidToString(ClassGuid, pszKeyName))
2558 return CR_INVALID_DATA;
2559
2560 *pulLength = MAX_GUID_STRING_LEN;
2561
2562 return CR_SUCCESS;
2563 }
2564
2565
2566 /***********************************************************************
2567 * CM_Get_Class_NameA [SETUPAPI.@]
2568 */
2569 CONFIGRET
2570 WINAPI
2571 CM_Get_Class_NameA(
2572 _In_ LPGUID ClassGuid,
2573 _Out_writes_opt_(*pulLength) PCHAR Buffer,
2574 _Inout_ PULONG pulLength,
2575 _In_ ULONG ulFlags)
2576 {
2577 TRACE("CM_Get_Class_NameA(%p %p %p %lx)\n",
2578 ClassGuid, Buffer, pulLength, ulFlags);
2579
2580 return CM_Get_Class_Name_ExA(ClassGuid, Buffer, pulLength, ulFlags,
2581 NULL);
2582 }
2583
2584
2585 /***********************************************************************
2586 * CM_Get_Class_NameW [SETUPAPI.@]
2587 */
2588 CONFIGRET
2589 WINAPI
2590 CM_Get_Class_NameW(
2591 _In_ LPGUID ClassGuid,
2592 _Out_writes_opt_(*pulLength) PWCHAR Buffer,
2593 _Inout_ PULONG pulLength,
2594 _In_ ULONG ulFlags)
2595 {
2596 TRACE("CM_Get_Class_NameW(%p %p %p %lx)\n",
2597 ClassGuid, Buffer, pulLength, ulFlags);
2598
2599 return CM_Get_Class_Name_ExW(ClassGuid, Buffer, pulLength, ulFlags,
2600 NULL);
2601 }
2602
2603
2604 /***********************************************************************
2605 * CM_Get_Class_Name_ExA [SETUPAPI.@]
2606 */
2607 CONFIGRET
2608 WINAPI
2609 CM_Get_Class_Name_ExA(
2610 _In_ LPGUID ClassGuid,
2611 _Out_writes_opt_(*pulLength) PCHAR Buffer,
2612 _Inout_ PULONG pulLength,
2613 _In_ ULONG ulFlags,
2614 _In_opt_ HMACHINE hMachine)
2615 {
2616 WCHAR szBuffer[MAX_CLASS_NAME_LEN];
2617 CONFIGRET ret = CR_SUCCESS;
2618 ULONG ulLength;
2619 ULONG ulOrigLength;
2620
2621 TRACE("CM_Get_Class_Name_ExA(%p %p %p %lx %p)\n",
2622 ClassGuid, Buffer, pulLength, ulFlags, hMachine);
2623
2624 if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
2625 return CR_INVALID_POINTER;
2626
2627 ulOrigLength = *pulLength;
2628 *pulLength = 0;
2629
2630 ulLength = MAX_CLASS_NAME_LEN;
2631 ret = CM_Get_Class_Name_ExW(ClassGuid, szBuffer, &ulLength,
2632 ulFlags, hMachine);
2633 if (ret == CR_SUCCESS)
2634 {
2635 if (WideCharToMultiByte(CP_ACP,
2636 0,
2637 szBuffer,
2638 ulLength,
2639 Buffer,
2640 ulOrigLength,
2641 NULL,
2642 NULL) == 0)
2643 ret = CR_FAILURE;
2644 else
2645 *pulLength = lstrlenA(Buffer) + 1;
2646 }
2647
2648 return ret;
2649 }
2650
2651
2652 /***********************************************************************
2653 * CM_Get_Class_Name_ExW [SETUPAPI.@]
2654 */
2655 CONFIGRET
2656 WINAPI
2657 CM_Get_Class_Name_ExW(
2658 _In_ LPGUID ClassGuid,
2659 _Out_writes_opt_(*pulLength) PWCHAR Buffer,
2660 _Inout_ PULONG pulLength,
2661 _In_ ULONG ulFlags,
2662 _In_opt_ HMACHINE hMachine)
2663 {
2664 WCHAR szGuidString[MAX_GUID_STRING_LEN];
2665 RPC_BINDING_HANDLE BindingHandle = NULL;
2666 CONFIGRET ret;
2667
2668 TRACE("CM_Get_Class_Name_ExW(%p %p %p %lx %p\n",
2669 ClassGuid, Buffer, pulLength, ulFlags, hMachine);
2670
2671 if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
2672 return CR_INVALID_POINTER;
2673
2674 if (ulFlags != 0)
2675 return CR_INVALID_FLAG;
2676
2677 if (!GuidToString(ClassGuid, szGuidString))
2678 return CR_INVALID_DATA;
2679
2680 TRACE("Guid %s\n", debugstr_w(szGuidString));
2681
2682 if (hMachine != NULL)
2683 {
2684 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2685 if (BindingHandle == NULL)
2686 return CR_FAILURE;
2687 }
2688 else
2689 {
2690 if (!PnpGetLocalHandles(&BindingHandle, NULL))
2691 return CR_FAILURE;
2692 }
2693
2694 RpcTryExcept
2695 {
2696 ret = PNP_GetClassName(BindingHandle,
2697 szGuidString,
2698 Buffer,
2699 pulLength,
2700 ulFlags);
2701 }
2702 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2703 {
2704 ret = RpcStatusToCmStatus(RpcExceptionCode());
2705 }
2706 RpcEndExcept;
2707
2708 return ret;
2709 }
2710
2711
2712 /***********************************************************************
2713 * CM_Get_Class_Registry_PropertyA [SETUPAPI.@]
2714 */
2715 CONFIGRET
2716 WINAPI
2717 CM_Get_Class_Registry_PropertyA(
2718 LPGUID ClassGuid,
2719 ULONG ulProperty,
2720 PULONG pulRegDataType,
2721 PVOID Buffer,
2722 PULONG pulLength,
2723 ULONG ulFlags,
2724 HMACHINE hMachine)
2725 {
2726 PWSTR BufferW = NULL;
2727 ULONG ulLength = 0;
2728 ULONG ulType;
2729 CONFIGRET ret;
2730
2731 TRACE("CM_Get_Class_Registry_PropertyA(%p %lu %p %p %p %lx %p)\n",
2732 ClassGuid, ulProperty, pulRegDataType, Buffer, pulLength,
2733 ulFlags, hMachine);
2734
2735 if (pulLength == NULL)
2736 return CR_INVALID_POINTER;
2737
2738 if (ulProperty < CM_CRP_MIN || ulProperty > CM_CRP_MAX)
2739 return CR_INVALID_PROPERTY;
2740
2741 ulType = GetRegistryPropertyType(ulProperty);
2742 if (ulType == REG_SZ || ulType == REG_MULTI_SZ)
2743 {
2744 /* Get the required buffer size */
2745 ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2746 NULL, &ulLength, ulFlags, hMachine);
2747 if (ret != CR_BUFFER_SMALL)
2748 return ret;
2749
2750 /* Allocate the unicode buffer */
2751 BufferW = HeapAlloc(GetProcessHeap(), 0, ulLength);
2752 if (BufferW == NULL)
2753 return CR_OUT_OF_MEMORY;
2754
2755 /* Get the property */
2756 ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2757 BufferW, &ulLength, ulFlags, hMachine);
2758 if (ret != CR_SUCCESS)
2759 {
2760 HeapFree(GetProcessHeap(), 0, BufferW);
2761 return ret;
2762 }
2763
2764 /* Do W->A conversion */
2765 *pulLength = WideCharToMultiByte(CP_ACP,
2766 0,
2767 BufferW,
2768 lstrlenW(BufferW) + 1,
2769 Buffer,
2770 *pulLength,
2771 NULL,
2772 NULL);
2773
2774 /* Release the unicode buffer */
2775 HeapFree(GetProcessHeap(), 0, BufferW);
2776
2777 if (*pulLength == 0)
2778 ret = CR_FAILURE;
2779 }
2780 else
2781 {
2782 /* Get the property */
2783 ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2784 Buffer, pulLength, ulFlags, hMachine);
2785 }
2786
2787 return ret;
2788 }
2789
2790
2791 /***********************************************************************
2792 * CM_Get_Class_Registry_PropertyW [SETUPAPI.@]
2793 */
2794 CONFIGRET
2795 WINAPI
2796 CM_Get_Class_Registry_PropertyW(
2797 LPGUID ClassGuid,
2798 ULONG ulProperty,
2799 PULONG pulRegDataType,
2800 PVOID Buffer,
2801 PULONG pulLength,
2802 ULONG ulFlags,
2803 HMACHINE hMachine)
2804 {
2805 RPC_BINDING_HANDLE BindingHandle = NULL;
2806 WCHAR szGuidString[PNP_MAX_GUID_STRING_LEN + 1];
2807 ULONG ulType = 0;
2808 ULONG ulTransferLength = 0;
2809 CONFIGRET ret;
2810
2811 TRACE("CM_Get_Class_Registry_PropertyW(%p %lu %p %p %p %lx %p)\n",
2812 ClassGuid, ulProperty, pulRegDataType, Buffer, pulLength,
2813 ulFlags, hMachine);
2814
2815 if (ClassGuid == NULL || pulLength == NULL)
2816 return CR_INVALID_POINTER;
2817
2818 if (ulFlags != 0)
2819 return CR_INVALID_FLAG;
2820
2821 if (pSetupStringFromGuid(ClassGuid,
2822 szGuidString,
2823 PNP_MAX_GUID_STRING_LEN) != 0)
2824 return CR_INVALID_DATA;
2825
2826 if (ulProperty < CM_CRP_MIN || ulProperty > CM_CRP_MAX)
2827 return CR_INVALID_PROPERTY;
2828
2829 if (hMachine != NULL)
2830 {
2831 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2832 if (BindingHandle == NULL)
2833 return CR_FAILURE;
2834 }
2835 else
2836 {
2837 if (!PnpGetLocalHandles(&BindingHandle, NULL))
2838 return CR_FAILURE;
2839 }
2840
2841 ulTransferLength = *pulLength;
2842
2843 RpcTryExcept
2844 {
2845 ret = PNP_GetClassRegProp(BindingHandle,
2846 szGuidString,
2847 ulProperty,
2848 &ulType,
2849 Buffer,
2850 &ulTransferLength,
2851 pulLength,
2852 ulFlags);
2853 }
2854 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2855 {
2856 ret = RpcStatusToCmStatus(RpcExceptionCode());
2857 }
2858 RpcEndExcept;
2859
2860 if (ret == CR_SUCCESS)
2861 {
2862 if (pulRegDataType != NULL)
2863 *pulRegDataType = ulType;
2864 }
2865
2866 return ret;
2867 }
2868
2869
2870 /***********************************************************************
2871 * CM_Get_Depth [SETUPAPI.@]
2872 */
2873 CONFIGRET
2874 WINAPI
2875 CM_Get_Depth(
2876 _Out_ PULONG pulDepth,
2877 _In_ DEVINST dnDevInst,
2878 _In_ ULONG ulFlags)
2879 {
2880 TRACE("CM_Get_Depth(%p %lx %lx)\n",
2881 pulDepth, dnDevInst, ulFlags);
2882
2883 return CM_Get_Depth_Ex(pulDepth, dnDevInst, ulFlags, NULL);
2884 }
2885
2886
2887 /***********************************************************************
2888 * CM_Get_Depth_Ex [SETUPAPI.@]
2889 */
2890 CONFIGRET
2891 WINAPI
2892 CM_Get_Depth_Ex(
2893 _Out_ PULONG pulDepth,
2894 _In_ DEVINST dnDevInst,
2895 _In_ ULONG ulFlags,
2896 _In_opt_ HMACHINE hMachine)
2897 {
2898 RPC_BINDING_HANDLE BindingHandle = NULL;
2899 HSTRING_TABLE StringTable = NULL;
2900 LPWSTR lpDevInst;
2901 CONFIGRET ret;
2902
2903 TRACE("CM_Get_Depth_Ex(%p %lx %lx %p)\n",
2904 pulDepth, dnDevInst, ulFlags, hMachine);
2905
2906 if (pulDepth == NULL)
2907 return CR_INVALID_POINTER;
2908
2909 if (dnDevInst == 0)
2910 return CR_INVALID_DEVINST;
2911
2912 if (ulFlags != 0)
2913 return CR_INVALID_FLAG;
2914
2915 if (hMachine != NULL)
2916 {
2917 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2918 if (BindingHandle == NULL)
2919 return CR_FAILURE;
2920
2921 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
2922 if (StringTable == 0)
2923 return CR_FAILURE;
2924 }
2925 else
2926 {
2927 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
2928 return CR_FAILURE;
2929 }
2930
2931 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
2932 if (lpDevInst == NULL)
2933 return CR_INVALID_DEVNODE;
2934
2935 RpcTryExcept
2936 {
2937 ret = PNP_GetDepth(BindingHandle,
2938 lpDevInst,
2939 pulDepth,
2940 ulFlags);
2941 }
2942 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2943 {
2944 ret = RpcStatusToCmStatus(RpcExceptionCode());
2945 }
2946 RpcEndExcept;
2947
2948 return ret;
2949 }
2950
2951
2952 /***********************************************************************
2953 * CM_Get_DevNode_Custom_PropertyA [SETUPAPI.@]
2954 */
2955 CONFIGRET
2956 WINAPI
2957 CM_Get_DevNode_Custom_PropertyA(
2958 _In_ DEVINST dnDevInst,
2959 _In_ PCSTR pszCustomPropertyName,
2960 _Out_opt_ PULONG pulRegDataType,
2961 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
2962 _Inout_ PULONG pulLength,
2963 _In_ ULONG ulFlags)
2964 {
2965 TRACE("CM_Get_DevNode_Custom_PropertyA(%lx %s %p %p %p %lx)\n",
2966 dnDevInst, pszCustomPropertyName, pulRegDataType,
2967 Buffer, pulLength, ulFlags);
2968
2969 return CM_Get_DevNode_Custom_Property_ExA(dnDevInst, pszCustomPropertyName,
2970 pulRegDataType, Buffer,
2971 pulLength, ulFlags, NULL);
2972 }
2973
2974
2975 /***********************************************************************
2976 * CM_Get_DevNode_Custom_PropertyW [SETUPAPI.@]
2977 */
2978 CONFIGRET
2979 WINAPI
2980 CM_Get_DevNode_Custom_PropertyW(
2981 _In_ DEVINST dnDevInst,
2982 _In_ PCWSTR pszCustomPropertyName,
2983 _Out_opt_ PULONG pulRegDataType,
2984 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
2985 _Inout_ PULONG pulLength,
2986 _In_ ULONG ulFlags)
2987 {
2988 TRACE("CM_Get_DevNode_Custom_PropertyW(%lx %s %p %p %p %lx)\n",
2989 dnDevInst, debugstr_w(pszCustomPropertyName), pulRegDataType,
2990 Buffer, pulLength, ulFlags);
2991
2992 return CM_Get_DevNode_Custom_Property_ExW(dnDevInst, pszCustomPropertyName,
2993 pulRegDataType, Buffer,
2994 pulLength, ulFlags, NULL);
2995 }
2996
2997
2998 /***********************************************************************
2999 * CM_Get_DevNode_Custom_Property_ExA [SETUPAPI.@]
3000 */
3001 CONFIGRET
3002 WINAPI
3003 CM_Get_DevNode_Custom_Property_ExA(
3004 _In_ DEVINST dnDevInst,
3005 _In_ PCSTR pszCustomPropertyName,
3006 _Out_opt_ PULONG pulRegDataType,
3007 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3008 _Inout_ PULONG pulLength,
3009 _In_ ULONG ulFlags,
3010 _In_opt_ HMACHINE hMachine)
3011 {
3012 LPWSTR pszPropertyNameW = NULL;
3013 PVOID BufferW;
3014 ULONG ulLengthW;
3015 ULONG ulDataType = REG_NONE;
3016 CONFIGRET ret;
3017
3018 TRACE("CM_Get_DevNode_Custom_Property_ExA(%lx %s %p %p %p %lx %p)\n",
3019 dnDevInst, pszCustomPropertyName, pulRegDataType,
3020 Buffer, pulLength, ulFlags, hMachine);
3021
3022 if (!pulLength)
3023 return CR_INVALID_POINTER;
3024
3025 ulLengthW = *pulLength * sizeof(WCHAR);
3026 BufferW = HeapAlloc(GetProcessHeap(), 0, ulLengthW);
3027 if (!BufferW)
3028 return CR_OUT_OF_MEMORY;
3029
3030 pszPropertyNameW = pSetupMultiByteToUnicode(pszCustomPropertyName,
3031 CP_ACP);
3032 if (pszPropertyNameW == NULL)
3033 {
3034 HeapFree(GetProcessHeap(), 0, BufferW);
3035 return CR_OUT_OF_MEMORY;
3036 }
3037
3038 ret = CM_Get_DevNode_Custom_Property_ExW(dnDevInst,
3039 pszPropertyNameW,
3040 &ulDataType,
3041 BufferW,
3042 &ulLengthW,
3043 ulFlags,
3044 hMachine);
3045 if (ret == CR_SUCCESS)
3046 {
3047 if (ulDataType == REG_SZ ||
3048 ulDataType == REG_EXPAND_SZ ||
3049 ulDataType == REG_MULTI_SZ)
3050 {
3051 /* Do W->A conversion */
3052 *pulLength = WideCharToMultiByte(CP_ACP,
3053 0,
3054 BufferW,
3055 lstrlenW(BufferW) + 1,
3056 Buffer,
3057 *pulLength,
3058 NULL,
3059 NULL);
3060 if (*pulLength == 0)
3061 ret = CR_FAILURE;
3062 }
3063 else
3064 {
3065 /* Directly copy the value */
3066 if (ulLengthW <= *pulLength)
3067 memcpy(Buffer, BufferW, ulLengthW);
3068 else
3069 {
3070 *pulLength = ulLengthW;
3071 ret = CR_BUFFER_SMALL;
3072 }
3073 }
3074 }
3075
3076 if (pulRegDataType)
3077 *pulRegDataType = ulDataType;
3078
3079 HeapFree(GetProcessHeap(), 0, BufferW);
3080 MyFree(pszPropertyNameW);
3081
3082 return ret;
3083 }
3084
3085
3086 /***********************************************************************
3087 * CM_Get_DevNode_Custom_Property_ExW [SETUPAPI.@]
3088 */
3089 CONFIGRET
3090 WINAPI
3091 CM_Get_DevNode_Custom_Property_ExW(
3092 _In_ DEVINST dnDevInst,
3093 _In_ PCWSTR pszCustomPropertyName,
3094 _Out_opt_ PULONG pulRegDataType,
3095 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3096 _Inout_ PULONG pulLength,
3097 _In_ ULONG ulFlags,
3098 _In_opt_ HMACHINE hMachine)
3099 {
3100 RPC_BINDING_HANDLE BindingHandle = NULL;
3101 HSTRING_TABLE StringTable = NULL;
3102 LPWSTR lpDevInst;
3103 ULONG ulDataType = REG_NONE;
3104 ULONG ulTransferLength;
3105 CONFIGRET ret = CR_SUCCESS;
3106
3107 TRACE("CM_Get_DevNode_Custom_Property_ExW(%lx %s %p %p %p %lx %p)\n",
3108 dnDevInst, debugstr_w(pszCustomPropertyName), pulRegDataType,
3109 Buffer, pulLength, ulFlags, hMachine);
3110
3111 if (dnDevInst == 0)
3112 return CR_INVALID_DEVNODE;
3113
3114 if (pszCustomPropertyName == NULL ||
3115 pulLength == NULL ||
3116 *pulLength == 0)
3117 return CR_INVALID_POINTER;
3118
3119 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
3120 return CR_INVALID_FLAG;
3121
3122 if (hMachine != NULL)
3123 {
3124 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3125 if (BindingHandle == NULL)
3126 return CR_FAILURE;
3127
3128 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3129 if (StringTable == 0)
3130 return CR_FAILURE;
3131 }
3132 else
3133 {
3134 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3135 return CR_FAILURE;
3136 }
3137
3138 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3139 if (lpDevInst == NULL)
3140 return CR_INVALID_DEVNODE;
3141
3142 ulTransferLength = *pulLength;
3143
3144 RpcTryExcept
3145 {
3146 ret = PNP_GetCustomDevProp(BindingHandle,
3147 lpDevInst,
3148 (LPWSTR)pszCustomPropertyName,
3149 &ulDataType,
3150 Buffer,
3151 &ulTransferLength,
3152 pulLength,
3153 ulFlags);
3154 }
3155 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3156 {
3157 ret = RpcStatusToCmStatus(RpcExceptionCode());
3158 }
3159 RpcEndExcept;
3160
3161 if (ret == CR_SUCCESS)
3162 {
3163 if (pulRegDataType != NULL)
3164 *pulRegDataType = ulDataType;
3165 }
3166
3167 return ret;
3168 }
3169
3170
3171 /***********************************************************************
3172 * CM_Get_DevNode_Registry_PropertyA [SETUPAPI.@]
3173 */
3174 CONFIGRET
3175 WINAPI
3176 CM_Get_DevNode_Registry_PropertyA(
3177 _In_ DEVINST dnDevInst,
3178 _In_ ULONG ulProperty,
3179 _Out_opt_ PULONG pulRegDataType,
3180 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3181 _Inout_ PULONG pulLength,
3182 _In_ ULONG ulFlags)
3183 {
3184 TRACE("CM_Get_DevNode_Registry_PropertyA(%lx %lu %p %p %p %lx)\n",
3185 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
3186
3187 return CM_Get_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
3188 pulRegDataType, Buffer,
3189 pulLength, ulFlags, NULL);
3190 }
3191
3192
3193 /***********************************************************************
3194 * CM_Get_DevNode_Registry_PropertyW [SETUPAPI.@]
3195 */
3196 CONFIGRET
3197 WINAPI
3198 CM_Get_DevNode_Registry_PropertyW(
3199 _In_ DEVINST dnDevInst,
3200 _In_ ULONG ulProperty,
3201 _Out_opt_ PULONG pulRegDataType,
3202 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3203 _Inout_ PULONG pulLength,
3204 _In_ ULONG ulFlags)
3205 {
3206 TRACE("CM_Get_DevNode_Registry_PropertyW(%lx %lu %p %p %p %lx)\n",
3207 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
3208
3209 return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
3210 pulRegDataType, Buffer,
3211 pulLength, ulFlags, NULL);
3212 }
3213
3214
3215 /***********************************************************************
3216 * CM_Get_DevNode_Registry_Property_ExA [SETUPAPI.@]
3217 */
3218 CONFIGRET
3219 WINAPI
3220 CM_Get_DevNode_Registry_Property_ExA(
3221 _In_ DEVINST dnDevInst,
3222 _In_ ULONG ulProperty,
3223 _Out_opt_ PULONG pulRegDataType,
3224 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3225 _Inout_ PULONG pulLength,
3226 _In_ ULONG ulFlags,
3227 _In_opt_ HMACHINE hMachine)
3228 {
3229 PVOID BufferW;
3230 ULONG LengthW;
3231 ULONG ulDataType = REG_NONE;
3232 CONFIGRET ret;
3233
3234 TRACE("CM_Get_DevNode_Registry_Property_ExA(%lx %lu %p %p %p %lx %p)\n",
3235 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
3236 ulFlags, hMachine);
3237
3238 if (!pulLength)
3239 return CR_INVALID_POINTER;
3240
3241 LengthW = *pulLength * sizeof(WCHAR);
3242 BufferW = HeapAlloc(GetProcessHeap(), 0, LengthW);
3243
3244 if (!BufferW)
3245 return CR_OUT_OF_MEMORY;
3246
3247 ret = CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
3248 ulProperty,
3249 &ulDataType,
3250 BufferW,
3251 &LengthW,
3252 ulFlags,
3253 hMachine);
3254
3255 if (ret == CR_SUCCESS)
3256 {
3257 if (ulDataType == REG_SZ ||
3258 ulDataType == REG_EXPAND_SZ ||
3259 ulDataType == REG_MULTI_SZ)
3260 {
3261 /* Do W->A conversion */
3262 *pulLength = WideCharToMultiByte(CP_ACP,
3263 0,
3264 BufferW,
3265 lstrlenW(BufferW) + 1,
3266 Buffer,
3267 *pulLength,
3268 NULL,
3269 NULL);
3270 if (*pulLength == 0)
3271 ret = CR_FAILURE;
3272 }
3273 else
3274 {
3275 /* Directly copy the value */
3276 if (LengthW <= *pulLength)
3277 memcpy(Buffer, BufferW, LengthW);
3278 else
3279 {
3280 *pulLength = LengthW;
3281 ret = CR_BUFFER_SMALL;
3282 }
3283 }
3284 }
3285
3286 if (pulRegDataType)
3287 *pulRegDataType = ulDataType;
3288
3289 HeapFree(GetProcessHeap(), 0, BufferW);
3290
3291 return ret;
3292 }
3293
3294
3295 /***********************************************************************
3296 * CM_Get_DevNode_Registry_Property_ExW [SETUPAPI.@]
3297 */
3298 CONFIGRET
3299 WINAPI
3300 CM_Get_DevNode_Registry_Property_ExW(
3301 _In_ DEVINST dnDevInst,
3302 _In_ ULONG ulProperty,
3303 _Out_opt_ PULONG pulRegDataType,
3304 _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3305 _Inout_ PULONG pulLength,
3306 _In_ ULONG ulFlags,
3307 _In_opt_ HMACHINE hMachine)
3308 {
3309 RPC_BINDING_HANDLE BindingHandle = NULL;
3310 HSTRING_TABLE StringTable = NULL;
3311 CONFIGRET ret = CR_SUCCESS;
3312 LPWSTR lpDevInst;
3313 ULONG ulDataType = REG_NONE;
3314 ULONG ulTransferLength = 0;
3315
3316 TRACE("CM_Get_DevNode_Registry_Property_ExW(%lx %lu %p %p %p %lx %p)\n",
3317 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
3318 ulFlags, hMachine);
3319
3320 if (dnDevInst == 0)
3321 return CR_INVALID_DEVNODE;
3322
3323 if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
3324 return CR_INVALID_PROPERTY;
3325
3326 /* pulRegDataType is optional */
3327
3328 /* Buffer is optional */
3329
3330 if (pulLength == NULL)
3331 return CR_INVALID_POINTER;
3332
3333 if (*pulLength == 0)
3334 return CR_INVALID_POINTER;
3335
3336 if (ulFlags != 0)
3337 return CR_INVALID_FLAG;
3338
3339 if (hMachine != NULL)
3340 {
3341 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3342 if (BindingHandle == NULL)
3343 return CR_FAILURE;
3344
3345 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3346 if (StringTable == 0)
3347 return CR_FAILURE;
3348 }
3349 else
3350 {
3351 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3352 return CR_FAILURE;
3353 }
3354
3355 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3356 if (lpDevInst == NULL)
3357 return CR_INVALID_DEVNODE;
3358
3359 ulTransferLength = *pulLength;
3360
3361 RpcTryExcept
3362 {
3363 ret = PNP_GetDeviceRegProp(BindingHandle,
3364 lpDevInst,
3365 ulProperty,
3366 &ulDataType,
3367 Buffer,
3368 &ulTransferLength,
3369 pulLength,
3370 ulFlags);
3371 }
3372 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3373 {
3374 ret = RpcStatusToCmStatus(RpcExceptionCode());
3375 }
3376 RpcEndExcept;
3377
3378 if (ret == CR_SUCCESS)
3379 {
3380 if (pulRegDataType != NULL)
3381 *pulRegDataType = ulDataType;
3382 }
3383
3384 return ret;
3385 }
3386
3387
3388 /***********************************************************************
3389 * CM_Get_DevNode_Status [SETUPAPI.@]
3390 */
3391 CONFIGRET
3392 WINAPI
3393 CM_Get_DevNode_Status(
3394 _Out_ PULONG pulStatus,
3395 _Out_ PULONG pulProblemNumber,
3396 _In_ DEVINST dnDevInst,
3397 _In_ ULONG ulFlags)
3398 {
3399 TRACE("CM_Get_DevNode_Status(%p %p %lx %lx)\n",
3400 pulStatus, pulProblemNumber, dnDevInst, ulFlags);
3401
3402 return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber, dnDevInst,
3403 ulFlags, NULL);
3404 }
3405
3406
3407 /***********************************************************************
3408 * CM_Get_DevNode_Status_Ex [SETUPAPI.@]
3409 */
3410 CONFIGRET
3411 WINAPI
3412 CM_Get_DevNode_Status_Ex(
3413 _Out_ PULONG pulStatus,
3414 _Out_ PULONG pulProblemNumber,
3415 _In_ DEVINST dnDevInst,
3416 _In_ ULONG ulFlags,
3417 _In_opt_ HMACHINE hMachine)
3418 {
3419 RPC_BINDING_HANDLE BindingHandle = NULL;
3420 HSTRING_TABLE StringTable = NULL;
3421 LPWSTR lpDevInst;
3422 CONFIGRET ret;
3423
3424 TRACE("CM_Get_DevNode_Status_Ex(%p %p %lx %lx %p)\n",
3425 pulStatus, pulProblemNumber, dnDevInst, ulFlags, hMachine);
3426
3427 if (pulStatus == NULL || pulProblemNumber == NULL)
3428 return CR_INVALID_POINTER;
3429
3430 if (dnDevInst == 0)
3431 return CR_INVALID_DEVINST;
3432
3433 if (ulFlags != 0)
3434 return CR_INVALID_FLAG;
3435
3436 if (hMachine != NULL)
3437 {
3438 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3439 if (BindingHandle == NULL)
3440 return CR_FAILURE;
3441
3442 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3443 if (StringTable == 0)
3444 return CR_FAILURE;
3445 }
3446 else
3447 {
3448 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3449 return CR_FAILURE;
3450 }
3451
3452 lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3453 if (lpDevInst == NULL)
3454 return CR_INVALID_DEVNODE;
3455
3456 RpcTryExcept
3457 {
3458 ret = PNP_GetDeviceStatus(BindingHandle,
3459 lpDevInst,
3460 pulStatus,
3461 pulProblemNumber,
3462 ulFlags);
3463 }
3464 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3465 {
3466 ret = RpcStatusToCmStatus(RpcExceptionCode());
3467 }
3468 RpcEndExcept;
3469
3470 return ret;
3471 }
3472
3473
3474 /***********************************************************************
3475 * CM_Get_Device_IDA [SETUPAPI.@]
3476 */
3477 CONFIGRET
3478 WINAPI
3479 CM_Get_Device_IDA(
3480 _In_ DEVINST dnDevInst,
3481 _Out_writes_(BufferLen) PCHAR Buffer,
3482 _In_ ULONG BufferLen,
3483 _In_ ULONG ulFlags)
3484 {
3485 TRACE("CM_Get_Device_IDA(%lx %p %lu %lx)\n",
3486 dnDevInst, Buffer, BufferLen, ulFlags);
3487
3488 return CM_Get_Device_ID_ExA(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
3489 }
3490
3491
3492 /***********************************************************************
3493 * CM_Get_Device_IDW [SETUPAPI.@]
3494 */
3495 CONFIGRET
3496 WINAPI
3497 CM_Get_Device_IDW(
3498 _In_ DEVINST dnDevInst,
3499 _Out_writes_(BufferLen) PWCHAR Buffer,
3500 _In_ ULONG BufferLen,
3501 _In_ ULONG ulFlags)
3502 {
3503 TRACE("CM_Get_Device_IDW(%lx %p %lu %lx)\n",
3504 dnDevInst, Buffer, BufferLen, ulFlags);
3505
3506 return CM_Get_Device_ID_ExW(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
3507 }
3508
3509
3510 /***********************************************************************
3511 * CM_Get_Device_ID_ExA [SETUPAPI.@]
3512 */
3513 CONFIGRET
3514 WINAPI
3515 CM_Get_Device_ID_ExA(
3516 _In_ DEVINST dnDevInst,
3517 _Out_writes_(BufferLen) PCHAR Buffer,
3518 _In_ ULONG BufferLen,
3519 _In_ ULONG ulFlags,
3520 _In_opt_ HMACHINE hMachine)
3521 {
3522 WCHAR szBufferW[MAX_DEVICE_ID_LEN];
3523 CONFIGRET ret = CR_SUCCESS;
3524
3525 TRACE("CM_Get_Device_ID_ExA(%lx %p %lu %lx %p)\n",
3526 dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
3527
3528 if (Buffer == NULL)
3529 return CR_INVALID_POINTER;
3530
3531 ret = CM_Get_Device_ID_ExW(dnDevInst,
3532 szBufferW,
3533 MAX_DEVICE_ID_LEN,
3534 ulFlags,
3535 hMachine);
3536 if (ret == CR_SUCCESS)
3537 {
3538 if (WideCharToMultiByte(CP_ACP,
3539 0,
3540 szBufferW,
3541 lstrlenW(szBufferW) + 1,
3542 Buffer,
3543 BufferLen,
3544 NULL,
3545 NULL) == 0)
3546 ret = CR_FAILURE;
3547 }
3548
3549 return ret;
3550 }
3551
3552
3553 /***********************************************************************
3554 * CM_Get_Device_ID_ExW [SETUPAPI.@]
3555 */
3556 CONFIGRET
3557 WINAPI
3558 CM_Get_Device_ID_ExW(
3559 _In_ DEVINST dnDevInst,
3560 _Out_writes_(BufferLen) PWCHAR Buffer,
3561 _In_ ULONG BufferLen,
3562 _In_ ULONG ulFlags,
3563 _In_opt_ HMACHINE hMachine)
3564 {
3565 HSTRING_TABLE StringTable = NULL;
3566
3567 TRACE("CM_Get_Device_ID_ExW(%lx %p %lu %lx %p)\n",
3568 dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
3569
3570 if (dnDevInst == 0)
3571 return CR_INVALID_DEVINST;
3572
3573 if (Buffer == NULL)
3574 return CR_INVALID_POINTER;
3575
3576 if (ulFlags != 0)
3577 return CR_INVALID_FLAG;
3578
3579 if (hMachine != NULL)
3580 {
3581 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3582 if (StringTable == NULL)
3583 return CR_FAILURE;
3584 }
3585 else
3586 {