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