xref: /reactos/dll/win32/setupapi/cfgmgr.c (revision 01e5cb0c)
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         ulTransferLength = 300 * sizeof(WCHAR);
240         ulLength = 300 * sizeof(WCHAR);
241         ret = PNP_GetDeviceRegProp(BindingHandle,
242                                    pszDeviceInst,
243                                    CM_DRP_DRIVER,
244                                    &ulType,
245                                    (PVOID)pszBuffer,
246                                    &ulTransferLength,
247                                    &ulLength,
248                                    0);
249         if (ret != CR_SUCCESS)
250         {
251             ERR("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret);
252             goto done;
253         }
254 
255         TRACE("szBuffer: %S\n", pszBuffer);
256 
257         SplitDeviceInstanceId(pszBuffer,
258                               pszBuffer,
259                               pszInstancePath);
260 
261         TRACE("szBuffer: %S\n", pszBuffer);
262 
263         if (ulFlags & CM_REGISTRY_CONFIG)
264         {
265             if (ulHardwareProfile == 0)
266             {
267                 wsprintfW(pszKeyPath,
268                           L"%s\\%s\\%s\\%s",
269                           L"System\\CurrentControlSet\\Hardware Profiles",
270                           L"Current",
271                           L"System\\CurrentControlSet\\Control\\Class",
272                           pszBuffer);
273             }
274             else
275             {
276                 wsprintfW(pszKeyPath,
277                           L"%s\\%04lu\\%s\\%s",
278                           L"System\\CurrentControlSet\\Hardware Profiles",
279                           ulHardwareProfile,
280                           L"System\\CurrentControlSet\\Control\\Class",
281                           pszBuffer);
282             }
283         }
284         else
285         {
286             wsprintfW(pszKeyPath,
287                       L"%s\\%s",
288                       L"System\\CurrentControlSet\\Control\\Class",
289                       pszBuffer);
290         }
291     }
292     else
293     {
294         /* Hardware Key Path */
295 
296         if (ulFlags & CM_REGISTRY_CONFIG)
297         {
298             SplitDeviceInstanceId(pszDeviceInst,
299                                   pszBuffer,
300                                   pszInstancePath);
301 
302             if (ulHardwareProfile == 0)
303             {
304                 wsprintfW(pszKeyPath,
305                           L"%s\\%s\\%s\\%s",
306                           L"System\\CurrentControlSet\\Hardware Profiles",
307                           L"Current",
308                           L"System\\CurrentControlSet\\Enum",
309                           pszBuffer);
310             }
311             else
312             {
313                 wsprintfW(pszKeyPath,
314                           L"%s\\%04lu\\%s\\%s",
315                           L"System\\CurrentControlSet\\Hardware Profiles",
316                           ulHardwareProfile,
317                           L"System\\CurrentControlSet\\Enum",
318                           pszBuffer);
319             }
320         }
321         else if (ulFlags & CM_REGISTRY_USER)
322         {
323             wsprintfW(pszKeyPath,
324                       L"%s\\%s",
325                       L"System\\CurrentControlSet\\Enum",
326                       pszDeviceInst);
327 
328             wcscpy(pszInstancePath,
329                    L"Device Parameters");
330         }
331         else
332         {
333             SplitDeviceInstanceId(pszDeviceInst,
334                                   pszBuffer,
335                                   pszInstancePath);
336 
337             wsprintfW(pszKeyPath,
338                       L"%s\\%s",
339                       L"System\\CurrentControlSet\\Enum",
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     {
3587         if (!PnpGetLocalHandles(NULL, &StringTable))
3588             return CR_FAILURE;
3589     }
3590 
3591     if (!pSetupStringTableStringFromIdEx(StringTable,
3592                                          dnDevInst,
3593                                          Buffer,
3594                                          &BufferLen))
3595         return CR_FAILURE;
3596 
3597     return CR_SUCCESS;
3598 }
3599 
3600 
3601 /***********************************************************************
3602  * CM_Get_Device_ID_ListA [SETUPAPI.@]
3603  */
3604 CONFIGRET
3605 WINAPI
3606 CM_Get_Device_ID_ListA(
3607     _In_ PCSTR pszFilter,
3608     _Out_writes_(BufferLen) PCHAR Buffer,
3609     _In_ ULONG BufferLen,
3610     _In_ ULONG ulFlags)
3611 {
3612     TRACE("CM_Get_Device_ID_ListA(%p %p %lu %lx)\n",
3613           pszFilter, Buffer, BufferLen, ulFlags);
3614 
3615     return CM_Get_Device_ID_List_ExA(pszFilter, Buffer, BufferLen,
3616                                      ulFlags, NULL);
3617 }
3618 
3619 
3620 /***********************************************************************
3621  * CM_Get_Device_ID_ListW [SETUPAPI.@]
3622  */
3623 CONFIGRET
3624 WINAPI
3625 CM_Get_Device_ID_ListW(
3626     _In_ PCWSTR pszFilter,
3627     _Out_writes_(BufferLen) PWCHAR Buffer,
3628     _In_ ULONG BufferLen,
3629     _In_ ULONG ulFlags)
3630 {
3631     TRACE("CM_Get_Device_ID_ListW(%p %p %lu %lx)\n",
3632           pszFilter, Buffer, BufferLen, ulFlags);
3633 
3634     return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen,
3635                                      ulFlags, NULL);
3636 }
3637 
3638 
3639 /***********************************************************************
3640  * CM_Get_Device_ID_List_ExA [SETUPAPI.@]
3641  */
3642 CONFIGRET
3643 WINAPI
3644 CM_Get_Device_ID_List_ExA(
3645     _In_ PCSTR pszFilter,
3646     _Out_writes_(BufferLen) PCHAR Buffer,
3647     _In_ ULONG BufferLen,
3648     _In_ ULONG ulFlags,
3649     _In_opt_ HMACHINE hMachine)
3650 {
3651     LPWSTR BufferW = NULL;
3652     LPWSTR pszFilterW = NULL;
3653     CONFIGRET ret = CR_SUCCESS;
3654 
3655     TRACE("CM_Get_Device_ID_List_ExA(%p %p %lu %lx %p)\n",
3656           pszFilter, Buffer, BufferLen, ulFlags, hMachine);
3657 
3658     BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
3659     if (BufferW == NULL)
3660         return CR_OUT_OF_MEMORY;
3661 
3662     if (pszFilter == NULL)
3663     {
3664         ret = CM_Get_Device_ID_List_ExW(NULL,
3665                                         BufferW,
3666                                         BufferLen,
3667                                         ulFlags,
3668                                         hMachine);
3669     }
3670     else
3671     {
3672         if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
3673         {
3674             ret = CR_INVALID_DEVICE_ID;
3675             goto Done;
3676         }
3677 
3678         ret = CM_Get_Device_ID_List_ExW(pszFilterW,
3679                                         BufferW,
3680                                         BufferLen,
3681                                         ulFlags,
3682                                         hMachine);
3683 
3684         MyFree(pszFilterW);
3685     }
3686 
3687     if (WideCharToMultiByte(CP_ACP,
3688                             0,
3689                             BufferW,
3690                             lstrlenW(BufferW) + 1,
3691                             Buffer,
3692                             BufferLen,
3693                             NULL,
3694                             NULL) == 0)
3695         ret = CR_FAILURE;
3696 
3697 Done:
3698     MyFree(BufferW);
3699 
3700     return ret;
3701 }
3702 
3703 
3704 /***********************************************************************
3705  * CM_Get_Device_ID_List_ExW [SETUPAPI.@]
3706  */
3707 CONFIGRET
3708 WINAPI
3709 CM_Get_Device_ID_List_ExW(
3710     _In_ PCWSTR pszFilter,
3711     _Out_writes_(BufferLen) PWCHAR Buffer,
3712     _In_ ULONG BufferLen,
3713     _In_ ULONG ulFlags,
3714     _In_opt_ HMACHINE hMachine)
3715 {
3716     RPC_BINDING_HANDLE BindingHandle = NULL;
3717     CONFIGRET ret;
3718 
3719     TRACE("CM_Get_Device_ID_List_ExW(%p %p %lu %lx %p)\n",
3720           pszFilter, Buffer, BufferLen, ulFlags, hMachine);
3721 
3722     if (Buffer == NULL || BufferLen == 0)
3723         return CR_INVALID_POINTER;
3724 
3725     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
3726         return CR_INVALID_FLAG;
3727 
3728     if (hMachine != NULL)
3729     {
3730         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3731         if (BindingHandle == NULL)
3732             return CR_FAILURE;
3733     }
3734     else
3735     {
3736         if (!PnpGetLocalHandles(&BindingHandle, NULL))
3737             return CR_FAILURE;
3738     }
3739 
3740     *Buffer = 0;
3741 
3742     RpcTryExcept
3743     {
3744         ret = PNP_GetDeviceList(BindingHandle,
3745                                 (LPWSTR)pszFilter,
3746                                 Buffer,
3747                                 &BufferLen,
3748                                 ulFlags);
3749     }
3750     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3751     {
3752         ret = RpcStatusToCmStatus(RpcExceptionCode());
3753     }
3754     RpcEndExcept;
3755 
3756     return ret;
3757 }
3758 
3759 
3760 /***********************************************************************
3761  * CM_Get_Device_ID_List_SizeA [SETUPAPI.@]
3762  */
3763 CONFIGRET
3764 WINAPI
3765 CM_Get_Device_ID_List_SizeA(
3766     _Out_ PULONG pulLen,
3767     _In_opt_ PCSTR pszFilter,
3768     _In_ ULONG ulFlags)
3769 {
3770     TRACE("CM_Get_Device_ID_List_SizeA(%p %s %lx)\n",
3771           pulLen, debugstr_a(pszFilter), ulFlags);
3772 
3773     return CM_Get_Device_ID_List_Size_ExA(pulLen, pszFilter, ulFlags, NULL);
3774 }
3775 
3776 
3777 /***********************************************************************
3778  * CM_Get_Device_ID_List_SizeW [SETUPAPI.@]
3779  */
3780 CONFIGRET
3781 WINAPI
3782 CM_Get_Device_ID_List_SizeW(
3783     _Out_ PULONG pulLen,
3784     _In_opt_ PCWSTR pszFilter,
3785     _In_ ULONG ulFlags)
3786 {
3787     TRACE("CM_Get_Device_ID_List_SizeW(%p %s %lx)\n",
3788           pulLen, debugstr_w(pszFilter), ulFlags);
3789 
3790     return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL);
3791 }
3792 
3793 
3794 /***********************************************************************
3795  * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@]
3796  */
3797 CONFIGRET
3798 WINAPI
3799 CM_Get_Device_ID_List_Size_ExA(
3800     _Out_ PULONG pulLen,
3801     _In_opt_ PCSTR pszFilter,
3802     _In_ ULONG ulFlags,
3803     _In_opt_ HMACHINE hMachine)
3804 {
3805     LPWSTR pszFilterW = NULL;
3806     CONFIGRET ret = CR_SUCCESS;
3807 
3808     FIXME("CM_Get_Device_ID_List_Size_ExA(%p %s %lx %p)\n",
3809           pulLen, debugstr_a(pszFilter), ulFlags, hMachine);
3810 
3811     if (pszFilter == NULL)
3812     {
3813         ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
3814                                              NULL,
3815                                              ulFlags,
3816                                              hMachine);
3817     }
3818     else
3819     {
3820         if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
3821             return CR_INVALID_DEVICE_ID;
3822 
3823         ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
3824                                              pszFilterW,
3825                                              ulFlags,
3826                                              hMachine);
3827 
3828         MyFree(pszFilterW);
3829     }
3830 
3831     return ret;
3832 }
3833 
3834 
3835 /***********************************************************************
3836  * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@]
3837  */
3838 CONFIGRET
3839 WINAPI
3840 CM_Get_Device_ID_List_Size_ExW(
3841     _Out_ PULONG pulLen,
3842     _In_opt_ PCWSTR pszFilter,
3843     _In_ ULONG ulFlags,
3844     _In_opt_ HMACHINE hMachine)
3845 {
3846     RPC_BINDING_HANDLE BindingHandle = NULL;
3847     CONFIGRET ret;
3848 
3849     FIXME("CM_Get_Device_ID_List_Size_ExW(%p %s %lx %p)\n",
3850           pulLen, debugstr_w(pszFilter), ulFlags, hMachine);
3851 
3852     if (pulLen == NULL)
3853         return CR_INVALID_POINTER;
3854 
3855     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
3856         return CR_INVALID_FLAG;
3857 
3858     if (hMachine != NULL)
3859     {
3860         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3861         if (BindingHandle == NULL)
3862             return CR_FAILURE;
3863     }
3864     else
3865     {
3866         if (!PnpGetLocalHandles(&BindingHandle, NULL))
3867             return CR_FAILURE;
3868     }
3869 
3870     *pulLen = 0;
3871 
3872     RpcTryExcept
3873     {
3874         ret = PNP_GetDeviceListSize(BindingHandle,
3875                                     (LPWSTR)pszFilter,
3876                                     pulLen,
3877                                     ulFlags);
3878     }
3879     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3880     {
3881         ret = RpcStatusToCmStatus(RpcExceptionCode());
3882     }
3883     RpcEndExcept;
3884 
3885     return ret;
3886 }
3887 
3888 
3889 /***********************************************************************
3890  * CM_Get_Device_ID_Size [SETUPAPI.@]
3891  */
3892 CONFIGRET
3893 WINAPI
3894 CM_Get_Device_ID_Size(
3895     _Out_ PULONG pulLen,
3896     _In_ DEVINST dnDevInst,
3897     _In_ ULONG ulFlags)
3898 {
3899     TRACE("CM_Get_Device_ID_Size(%p %lx %lx)\n",
3900           pulLen, dnDevInst, ulFlags);
3901 
3902     return CM_Get_Device_ID_Size_Ex(pulLen, dnDevInst, ulFlags, NULL);
3903 }
3904 
3905 
3906 /***********************************************************************
3907  * CM_Get_Device_ID_Size_Ex [SETUPAPI.@]
3908  */
3909 CONFIGRET
3910 WINAPI
3911 CM_Get_Device_ID_Size_Ex(
3912     _Out_ PULONG pulLen,
3913     _In_ DEVINST dnDevInst,
3914     _In_ ULONG ulFlags,
3915     _In_opt_ HMACHINE hMachine)
3916 {
3917     HSTRING_TABLE StringTable = NULL;
3918     LPWSTR DeviceId;
3919 
3920     TRACE("CM_Get_Device_ID_Size_Ex(%p %lx %lx %p)\n",
3921           pulLen, dnDevInst, ulFlags, hMachine);
3922 
3923     if (pulLen == NULL)
3924         return CR_INVALID_POINTER;
3925 
3926     if (dnDevInst == 0)
3927         return CR_INVALID_DEVINST;
3928 
3929     if (ulFlags != 0)
3930         return CR_INVALID_FLAG;
3931 
3932     if (hMachine != NULL)
3933     {
3934         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3935         if (StringTable == NULL)
3936             return CR_FAILURE;
3937     }
3938     else
3939     {
3940         if (!PnpGetLocalHandles(NULL, &StringTable))
3941             return CR_FAILURE;
3942     }
3943 
3944     DeviceId = pSetupStringTableStringFromId(StringTable, dnDevInst);
3945     if (DeviceId == NULL)
3946     {
3947         *pulLen = 0;
3948         return CR_SUCCESS;
3949     }
3950 
3951     *pulLen = lstrlenW(DeviceId);
3952 
3953     return CR_SUCCESS;
3954 }
3955 
3956 
3957 /***********************************************************************
3958  * CM_Get_Device_Interface_AliasA [SETUPAPI.@]
3959  */
3960 CONFIGRET
3961 WINAPI
3962 CM_Get_Device_Interface_AliasA(
3963     _In_ LPCSTR pszDeviceInterface,
3964     _In_ LPGUID AliasInterfaceGuid,
3965     _Out_writes_(*pulLength) LPSTR pszAliasDeviceInterface,
3966     _Inout_ PULONG pulLength,
3967     _In_ ULONG ulFlags)
3968 {
3969     TRACE("CM_Get_Device_Interface_AliasA(%p %p %p %p %lx)\n",
3970           pszDeviceInterface, AliasInterfaceGuid,
3971           pszAliasDeviceInterface, pulLength, ulFlags);
3972 
3973     return CM_Get_Device_Interface_Alias_ExA(pszDeviceInterface,
3974         AliasInterfaceGuid, pszAliasDeviceInterface, pulLength,
3975         ulFlags, NULL);
3976 }
3977 
3978 
3979 /***********************************************************************
3980  * CM_Get_Device_Interface_AliasW [SETUPAPI.@]
3981  */
3982 CONFIGRET
3983 WINAPI
3984 CM_Get_Device_Interface_AliasW(
3985     _In_ LPCWSTR pszDeviceInterface,
3986     _In_ LPGUID AliasInterfaceGuid,
3987     _Out_writes_(*pulLength) LPWSTR pszAliasDeviceInterface,
3988     _Inout_ PULONG pulLength,
3989     _In_ ULONG ulFlags)
3990 {
3991     TRACE("CM_Get_Device_Interface_AliasW(%p %p %p %p %lx)\n",
3992           pszDeviceInterface, AliasInterfaceGuid,
3993           pszAliasDeviceInterface, pulLength, ulFlags);
3994 
3995     return CM_Get_Device_Interface_Alias_ExW(pszDeviceInterface,
3996         AliasInterfaceGuid, pszAliasDeviceInterface, pulLength,
3997         ulFlags, NULL);
3998 }
3999 
4000 
4001 /***********************************************************************
4002  * CM_Get_Device_Interface_Alias_ExA [SETUPAPI.@]
4003  */
4004 CONFIGRET
4005 WINAPI
4006 CM_Get_Device_Interface_Alias_ExA(
4007     _In_ LPCSTR pszDeviceInterface,
4008     _In_ LPGUID AliasInterfaceGuid,
4009     _Out_writes_(*pulLength) LPSTR pszAliasDeviceInterface,
4010     _Inout_ PULONG pulLength,
4011     _In_ ULONG ulFlags,
4012     _In_opt_ HMACHINE hMachine)
4013 {
4014     FIXME("CM_Get_Device_Interface_Alias_ExA(%p %p %p %p %lx %p)\n",
4015           pszDeviceInterface, AliasInterfaceGuid,
4016           pszAliasDeviceInterface, pulLength, ulFlags, hMachine);
4017 
4018     return CR_CALL_NOT_IMPLEMENTED;
4019 }
4020 
4021 
4022 /***********************************************************************
4023  * CM_Get_Device_Interface_Alias_ExW [SETUPAPI.@]
4024  */
4025 CONFIGRET
4026 WINAPI
4027 CM_Get_Device_Interface_Alias_ExW(
4028     _In_ LPCWSTR pszDeviceInterface,
4029     _In_ LPGUID AliasInterfaceGuid,
4030     _Out_writes_(*pulLength) LPWSTR pszAliasDeviceInterface,
4031     _Inout_ PULONG pulLength,
4032     _In_ ULONG ulFlags,
4033     _In_opt_ HMACHINE hMachine)
4034 {
4035     RPC_BINDING_HANDLE BindingHandle = NULL;
4036     ULONG ulTransferLength;
4037     CONFIGRET ret = CR_SUCCESS;
4038 
4039     TRACE("CM_Get_Device_Interface_Alias_ExW(%p %p %p %p %lx %p)\n",
4040           pszDeviceInterface, AliasInterfaceGuid,
4041           pszAliasDeviceInterface, pulLength, ulFlags, hMachine);
4042 
4043     if (pszDeviceInterface == NULL ||
4044         AliasInterfaceGuid == NULL ||
4045         pszAliasDeviceInterface == NULL ||
4046         pulLength == NULL)
4047         return CR_INVALID_POINTER;
4048 
4049     if (ulFlags != 0)
4050         return CR_INVALID_FLAG;
4051 
4052     if (hMachine != NULL)
4053     {
4054         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4055         if (BindingHandle == NULL)
4056             return CR_FAILURE;
4057     }
4058     else
4059     {
4060         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4061             return CR_FAILURE;
4062     }
4063 
4064     ulTransferLength = *pulLength;
4065 
4066     RpcTryExcept
4067     {
4068         ret = PNP_GetInterfaceDeviceAlias(BindingHandle,
4069                                           (LPWSTR)pszDeviceInterface,
4070                                           AliasInterfaceGuid,
4071                                           pszAliasDeviceInterface,
4072                                           pulLength,
4073                                           &ulTransferLength,
4074                                           0);
4075     }
4076     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4077     {
4078         ret = RpcStatusToCmStatus(RpcExceptionCode());
4079     }
4080     RpcEndExcept;
4081 
4082     return ret;
4083 }
4084 
4085 
4086 /***********************************************************************
4087  *      CM_Get_Device_Interface_ListA (SETUPAPI.@)
4088  */
4089 CONFIGRET
4090 WINAPI
4091 CM_Get_Device_Interface_ListA(
4092     _In_ LPGUID InterfaceClassGuid,
4093     _In_opt_ DEVINSTID_A pDeviceID,
4094     _Out_writes_(BufferLen) PCHAR Buffer,
4095     _In_ ULONG BufferLen,
4096     _In_ ULONG ulFlags)
4097 {
4098     TRACE("CM_Get_Device_Interface_ListA(%s %s %p %lu 0x%08lx)\n",
4099           debugstr_guid(InterfaceClassGuid), debugstr_a(pDeviceID),
4100           Buffer, BufferLen, ulFlags);
4101 
4102     return CM_Get_Device_Interface_List_ExA(InterfaceClassGuid, pDeviceID,
4103                                             Buffer, BufferLen, ulFlags, NULL);
4104 }
4105 
4106 
4107 /***********************************************************************
4108  *      CM_Get_Device_Interface_ListW (SETUPAPI.@)
4109  */
4110 CONFIGRET
4111 WINAPI
4112 CM_Get_Device_Interface_ListW(
4113     _In_ LPGUID InterfaceClassGuid,
4114     _In_opt_ DEVINSTID_W pDeviceID,
4115     _Out_writes_(BufferLen) PWCHAR Buffer,
4116     _In_ ULONG BufferLen,
4117     _In_ ULONG ulFlags)
4118 {
4119     TRACE("CM_Get_Device_Interface_ListW(%s %s %p %lu 0x%08lx)\n",
4120           debugstr_guid(InterfaceClassGuid), debugstr_w(pDeviceID),
4121           Buffer, BufferLen, ulFlags);
4122 
4123     return CM_Get_Device_Interface_List_ExW(InterfaceClassGuid, pDeviceID,
4124                                             Buffer, BufferLen, ulFlags, NULL);
4125 }
4126 
4127 
4128 /***********************************************************************
4129  *      CM_Get_Device_Interface_List_ExA (SETUPAPI.@)
4130  */
4131 CONFIGRET
4132 WINAPI
4133 CM_Get_Device_Interface_List_ExA(
4134     _In_ LPGUID InterfaceClassGuid,
4135     _In_opt_ DEVINSTID_A pDeviceID,
4136     _Out_writes_(BufferLen) PCHAR Buffer,
4137     _In_ ULONG BufferLen,
4138     _In_ ULONG ulFlags,
4139     _In_opt_ HMACHINE hMachine)
4140 {
4141     DEVINSTID_W pDeviceIdW = NULL;
4142     PWCHAR BufferW = NULL;
4143     CONFIGRET ret = CR_SUCCESS;
4144 
4145     TRACE("CM_Get_Device_Interface_List_ExA(%s %s %p %lu 0x%08lx %p)\n",
4146           debugstr_guid(InterfaceClassGuid), debugstr_a(pDeviceID),
4147           Buffer, BufferLen, ulFlags, hMachine);
4148 
4149     if (Buffer == NULL ||
4150         BufferLen == 0)
4151         return CR_INVALID_POINTER;
4152 
4153     if (pDeviceID != NULL)
4154     {
4155         if (!pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIdW))
4156             return CR_INVALID_DEVICE_ID;
4157     }
4158 
4159     BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
4160     if (BufferW == NULL)
4161     {
4162         ret = CR_OUT_OF_MEMORY;
4163         goto Done;
4164     }
4165 
4166     ret = CM_Get_Device_Interface_List_ExW(InterfaceClassGuid, pDeviceIdW,
4167                                            BufferW, BufferLen, ulFlags,
4168                                            hMachine);
4169     if (ret != CR_SUCCESS)
4170         goto Done;
4171 
4172     if (WideCharToMultiByte(CP_ACP,
4173                             0,
4174                             BufferW,
4175                             lstrlenW(BufferW) + 1,
4176                             Buffer,
4177                             BufferLen,
4178                             NULL,
4179                             NULL) == 0)
4180         ret = CR_FAILURE;
4181 
4182 Done:
4183     if (BufferW != NULL)
4184         MyFree(BufferW);
4185 
4186     if (pDeviceIdW != NULL)
4187         MyFree(pDeviceIdW);
4188 
4189     return ret;
4190 }
4191 
4192 
4193 /***********************************************************************
4194  *      CM_Get_Device_Interface_List_ExW (SETUPAPI.@)
4195  */
4196 CONFIGRET
4197 WINAPI
4198 CM_Get_Device_Interface_List_ExW(
4199     _In_ LPGUID InterfaceClassGuid,
4200     _In_opt_ DEVINSTID_W pDeviceID,
4201     _Out_writes_(BufferLen) PWCHAR Buffer,
4202     _In_ ULONG BufferLen,
4203     _In_ ULONG ulFlags,
4204     _In_opt_ HMACHINE hMachine)
4205 {
4206     RPC_BINDING_HANDLE BindingHandle = NULL;
4207     PNP_RPC_BUFFER_SIZE BufferSize = 0;
4208     CONFIGRET ret = CR_SUCCESS;
4209 
4210     TRACE("CM_Get_Device_Interface_List_ExW(%s %s %p %lu 0x%08lx %p)\n",
4211           debugstr_guid(InterfaceClassGuid), debugstr_w(pDeviceID),
4212           Buffer, BufferLen, ulFlags, hMachine);
4213 
4214     if (Buffer == NULL ||
4215         BufferLen == 0)
4216         return CR_INVALID_POINTER;
4217 
4218     if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
4219         return CR_INVALID_FLAG;
4220 
4221     if (hMachine != NULL)
4222     {
4223         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4224         if (BindingHandle == NULL)
4225             return CR_FAILURE;
4226     }
4227     else
4228     {
4229         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4230             return CR_FAILURE;
4231     }
4232 
4233     *Buffer = 0;
4234     BufferSize = BufferLen;
4235 
4236     RpcTryExcept
4237     {
4238         ret = PNP_GetInterfaceDeviceList(BindingHandle,
4239                                          InterfaceClassGuid,
4240                                          pDeviceID,
4241                                          (LPBYTE)Buffer,
4242                                          &BufferSize,
4243                                          ulFlags);
4244     }
4245     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4246     {
4247         ret = RpcStatusToCmStatus(RpcExceptionCode());
4248     }
4249     RpcEndExcept;
4250 
4251     return ret;
4252 }
4253 
4254 
4255 /***********************************************************************
4256  *      CM_Get_Device_Interface_List_SizeA (SETUPAPI.@)
4257  */
4258 CONFIGRET
4259 WINAPI
4260 CM_Get_Device_Interface_List_SizeA(
4261     _Out_ PULONG pulLen,
4262     _In_ LPGUID InterfaceClassGuid,
4263     _In_opt_ DEVINSTID_A pDeviceID,
4264     _In_ ULONG ulFlags)
4265 {
4266     TRACE("CM_Get_Device_Interface_List_SizeA(%p %p %s 0x%08lx)\n",
4267           pulLen, InterfaceClassGuid, debugstr_a(pDeviceID), ulFlags);
4268 
4269     return CM_Get_Device_Interface_List_Size_ExA(pulLen, InterfaceClassGuid,
4270                                                  pDeviceID, ulFlags, NULL);
4271 }
4272 
4273 
4274 /***********************************************************************
4275  *      CM_Get_Device_Interface_List_SizeW (SETUPAPI.@)
4276  */
4277 CONFIGRET
4278 WINAPI
4279 CM_Get_Device_Interface_List_SizeW(
4280     _Out_ PULONG pulLen,
4281     _In_ LPGUID InterfaceClassGuid,
4282     _In_opt_ DEVINSTID_W pDeviceID,
4283     _In_ ULONG ulFlags)
4284 {
4285     TRACE("CM_Get_Device_Interface_List_SizeW(%p %p %s 0x%08lx)\n",
4286           pulLen, InterfaceClassGuid, debugstr_w(pDeviceID), ulFlags);
4287 
4288     return CM_Get_Device_Interface_List_Size_ExW(pulLen, InterfaceClassGuid,
4289                                                  pDeviceID, ulFlags, NULL);
4290 }
4291 
4292 
4293 /***********************************************************************
4294  *      CM_Get_Device_Interface_List_Size_ExA (SETUPAPI.@)
4295  */
4296 CONFIGRET
4297 WINAPI
4298 CM_Get_Device_Interface_List_Size_ExA(
4299     _Out_ PULONG pulLen,
4300     _In_ LPGUID InterfaceClassGuid,
4301     _In_opt_ DEVINSTID_A pDeviceID,
4302     _In_ ULONG ulFlags,
4303     _In_opt_ HMACHINE hMachine)
4304 {
4305     DEVINSTID_W pDeviceIdW = NULL;
4306     CONFIGRET ret = CR_SUCCESS;
4307 
4308     TRACE("CM_Get_Device_Interface_List_Size_ExA(%p %p %s 0x%08lx %p)\n",
4309           pulLen, InterfaceClassGuid, debugstr_a(pDeviceID), ulFlags, hMachine);
4310 
4311     if (pulLen == NULL)
4312         return CR_INVALID_POINTER;
4313 
4314     if (pDeviceID != NULL)
4315     {
4316         if (!pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIdW))
4317             return CR_INVALID_DEVICE_ID;
4318     }
4319 
4320     *pulLen = 0;
4321 
4322     ret = CM_Get_Device_Interface_List_Size_ExW(pulLen, InterfaceClassGuid,
4323                                                 pDeviceIdW, ulFlags, hMachine);
4324 
4325     if (pDeviceIdW != NULL)
4326         MyFree(pDeviceIdW);
4327 
4328     return ret;
4329 }
4330 
4331 
4332 /***********************************************************************
4333  *      CM_Get_Device_Interface_List_Size_ExW (SETUPAPI.@)
4334  */
4335 CONFIGRET
4336 WINAPI
4337 CM_Get_Device_Interface_List_Size_ExW(
4338     _Out_ PULONG pulLen,
4339     _In_ LPGUID InterfaceClassGuid,
4340     _In_opt_ DEVINSTID_W pDeviceID,
4341     _In_ ULONG ulFlags,
4342     _In_opt_ HMACHINE hMachine)
4343 {
4344     RPC_BINDING_HANDLE BindingHandle = NULL;
4345     CONFIGRET ret = CR_SUCCESS;
4346 
4347     TRACE("CM_Get_Device_Interface_List_Size_ExW(%p %p %s 0x%08lx %p)\n",
4348           pulLen, InterfaceClassGuid, debugstr_w(pDeviceID), ulFlags, hMachine);
4349 
4350     if (pulLen == NULL)
4351         return CR_INVALID_POINTER;
4352 
4353     if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
4354         return CR_INVALID_FLAG;
4355 
4356     if (hMachine != NULL)
4357     {
4358         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4359         if (BindingHandle == NULL)
4360             return CR_FAILURE;
4361     }
4362     else
4363     {
4364         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4365             return CR_FAILURE;
4366     }
4367 
4368     *pulLen = 0;
4369 
4370     RpcTryExcept
4371     {
4372         ret = PNP_GetInterfaceDeviceListSize(BindingHandle,
4373                                              pulLen,
4374                                              InterfaceClassGuid,
4375                                              pDeviceID,
4376                                              ulFlags);
4377     }
4378     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4379     {
4380         ret = RpcStatusToCmStatus(RpcExceptionCode());
4381     }
4382     RpcEndExcept;
4383 
4384     return ret;
4385 }
4386 
4387 
4388 /***********************************************************************
4389  * CM_Get_First_Log_Conf [SETUPAPI.@]
4390  */
4391 CONFIGRET
4392 WINAPI
4393 CM_Get_First_Log_Conf(
4394     _Out_opt_ PLOG_CONF plcLogConf,
4395     _In_ DEVINST dnDevInst,
4396     _In_ ULONG ulFlags)
4397 {
4398     TRACE("CM_Get_First_Log_Conf(%p %lx %lx)\n",
4399           plcLogConf, dnDevInst, ulFlags);
4400 
4401     return CM_Get_First_Log_Conf_Ex(plcLogConf, dnDevInst, ulFlags, NULL);
4402 }
4403 
4404 
4405 /***********************************************************************
4406  * CM_Get_First_Log_Conf_Ex [SETUPAPI.@]
4407  */
4408 CONFIGRET
4409 WINAPI
4410 CM_Get_First_Log_Conf_Ex(
4411     _Out_opt_ PLOG_CONF plcLogConf,
4412     _In_ DEVINST dnDevInst,
4413     _In_ ULONG ulFlags,
4414     _In_opt_ HMACHINE hMachine)
4415 {
4416     RPC_BINDING_HANDLE BindingHandle = NULL;
4417     HSTRING_TABLE StringTable = NULL;
4418     LPWSTR lpDevInst = NULL;
4419     CONFIGRET ret = CR_SUCCESS;
4420     ULONG ulTag;
4421     PLOG_CONF_INFO pLogConfInfo;
4422 
4423     FIXME("CM_Get_First_Log_Conf_Ex(%p %lx %lx %p)\n",
4424           plcLogConf, dnDevInst, ulFlags, hMachine);
4425 
4426     if (dnDevInst == 0)
4427         return CR_INVALID_DEVINST;
4428 
4429     if (ulFlags & ~LOG_CONF_BITS)
4430         return CR_INVALID_FLAG;
4431 
4432     if (plcLogConf)
4433         *plcLogConf = 0;
4434 
4435     if (hMachine != NULL)
4436     {
4437         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4438         if (BindingHandle == NULL)
4439             return CR_FAILURE;
4440 
4441         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
4442         if (StringTable == 0)
4443             return CR_FAILURE;
4444     }
4445     else
4446     {
4447         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
4448             return CR_FAILURE;
4449     }
4450 
4451     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
4452     if (lpDevInst == NULL)
4453         return CR_INVALID_DEVNODE;
4454 
4455     RpcTryExcept
4456     {
4457         ret = PNP_GetFirstLogConf(BindingHandle,
4458                                   lpDevInst,
4459                                   ulFlags,
4460                                   &ulTag,
4461                                   ulFlags);
4462     }
4463     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4464     {
4465         ret = RpcStatusToCmStatus(RpcExceptionCode());
4466     }
4467     RpcEndExcept;
4468 
4469     if (ret != CR_SUCCESS)
4470         return ret;
4471 
4472     if (plcLogConf)
4473     {
4474         pLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
4475         if (pLogConfInfo == NULL)
4476             return CR_OUT_OF_MEMORY;
4477 
4478         pLogConfInfo->ulMagic = LOG_CONF_MAGIC;
4479         pLogConfInfo->dnDevInst = dnDevInst;
4480         pLogConfInfo->ulFlags = ulFlags;
4481         pLogConfInfo->ulTag = ulTag;
4482 
4483         *plcLogConf = (LOG_CONF)pLogConfInfo;
4484     }
4485 
4486     return CR_SUCCESS;
4487 }
4488 
4489 
4490 /***********************************************************************
4491  * CM_Get_Global_State [SETUPAPI.@]
4492  */
4493 CONFIGRET
4494 WINAPI
4495 CM_Get_Global_State(
4496     _Out_ PULONG pulState,
4497     _In_ ULONG ulFlags)
4498 {
4499     TRACE("CM_Get_Global_State(%p %lx)\n",
4500           pulState, ulFlags);
4501 
4502     return CM_Get_Global_State_Ex(pulState, ulFlags, NULL);
4503 }
4504 
4505 
4506 /***********************************************************************
4507  * CM_Get_Global_State_Ex [SETUPAPI.@]
4508  */
4509 CONFIGRET
4510 WINAPI
4511 CM_Get_Global_State_Ex(
4512     _Out_ PULONG pulState,
4513     _In_ ULONG ulFlags,
4514     _In_opt_ HMACHINE hMachine)
4515 {
4516     RPC_BINDING_HANDLE BindingHandle = NULL;
4517     CONFIGRET ret;
4518 
4519     TRACE("CM_Get_Global_State_Ex(%p %lx %p)\n",
4520           pulState, ulFlags, hMachine);
4521 
4522     if (pulState == NULL)
4523         return CR_INVALID_POINTER;
4524 
4525     if (ulFlags != 0)
4526         return CR_INVALID_FLAG;
4527 
4528     if (hMachine != NULL)
4529     {
4530         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4531         if (BindingHandle == NULL)
4532             return CR_FAILURE;
4533     }
4534     else
4535     {
4536         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4537             return CR_FAILURE;
4538     }
4539 
4540     RpcTryExcept
4541     {
4542         ret = PNP_GetGlobalState(BindingHandle, pulState, ulFlags);
4543     }
4544     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4545     {
4546         ret = RpcStatusToCmStatus(RpcExceptionCode());
4547     }
4548     RpcEndExcept;
4549 
4550     return ret;
4551 }
4552 
4553 
4554 /***********************************************************************
4555  * CM_Get_HW_Prof_FlagsA [SETUPAPI.@]
4556  */
4557 CONFIGRET
4558 WINAPI
4559 CM_Get_HW_Prof_FlagsA(
4560     _In_ DEVINSTID_A szDevInstName,
4561     _In_ ULONG ulHardwareProfile,
4562     _Out_ PULONG pulValue,
4563     _In_ ULONG ulFlags)
4564 {
4565     TRACE("CM_Get_HW_Prof_FlagsA(%s %lu %p %lx)\n",
4566           debugstr_a(szDevInstName), ulHardwareProfile, pulValue, ulFlags);
4567 
4568     return CM_Get_HW_Prof_Flags_ExA(szDevInstName, ulHardwareProfile,
4569                                     pulValue, ulFlags, NULL);
4570 }
4571 
4572 
4573 /***********************************************************************
4574  * CM_Get_HW_Prof_FlagsW [SETUPAPI.@]
4575  */
4576 CONFIGRET
4577 WINAPI
4578 CM_Get_HW_Prof_FlagsW(
4579     _In_ DEVINSTID_W szDevInstName,
4580     _In_ ULONG ulHardwareProfile,
4581     _Out_ PULONG pulValue,
4582     _In_ ULONG ulFlags)
4583 {
4584     TRACE("CM_Get_HW_Prof_FlagsW(%s %lu %p %lx)\n",
4585           debugstr_w(szDevInstName), ulHardwareProfile, pulValue, ulFlags);
4586 
4587     return CM_Get_HW_Prof_Flags_ExW(szDevInstName, ulHardwareProfile,
4588                                     pulValue, ulFlags, NULL);
4589 }
4590 
4591 
4592 /***********************************************************************
4593  * CM_Get_HW_Prof_Flags_ExA [SETUPAPI.@]
4594  */
4595 CONFIGRET
4596 WINAPI
4597 CM_Get_HW_Prof_Flags_ExA(
4598     _In_ DEVINSTID_A szDevInstName,
4599     _In_ ULONG ulHardwareProfile,
4600     _Out_ PULONG pulValue,
4601     _In_ ULONG ulFlags,
4602     _In_opt_ HMACHINE hMachine)
4603 {
4604     DEVINSTID_W pszDevIdW = NULL;
4605     CONFIGRET ret = CR_SUCCESS;
4606 
4607     TRACE("CM_Get_HW_Prof_Flags_ExA(%s %lu %p %lx %p)\n",
4608           debugstr_a(szDevInstName), ulHardwareProfile, pulValue, ulFlags, hMachine);
4609 
4610     if (szDevInstName != NULL)
4611     {
4612        if (pSetupCaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
4613          return CR_INVALID_DEVICE_ID;
4614     }
4615 
4616     ret = CM_Get_HW_Prof_Flags_ExW(pszDevIdW, ulHardwareProfile,
4617                                    pulValue, ulFlags, hMachine);
4618 
4619     if (pszDevIdW != NULL)
4620         MyFree(pszDevIdW);
4621 
4622     return ret;
4623 }
4624 
4625 
4626 /***********************************************************************
4627  * CM_Get_HW_Prof_Flags_ExW [SETUPAPI.@]
4628  */
4629 CONFIGRET
4630 WINAPI
4631 CM_Get_HW_Prof_Flags_ExW(
4632     _In_ DEVINSTID_W szDevInstName,
4633     _In_ ULONG ulHardwareProfile,
4634     _Out_ PULONG pulValue,
4635     _In_ ULONG ulFlags,
4636     _In_opt_ HMACHINE hMachine)
4637 {
4638     RPC_BINDING_HANDLE BindingHandle = NULL;
4639     CONFIGRET ret;
4640 
4641     FIXME("CM_Get_HW_Prof_Flags_ExW(%s %lu %p %lx %p)\n",
4642           debugstr_w(szDevInstName), ulHardwareProfile, pulValue, ulFlags, hMachine);
4643 
4644     if ((szDevInstName == NULL) || (pulValue == NULL))
4645         return CR_INVALID_POINTER;
4646 
4647     if (ulFlags != 0)
4648         return CR_INVALID_FLAG;
4649 
4650     /* FIXME: Check whether szDevInstName is valid */
4651 
4652     if (hMachine != NULL)
4653     {
4654         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4655         if (BindingHandle == NULL)
4656             return CR_FAILURE;
4657     }
4658     else
4659     {
4660         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4661             return CR_FAILURE;
4662     }
4663 
4664     RpcTryExcept
4665     {
4666         ret = PNP_HwProfFlags(BindingHandle, PNP_GET_HWPROFFLAGS, szDevInstName,
4667                               ulHardwareProfile, pulValue, NULL, NULL, 0, 0);
4668     }
4669     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4670     {
4671         ret = RpcStatusToCmStatus(RpcExceptionCode());
4672     }
4673     RpcEndExcept;
4674 
4675     return ret;
4676 }
4677 
4678 
4679 /***********************************************************************
4680  * CM_Get_Hardware_Profile_InfoA [SETUPAPI.@]
4681  */
4682 CONFIGRET
4683 WINAPI
4684 CM_Get_Hardware_Profile_InfoA(
4685     _In_ ULONG ulIndex,
4686     _Out_ PHWPROFILEINFO_A pHWProfileInfo,
4687     _In_ ULONG ulFlags)
4688 {
4689     TRACE("CM_Get_Hardware_Profile_InfoA(%lu %p %lx)\n",
4690           ulIndex, pHWProfileInfo, ulFlags);
4691 
4692     return CM_Get_Hardware_Profile_Info_ExA(ulIndex, pHWProfileInfo,
4693                                             ulFlags, NULL);
4694 }
4695 
4696 
4697 /***********************************************************************
4698  * CM_Get_Hardware_Profile_InfoW [SETUPAPI.@]
4699  */
4700 CONFIGRET
4701 WINAPI
4702 CM_Get_Hardware_Profile_InfoW(
4703     _In_ ULONG ulIndex,
4704     _Out_ PHWPROFILEINFO_W pHWProfileInfo,
4705     _In_ ULONG ulFlags)
4706 {
4707     TRACE("CM_Get_Hardware_Profile_InfoW(%lu %p %lx)\n",
4708           ulIndex, pHWProfileInfo, ulFlags);
4709 
4710     return CM_Get_Hardware_Profile_Info_ExW(ulIndex, pHWProfileInfo,
4711                                             ulFlags, NULL);
4712 }
4713 
4714 
4715 /***********************************************************************
4716  * CM_Get_Hardware_Profile_Info_ExA [SETUPAPI.@]
4717  */
4718 CONFIGRET
4719 WINAPI
4720 CM_Get_Hardware_Profile_Info_ExA(
4721     _In_ ULONG ulIndex,
4722     _Out_ PHWPROFILEINFO_A pHWProfileInfo,
4723     _In_ ULONG ulFlags,
4724     _In_opt_ HMACHINE hMachine)
4725 {
4726     HWPROFILEINFO_W LocalProfileInfo;
4727     CONFIGRET ret;
4728 
4729     TRACE("CM_Get_Hardware_Profile_Info_ExA(%lu %p %lx %p)\n",
4730           ulIndex, pHWProfileInfo, ulFlags, hMachine);
4731 
4732     if (pHWProfileInfo == NULL)
4733         return CR_INVALID_POINTER;
4734 
4735     ret = CM_Get_Hardware_Profile_Info_ExW(ulIndex, &LocalProfileInfo,
4736                                            ulFlags, hMachine);
4737     if (ret == CR_SUCCESS)
4738     {
4739         pHWProfileInfo->HWPI_ulHWProfile = LocalProfileInfo.HWPI_ulHWProfile;
4740         pHWProfileInfo->HWPI_dwFlags = LocalProfileInfo.HWPI_dwFlags;
4741 
4742         if (WideCharToMultiByte(CP_ACP,
4743                                 0,
4744                                 LocalProfileInfo.HWPI_szFriendlyName,
4745                                 lstrlenW(LocalProfileInfo.HWPI_szFriendlyName) + 1,
4746                                 pHWProfileInfo->HWPI_szFriendlyName,
4747                                 MAX_PROFILE_LEN,
4748                                 NULL,
4749                                 NULL) == 0)
4750             ret = CR_FAILURE;
4751     }
4752 
4753     return ret;
4754 }
4755 
4756 
4757 /***********************************************************************
4758  * CM_Get_Hardware_Profile_Info_ExW [SETUPAPI.@]
4759  */
4760 CONFIGRET
4761 WINAPI
4762 CM_Get_Hardware_Profile_Info_ExW(
4763     _In_ ULONG ulIndex,
4764     _Out_ PHWPROFILEINFO_W pHWProfileInfo,
4765     _In_ ULONG ulFlags,
4766     _In_opt_ HMACHINE hMachine)
4767 {
4768     RPC_BINDING_HANDLE BindingHandle = NULL;
4769     CONFIGRET ret;
4770 
4771     TRACE("CM_Get_Hardware_Profile_Info_ExW(%lu %p %lx %p)\n",
4772           ulIndex, pHWProfileInfo, ulFlags, hMachine);
4773 
4774     if (pHWProfileInfo == NULL)
4775         return CR_INVALID_POINTER;
4776 
4777     if (ulFlags != 0)
4778         return CR_INVALID_FLAG;
4779 
4780     if (hMachine != NULL)
4781     {
4782         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4783         if (BindingHandle == NULL)
4784             return CR_FAILURE;
4785     }
4786     else
4787     {
4788         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4789             return CR_FAILURE;
4790     }
4791 
4792     RpcTryExcept
4793     {
4794         ret = PNP_GetHwProfInfo(BindingHandle, ulIndex, pHWProfileInfo,
4795                                 sizeof(HWPROFILEINFO_W), 0);
4796     }
4797     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4798     {
4799         ret = RpcStatusToCmStatus(RpcExceptionCode());
4800     }
4801     RpcEndExcept;
4802 
4803     return ret;
4804 }
4805 
4806 
4807 /***********************************************************************
4808  * CM_Get_Log_Conf_Priority [SETUPAPI.@]
4809  */
4810 CONFIGRET
4811 WINAPI
4812 CM_Get_Log_Conf_Priority(
4813     _In_ LOG_CONF lcLogConf,
4814     _Out_ PPRIORITY pPriority,
4815     _In_ ULONG ulFlags)
4816 {
4817     TRACE("CM_Get_Log_Conf_Priority(%p %p %lx)\n",
4818           lcLogConf, pPriority, ulFlags);
4819 
4820     return CM_Get_Log_Conf_Priority_Ex(lcLogConf, pPriority, ulFlags, NULL);
4821 }
4822 
4823 
4824 /***********************************************************************
4825  * CM_Get_Log_Conf_Priority_Ex [SETUPAPI.@]
4826  */
4827 CONFIGRET
4828 WINAPI
4829 CM_Get_Log_Conf_Priority_Ex(
4830     _In_ LOG_CONF lcLogConf,
4831     _Out_ PPRIORITY pPriority,
4832     _In_ ULONG ulFlags,
4833     _In_opt_ HMACHINE hMachine)
4834 {
4835     RPC_BINDING_HANDLE BindingHandle = NULL;
4836     HSTRING_TABLE StringTable = NULL;
4837     PLOG_CONF_INFO pLogConfInfo;
4838     LPWSTR lpDevInst;
4839     CONFIGRET ret;
4840 
4841     FIXME("CM_Get_Log_Conf_Priority_Ex(%p %p %lx %p)\n",
4842           lcLogConf, pPriority, ulFlags, hMachine);
4843 
4844     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
4845     if (!IsValidLogConf(pLogConfInfo))
4846         return CR_INVALID_LOG_CONF;
4847 
4848     if (pPriority == NULL)
4849         return CR_INVALID_POINTER;
4850 
4851     if (ulFlags != 0)
4852         return CR_INVALID_FLAG;
4853 
4854     if (hMachine != NULL)
4855     {
4856         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4857         if (BindingHandle == NULL)
4858             return CR_FAILURE;
4859 
4860         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
4861         if (StringTable == 0)
4862             return CR_FAILURE;
4863     }
4864     else
4865     {
4866         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
4867             return CR_FAILURE;
4868     }
4869 
4870     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
4871     if (lpDevInst == NULL)
4872         return CR_INVALID_DEVNODE;
4873 
4874     RpcTryExcept
4875     {
4876         ret = PNP_GetLogConfPriority(BindingHandle,
4877                                      lpDevInst,
4878                                      pLogConfInfo->ulFlags,
4879                                      pLogConfInfo->ulTag,
4880                                      pPriority,
4881                                      0);
4882     }
4883     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4884     {
4885         ret = RpcStatusToCmStatus(RpcExceptionCode());
4886     }
4887     RpcEndExcept;
4888 
4889     return ret;
4890 }
4891 
4892 
4893 /***********************************************************************
4894  * CM_Get_Next_Log_Conf [SETUPAPI.@]
4895  */
4896 CONFIGRET
4897 WINAPI
4898 CM_Get_Next_Log_Conf(
4899     _Out_opt_ PLOG_CONF plcLogConf,
4900     _In_ LOG_CONF lcLogConf,
4901     _In_ ULONG ulFlags)
4902 {
4903     TRACE("CM_Get_Next_Log_Conf(%p %p %lx)\n",
4904           plcLogConf, lcLogConf, ulFlags);
4905 
4906     return CM_Get_Next_Log_Conf_Ex(plcLogConf, lcLogConf, ulFlags, NULL);
4907 }
4908 
4909 
4910 /***********************************************************************
4911  * CM_Get_Next_Log_Conf_Ex [SETUPAPI.@]
4912  */
4913 CONFIGRET
4914 WINAPI
4915 CM_Get_Next_Log_Conf_Ex(
4916     _Out_opt_ PLOG_CONF plcLogConf,
4917     _In_ LOG_CONF lcLogConf,
4918     _In_ ULONG ulFlags,
4919     _In_opt_ HMACHINE hMachine)
4920 {
4921     RPC_BINDING_HANDLE BindingHandle = NULL;
4922     HSTRING_TABLE StringTable = NULL;
4923     PLOG_CONF_INFO pLogConfInfo;
4924     PLOG_CONF_INFO pNewLogConfInfo;
4925     ULONG ulNewTag;
4926     LPWSTR lpDevInst;
4927     CONFIGRET ret;
4928 
4929     FIXME("CM_Get_Next_Log_Conf_Ex(%p %p %lx %p)\n",
4930           plcLogConf, lcLogConf, ulFlags, hMachine);
4931 
4932     if (plcLogConf)
4933         *plcLogConf = 0;
4934 
4935     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
4936     if (!IsValidLogConf(pLogConfInfo))
4937         return CR_INVALID_LOG_CONF;
4938 
4939     if (ulFlags != 0)
4940         return CR_INVALID_FLAG;
4941 
4942     if (hMachine != NULL)
4943     {
4944         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4945         if (BindingHandle == NULL)
4946             return CR_FAILURE;
4947 
4948         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
4949         if (StringTable == 0)
4950             return CR_FAILURE;
4951     }
4952     else
4953     {
4954         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
4955             return CR_FAILURE;
4956     }
4957 
4958     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
4959     if (lpDevInst == NULL)
4960         return CR_INVALID_DEVNODE;
4961 
4962     RpcTryExcept
4963     {
4964         ret = PNP_GetNextLogConf(BindingHandle,
4965                                  lpDevInst,
4966                                  pLogConfInfo->ulFlags,
4967                                  pLogConfInfo->ulTag,
4968                                  &ulNewTag,
4969                                  0);
4970     }
4971     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4972     {
4973         ret = RpcStatusToCmStatus(RpcExceptionCode());
4974     }
4975     RpcEndExcept;
4976 
4977     if (ret != CR_SUCCESS)
4978         return ret;
4979 
4980     if (plcLogConf)
4981     {
4982         pNewLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
4983         if (pNewLogConfInfo == NULL)
4984             return CR_OUT_OF_MEMORY;
4985 
4986         pNewLogConfInfo->ulMagic = LOG_CONF_MAGIC;
4987         pNewLogConfInfo->dnDevInst = pLogConfInfo->dnDevInst;
4988         pNewLogConfInfo->ulFlags = pLogConfInfo->ulFlags;
4989         pNewLogConfInfo->ulTag = ulNewTag;
4990 
4991         *plcLogConf = (LOG_CONF)pNewLogConfInfo;
4992     }
4993 
4994     return CR_SUCCESS;
4995 }
4996 
4997 
4998 /***********************************************************************
4999  * CM_Get_Next_Re_Des [SETUPAPI.@]
5000  */
5001 CONFIGRET
5002 WINAPI
5003 CM_Get_Next_Res_Des(
5004     _Out_ PRES_DES prdResDes,
5005     _In_ RES_DES rdResDes,
5006     _In_ RESOURCEID ForResource,
5007     _Out_opt_ PRESOURCEID pResourceID,
5008     _In_ ULONG ulFlags)
5009 {
5010     TRACE("CM_Get_Next_Res_Des(%p %p %lu %p %lx)\n",
5011           prdResDes, rdResDes, ForResource, pResourceID, ulFlags);
5012 
5013     return CM_Get_Next_Res_Des_Ex(prdResDes, rdResDes, ForResource,
5014                                   pResourceID, ulFlags, NULL);
5015 }
5016 
5017 
5018 /***********************************************************************
5019  * CM_Get_Next_Re_Des_Ex [SETUPAPI.@]
5020  */
5021 CONFIGRET
5022 WINAPI
5023 CM_Get_Next_Res_Des_Ex(
5024     _Out_ PRES_DES prdResDes,
5025     _In_ RES_DES rdResDes,
5026     _In_ RESOURCEID ForResource,
5027     _Out_opt_ PRESOURCEID pResourceID,
5028     _In_ ULONG ulFlags,
5029     _In_opt_ HMACHINE hMachine)
5030 {
5031     FIXME("CM_Get_Next_Res_Des_Ex(%p %p %lu %p %lx %p)\n",
5032           prdResDes, rdResDes, ForResource, pResourceID, ulFlags, hMachine);
5033 
5034     return CR_CALL_NOT_IMPLEMENTED;
5035 }
5036 
5037 
5038 /***********************************************************************
5039  * CM_Get_Parent [SETUPAPI.@]
5040  */
5041 CONFIGRET
5042 WINAPI
5043 CM_Get_Parent(
5044     _Out_ PDEVINST pdnDevInst,
5045     _In_ DEVINST dnDevInst,
5046     _In_ ULONG ulFlags)
5047 {
5048     TRACE("CM_Get_Parent(%p %p %lx)\n",
5049           pdnDevInst, dnDevInst, ulFlags);
5050 
5051     return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
5052 }
5053 
5054 
5055 /***********************************************************************
5056  * CM_Get_Parent_Ex [SETUPAPI.@]
5057  */
5058 CONFIGRET
5059 WINAPI
5060 CM_Get_Parent_Ex(
5061     _Out_ PDEVINST pdnDevInst,
5062     _In_ DEVINST dnDevInst,
5063     _In_ ULONG ulFlags,
5064     _In_opt_ HMACHINE hMachine)
5065 {
5066     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
5067     RPC_BINDING_HANDLE BindingHandle = NULL;
5068     HSTRING_TABLE StringTable = NULL;
5069     LPWSTR lpDevInst;
5070     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
5071     CONFIGRET ret;
5072 
5073     TRACE("CM_Get_Parent_Ex(%p %lx %lx %p)\n",
5074           pdnDevInst, dnDevInst, ulFlags, hMachine);
5075 
5076     if (pdnDevInst == NULL)
5077         return CR_INVALID_POINTER;
5078 
5079     if (dnDevInst == 0)
5080         return CR_INVALID_DEVINST;
5081 
5082     if (ulFlags != 0)
5083         return CR_INVALID_FLAG;
5084 
5085     *pdnDevInst = -1;
5086 
5087     if (hMachine != NULL)
5088     {
5089         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5090         if (BindingHandle == NULL)
5091             return CR_FAILURE;
5092 
5093         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5094         if (StringTable == 0)
5095             return CR_FAILURE;
5096     }
5097     else
5098     {
5099         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5100             return CR_FAILURE;
5101     }
5102 
5103     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
5104     if (lpDevInst == NULL)
5105         return CR_INVALID_DEVNODE;
5106 
5107     RpcTryExcept
5108     {
5109         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
5110                                            PNP_GET_PARENT_DEVICE_INSTANCE,
5111                                            lpDevInst,
5112                                            szRelatedDevInst,
5113                                            &dwLength,
5114                                            0);
5115     }
5116     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5117     {
5118         ret = RpcStatusToCmStatus(RpcExceptionCode());
5119     }
5120     RpcEndExcept;
5121 
5122     if (ret != CR_SUCCESS)
5123         return ret;
5124 
5125     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
5126 
5127     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
5128     if (dwIndex == -1)
5129         return CR_FAILURE;
5130 
5131     *pdnDevInst = dwIndex;
5132 
5133     return CR_SUCCESS;
5134 }
5135 
5136 
5137 /***********************************************************************
5138  * CM_Get_Res_Des_Data [SETUPAPI.@]
5139  */
5140 CONFIGRET
5141 WINAPI
5142 CM_Get_Res_Des_Data(
5143     _In_ RES_DES rdResDes,
5144     _Out_writes_bytes_(BufferLen) PVOID Buffer,
5145     _In_ ULONG BufferLen,
5146     _In_ ULONG ulFlags)
5147 {
5148     TRACE("CM_Get_Res_Des_Data(%p %p %lu %lx)\n",
5149           rdResDes, Buffer, BufferLen, ulFlags);
5150 
5151     return CM_Get_Res_Des_Data_Ex(rdResDes, Buffer, BufferLen, ulFlags, NULL);
5152 }
5153 
5154 
5155 /***********************************************************************
5156  * CM_Get_Res_Des_Data_Ex [SETUPAPI.@]
5157  */
5158 CONFIGRET
5159 WINAPI
5160 CM_Get_Res_Des_Data_Ex(
5161     _In_ RES_DES rdResDes,
5162     _Out_writes_bytes_(BufferLen) PVOID Buffer,
5163     _In_ ULONG BufferLen,
5164     _In_ ULONG ulFlags,
5165     _In_opt_ HMACHINE hMachine)
5166 {
5167     FIXME("CM_Get_Res_Des_Data_Ex(%p %p %lu %lx %p)\n",
5168           rdResDes, Buffer, BufferLen, ulFlags, hMachine);
5169 
5170     return CR_CALL_NOT_IMPLEMENTED;
5171 }
5172 
5173 
5174 /***********************************************************************
5175  * CM_Get_Res_Des_Size [SETUPAPI.@]
5176  */
5177 CONFIGRET
5178 WINAPI
5179 CM_Get_Res_Des_Data_Size(
5180     _Out_ PULONG pulSize,
5181     _In_ RES_DES rdResDes,
5182     _In_ ULONG ulFlags)
5183 {
5184     TRACE("CM_Get_Res_Des_Data_Size(%p %p %lx)\n",
5185           pulSize, rdResDes, ulFlags);
5186 
5187     return CM_Get_Res_Des_Data_Size_Ex(pulSize, rdResDes, ulFlags, NULL);
5188 }
5189 
5190 
5191 /***********************************************************************
5192  * CM_Get_Res_Des_Size_Ex [SETUPAPI.@]
5193  */
5194 CONFIGRET
5195 WINAPI
5196 CM_Get_Res_Des_Data_Size_Ex(
5197     _Out_ PULONG pulSize,
5198     _In_ RES_DES rdResDes,
5199     _In_ ULONG ulFlags,
5200     _In_opt_ HMACHINE hMachine)
5201 {
5202     TRACE("CM_Get_Res_Des_Data_Size_Ex(%p %p %lx %p)\n",
5203           pulSize, rdResDes, ulFlags, hMachine);
5204 
5205     return CR_CALL_NOT_IMPLEMENTED;
5206 }
5207 
5208 
5209 /***********************************************************************
5210  * CM_Get_Resource_Conflict_Count [SETUPAPI.@]
5211  */
5212 CONFIGRET
5213 WINAPI
5214 CM_Get_Resource_Conflict_Count(
5215     _In_ CONFLICT_LIST clConflictList,
5216     _Out_ PULONG pulCount)
5217 {
5218     PCONFLICT_DATA pConflictData;
5219 
5220     FIXME("CM_Get_Resource_Conflict_Count(%p %p)\n",
5221           clConflictList, pulCount);
5222 
5223     pConflictData = (PCONFLICT_DATA)clConflictList;
5224     if (!IsValidConflictData(pConflictData))
5225         return CR_INVALID_CONFLICT_LIST;
5226 
5227     if (pulCount == NULL)
5228         return CR_INVALID_POINTER;
5229 
5230     *pulCount = pConflictData->pConflictList->ConflictsListed;
5231 
5232     return CR_SUCCESS;
5233 }
5234 
5235 
5236 /***********************************************************************
5237  * CM_Get_Resource_Conflict_DetailsA [SETUPAPI.@]
5238  */
5239 CONFIGRET
5240 WINAPI
5241 CM_Get_Resource_Conflict_DetailsA(
5242     _In_ CONFLICT_LIST clConflictList,
5243     _In_ ULONG ulIndex,
5244     _Inout_ PCONFLICT_DETAILS_A pConflictDetails)
5245 {
5246     FIXME("CM_Get_Resource_Conflict_CountA(%p %lu %p)\n",
5247           clConflictList, ulIndex, pConflictDetails);
5248 
5249     return CR_CALL_NOT_IMPLEMENTED;
5250 }
5251 
5252 
5253 /***********************************************************************
5254  * CM_Get_Resource_Conflict_DetailsW [SETUPAPI.@]
5255  */
5256 CONFIGRET
5257 WINAPI
5258 CM_Get_Resource_Conflict_DetailsW(
5259     _In_ CONFLICT_LIST clConflictList,
5260     _In_ ULONG ulIndex,
5261     _Inout_ PCONFLICT_DETAILS_W pConflictDetails)
5262 {
5263     FIXME("CM_Get_Resource_Conflict_CountW(%p %lu %p)\n",
5264           clConflictList, ulIndex, pConflictDetails);
5265 
5266     return CR_CALL_NOT_IMPLEMENTED;
5267 }
5268 
5269 
5270 /***********************************************************************
5271  * CM_Get_Sibling [SETUPAPI.@]
5272  */
5273 CONFIGRET
5274 WINAPI
5275 CM_Get_Sibling(
5276     _Out_ PDEVINST pdnDevInst,
5277     _In_ DEVINST dnDevInst,
5278     _In_ ULONG ulFlags)
5279 {
5280     TRACE("CM_Get_Sibling(%p %p %lx)\n",
5281           pdnDevInst, dnDevInst, ulFlags);
5282 
5283     return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
5284 }
5285 
5286 
5287 /***********************************************************************
5288  * CM_Get_Sibling_Ex [SETUPAPI.@]
5289  */
5290 CONFIGRET
5291 WINAPI
5292 CM_Get_Sibling_Ex(
5293     _Out_ PDEVINST pdnDevInst,
5294     _In_ DEVINST dnDevInst,
5295     _In_ ULONG ulFlags,
5296     _In_opt_ HMACHINE hMachine)
5297 {
5298     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
5299     RPC_BINDING_HANDLE BindingHandle = NULL;
5300     HSTRING_TABLE StringTable = NULL;
5301     LPWSTR lpDevInst;
5302     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
5303     CONFIGRET ret;
5304 
5305     TRACE("CM_Get_Sibling_Ex(%p %lx %lx %p)\n",
5306           pdnDevInst, dnDevInst, ulFlags, hMachine);
5307 
5308     if (pdnDevInst == NULL)
5309         return CR_INVALID_POINTER;
5310 
5311     if (dnDevInst == 0)
5312         return CR_INVALID_DEVINST;
5313 
5314     if (ulFlags != 0)
5315         return CR_INVALID_FLAG;
5316 
5317     *pdnDevInst = -1;
5318 
5319     if (hMachine != NULL)
5320     {
5321         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5322         if (BindingHandle == NULL)
5323             return CR_FAILURE;
5324 
5325         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5326         if (StringTable == 0)
5327             return CR_FAILURE;
5328     }
5329     else
5330     {
5331         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5332             return CR_FAILURE;
5333     }
5334 
5335     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
5336     if (lpDevInst == NULL)
5337         return CR_INVALID_DEVNODE;
5338 
5339     RpcTryExcept
5340     {
5341         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
5342                                            PNP_GET_SIBLING_DEVICE_INSTANCE,
5343                                            lpDevInst,
5344                                            szRelatedDevInst,
5345                                            &dwLength,
5346                                            0);
5347     }
5348     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5349     {
5350         ret = RpcStatusToCmStatus(RpcExceptionCode());
5351     }
5352     RpcEndExcept;
5353 
5354     if (ret != CR_SUCCESS)
5355         return ret;
5356 
5357     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
5358 
5359     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
5360     if (dwIndex == -1)
5361         return CR_FAILURE;
5362 
5363     *pdnDevInst = dwIndex;
5364 
5365     return CR_SUCCESS;
5366 }
5367 
5368 
5369 /***********************************************************************
5370  * CM_Get_Version [SETUPAPI.@]
5371  */
5372 WORD
5373 WINAPI
5374 CM_Get_Version(VOID)
5375 {
5376     TRACE("CM_Get_Version()\n");
5377 
5378     return CM_Get_Version_Ex(NULL);
5379 }
5380 
5381 
5382 /***********************************************************************
5383  * CM_Get_Version_Ex [SETUPAPI.@]
5384  */
5385 WORD
5386 WINAPI
5387 CM_Get_Version_Ex(
5388     _In_opt_ HMACHINE hMachine)
5389 {
5390     RPC_BINDING_HANDLE BindingHandle = NULL;
5391     WORD Version = 0;
5392     CONFIGRET ret;
5393 
5394     TRACE("CM_Get_Version_Ex(%p)\n", hMachine);
5395 
5396     if (hMachine != NULL)
5397     {
5398         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5399         if (BindingHandle == NULL)
5400             return 0;
5401     }
5402     else
5403     {
5404         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5405             return CR_FAILURE;
5406     }
5407 
5408     RpcTryExcept
5409     {
5410         ret = PNP_GetVersion(BindingHandle, &Version);
5411     }
5412     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5413     {
5414         ret = RpcStatusToCmStatus(RpcExceptionCode());
5415     }
5416     RpcEndExcept;
5417 
5418     if (ret != CR_SUCCESS)
5419         return 0;
5420 
5421     return Version;
5422 }
5423 
5424 
5425 /***********************************************************************
5426  * CM_Intersect_Range_List [SETUPAPI.@]
5427  */
5428 CONFIGRET
5429 WINAPI
5430 CM_Intersect_Range_List(
5431     _In_ RANGE_LIST rlhOld1,
5432     _In_ RANGE_LIST rlhOld2,
5433     _In_ RANGE_LIST rlhNew,
5434     _In_ ULONG ulFlags)
5435 {
5436     FIXME("CM_Intersect_Range_List(%p %p %p %lx)\n",
5437           rlhOld1, rlhOld2, rlhNew, ulFlags);
5438 
5439     return CR_CALL_NOT_IMPLEMENTED;
5440 }
5441 
5442 
5443 /***********************************************************************
5444  * CM_Invert_Range_List [SETUPAPI.@]
5445  */
5446 CONFIGRET
5447 WINAPI
5448 CM_Invert_Range_List(
5449     _In_ RANGE_LIST rlhOld,
5450     _In_ RANGE_LIST rlhNew,
5451     _In_ DWORDLONG ullMaxValue,
5452     _In_ ULONG ulFlags)
5453 {
5454     FIXME("CM_Invert_Range_List(%p %p %I64u %lx)\n",
5455           rlhOld, rlhNew, ullMaxValue, ulFlags);
5456 
5457     return CR_CALL_NOT_IMPLEMENTED;
5458 }
5459 
5460 
5461 /***********************************************************************
5462  * CM_Is_Dock_Station_Present [SETUPAPI.@]
5463  */
5464 CONFIGRET
5465 WINAPI
5466 CM_Is_Dock_Station_Present(
5467     _Out_ PBOOL pbPresent)
5468 {
5469     TRACE("CM_Is_Dock_Station_Present(%p)\n",
5470           pbPresent);
5471 
5472     return CM_Is_Dock_Station_Present_Ex(pbPresent, NULL);
5473 }
5474 
5475 
5476 /***********************************************************************
5477  * CM_Is_Dock_Station_Present_Ex [SETUPAPI.@]
5478  */
5479 CONFIGRET
5480 WINAPI
5481 CM_Is_Dock_Station_Present_Ex(
5482     _Out_ PBOOL pbPresent,
5483     _In_opt_ HMACHINE hMachine)
5484 {
5485     RPC_BINDING_HANDLE BindingHandle = NULL;
5486     CONFIGRET ret;
5487 
5488     TRACE("CM_Is_Dock_Station_Present_Ex(%p %p)\n",
5489           pbPresent, hMachine);
5490 
5491     if (pbPresent == NULL)
5492         return CR_INVALID_POINTER;
5493 
5494     *pbPresent = FALSE;
5495 
5496     if (hMachine != NULL)
5497     {
5498         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5499         if (BindingHandle == NULL)
5500             return CR_FAILURE;
5501     }
5502     else
5503     {
5504         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5505             return CR_FAILURE;
5506     }
5507 
5508     RpcTryExcept
5509     {
5510         ret = PNP_IsDockStationPresent(BindingHandle,
5511                                        pbPresent);
5512     }
5513     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5514     {
5515         ret = RpcStatusToCmStatus(RpcExceptionCode());
5516     }
5517     RpcEndExcept;
5518 
5519     return ret;
5520 }
5521 
5522 
5523 /***********************************************************************
5524  * CM_Is_Version_Available_Ex [SETUPAPI.@]
5525  */
5526 BOOL
5527 WINAPI
5528 CM_Is_Version_Available(
5529      _In_ WORD wVersion)
5530 {
5531     TRACE("CM_Is_Version_Available(%hu)\n",
5532           wVersion);
5533 
5534     return CM_Is_Version_Available_Ex(wVersion, NULL);
5535 }
5536 
5537 
5538 /***********************************************************************
5539  * CM_Is_Version_Available_Ex [SETUPAPI.@]
5540  */
5541 BOOL
5542 WINAPI
5543 CM_Is_Version_Available_Ex(
5544     _In_ WORD wVersion,
5545     _In_opt_ HMACHINE hMachine)
5546 {
5547     RPC_BINDING_HANDLE BindingHandle = NULL;
5548     WORD wServerVersion;
5549     CONFIGRET ret;
5550 
5551     TRACE("CM_Is_Version_Available_Ex(%hu %p)\n",
5552           wVersion, hMachine);
5553 
5554     if (wVersion <= 0x400)
5555         return TRUE;
5556 
5557     if (hMachine != NULL)
5558     {
5559         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5560         if (BindingHandle == NULL)
5561             return FALSE;
5562     }
5563     else
5564     {
5565         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5566             return FALSE;
5567     }
5568 
5569     RpcTryExcept
5570     {
5571         ret = PNP_GetVersion(BindingHandle, &wServerVersion);
5572     }
5573     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5574     {
5575         ret = RpcStatusToCmStatus(RpcExceptionCode());
5576     }
5577     RpcEndExcept;
5578 
5579     if (ret != CR_SUCCESS)
5580         return FALSE;
5581 
5582     return (wServerVersion >= wVersion);
5583 }
5584 
5585 
5586 /***********************************************************************
5587  * CM_Locate_DevNodeA [SETUPAPI.@]
5588  */
5589 CONFIGRET
5590 WINAPI
5591 CM_Locate_DevNodeA(
5592     _Out_ PDEVINST pdnDevInst,
5593     _In_opt_ DEVINSTID_A pDeviceID,
5594     _In_ ULONG ulFlags)
5595 {
5596     TRACE("CM_Locate_DevNodeA(%p %s %lx)\n",
5597           pdnDevInst, debugstr_a(pDeviceID), ulFlags);
5598 
5599     return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
5600 }
5601 
5602 
5603 /***********************************************************************
5604  * CM_Locate_DevNodeW [SETUPAPI.@]
5605  */
5606 CONFIGRET
5607 WINAPI
5608 CM_Locate_DevNodeW(
5609     _Out_ PDEVINST pdnDevInst,
5610     _In_opt_ DEVINSTID_W pDeviceID,
5611     _In_ ULONG ulFlags)
5612 {
5613     TRACE("CM_Locate_DevNodeW(%p %s %lx)\n",
5614           pdnDevInst, debugstr_w(pDeviceID), ulFlags);
5615 
5616     return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
5617 }
5618 
5619 
5620 /***********************************************************************
5621  * CM_Locate_DevNode_ExA [SETUPAPI.@]
5622  */
5623 CONFIGRET
5624 WINAPI
5625 CM_Locate_DevNode_ExA(
5626     _Out_ PDEVINST pdnDevInst,
5627     _In_opt_ DEVINSTID_A pDeviceID,
5628     _In_ ULONG ulFlags,
5629     _In_opt_ HMACHINE hMachine)
5630 {
5631     DEVINSTID_W pDevIdW = NULL;
5632     CONFIGRET ret = CR_SUCCESS;
5633 
5634     TRACE("CM_Locate_DevNode_ExA(%p %s %lx %p)\n",
5635           pdnDevInst, debugstr_a(pDeviceID), ulFlags, hMachine);
5636 
5637     if (pDeviceID != NULL)
5638     {
5639        if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDevIdW))
5640          return CR_INVALID_DEVICE_ID;
5641     }
5642 
5643     ret = CM_Locate_DevNode_ExW(pdnDevInst, pDevIdW, ulFlags, hMachine);
5644 
5645     if (pDevIdW != NULL)
5646         MyFree(pDevIdW);
5647 
5648     return ret;
5649 }
5650 
5651 
5652 /***********************************************************************
5653  * CM_Locate_DevNode_ExW [SETUPAPI.@]
5654  */
5655 CONFIGRET
5656 WINAPI
5657 CM_Locate_DevNode_ExW(
5658     _Out_ PDEVINST pdnDevInst,
5659     _In_opt_ DEVINSTID_W pDeviceID,
5660     _In_ ULONG ulFlags,
5661     _In_opt_ HMACHINE hMachine)
5662 {
5663     WCHAR DeviceIdBuffer[MAX_DEVICE_ID_LEN];
5664     RPC_BINDING_HANDLE BindingHandle = NULL;
5665     HSTRING_TABLE StringTable = NULL;
5666     CONFIGRET ret = CR_SUCCESS;
5667 
5668     TRACE("CM_Locate_DevNode_ExW(%p %s %lx %p)\n",
5669           pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
5670 
5671     if (pdnDevInst == NULL)
5672         return CR_INVALID_POINTER;
5673 
5674     if (ulFlags & ~CM_LOCATE_DEVNODE_BITS)
5675         return CR_INVALID_FLAG;
5676 
5677     if (hMachine != NULL)
5678     {
5679         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5680         if (BindingHandle == NULL)
5681             return CR_FAILURE;
5682 
5683         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5684         if (StringTable == 0)
5685             return CR_FAILURE;
5686     }
5687     else
5688     {
5689         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5690             return CR_FAILURE;
5691     }
5692 
5693     if (pDeviceID != NULL && lstrlenW(pDeviceID) != 0)
5694     {
5695         lstrcpyW(DeviceIdBuffer, pDeviceID);
5696     }
5697     else
5698     {
5699         RpcTryExcept
5700         {
5701             /* Get the root device ID */
5702             ret = PNP_GetRootDeviceInstance(BindingHandle,
5703                                             DeviceIdBuffer,
5704                                             MAX_DEVICE_ID_LEN);
5705         }
5706         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5707         {
5708             ret = RpcStatusToCmStatus(RpcExceptionCode());
5709         }
5710         RpcEndExcept;
5711 
5712         if (ret != CR_SUCCESS)
5713             return CR_FAILURE;
5714     }
5715     TRACE("DeviceIdBuffer: %s\n", debugstr_w(DeviceIdBuffer));
5716 
5717     RpcTryExcept
5718     {
5719         /* Validate the device ID */
5720         ret = PNP_ValidateDeviceInstance(BindingHandle,
5721                                          DeviceIdBuffer,
5722                                          ulFlags);
5723     }
5724     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5725     {
5726         ret = RpcStatusToCmStatus(RpcExceptionCode());
5727     }
5728     RpcEndExcept;
5729 
5730     if (ret == CR_SUCCESS)
5731     {
5732         *pdnDevInst = pSetupStringTableAddString(StringTable, DeviceIdBuffer, 1);
5733         if (*pdnDevInst == -1)
5734             ret = CR_FAILURE;
5735     }
5736 
5737     return ret;
5738 }
5739 
5740 
5741 /***********************************************************************
5742  * CM_Merge_Range_List [SETUPAPI.@]
5743  */
5744 CONFIGRET
5745 WINAPI
5746 CM_Merge_Range_List(
5747     _In_ RANGE_LIST rlhOld1,
5748     _In_ RANGE_LIST rlhOld2,
5749     _In_ RANGE_LIST rlhNew,
5750     _In_ ULONG ulFlags)
5751 {
5752     FIXME("CM_Merge_Range_List(%p %p %p %lx)\n",
5753           rlhOld1, rlhOld2, rlhNew, ulFlags);
5754 
5755     return CR_CALL_NOT_IMPLEMENTED;
5756 }
5757 
5758 
5759 /***********************************************************************
5760  * CM_Modify_Res_Des [SETUPAPI.@]
5761  */
5762 CONFIGRET
5763 WINAPI
5764 CM_Modify_Res_Des(
5765     _Out_ PRES_DES prdResDes,
5766     _In_ RES_DES rdResDes,
5767     _In_ RESOURCEID ResourceID,
5768     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
5769     _In_ ULONG ResourceLen,
5770     _In_ ULONG ulFlags)
5771 {
5772     TRACE("CM_Modify_Res_Des(%p %p %lx %p %lu %lx)\n",
5773           prdResDes, rdResDes, ResourceID, ResourceData,
5774           ResourceLen, ulFlags);
5775 
5776     return CM_Modify_Res_Des_Ex(prdResDes, rdResDes, ResourceID, ResourceData,
5777                                 ResourceLen, ulFlags, NULL);
5778 }
5779 
5780 
5781 /***********************************************************************
5782  * CM_Modify_Res_Des_Ex [SETUPAPI.@]
5783  */
5784 CONFIGRET
5785 WINAPI
5786 CM_Modify_Res_Des_Ex(
5787     _Out_ PRES_DES prdResDes,
5788     _In_ RES_DES rdResDes,
5789     _In_ RESOURCEID ResourceID,
5790     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
5791     _In_ ULONG ResourceLen,
5792     _In_ ULONG ulFlags,
5793     _In_opt_ HMACHINE hMachine)
5794 {
5795     FIXME("CM_Modify_Res_Des_Ex(%p %p %lx %p %lu %lx %p)\n",
5796           prdResDes, rdResDes, ResourceID, ResourceData,
5797           ResourceLen, ulFlags, hMachine);
5798 
5799     return CR_CALL_NOT_IMPLEMENTED;
5800 }
5801 
5802 
5803 /***********************************************************************
5804  * CM_Move_DevNode [SETUPAPI.@]
5805  */
5806 CONFIGRET
5807 WINAPI
5808 CM_Move_DevNode(
5809     _In_ DEVINST dnFromDevInst,
5810     _In_ DEVINST dnToDevInst,
5811     _In_ ULONG ulFlags)
5812 {
5813     TRACE("CM_Move_DevNode(%lx %lx %lx)\n",
5814           dnFromDevInst, dnToDevInst, ulFlags);
5815 
5816     return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
5817 }
5818 
5819 
5820 /***********************************************************************
5821  * CM_Move_DevNode_Ex [SETUPAPI.@]
5822  */
5823 CONFIGRET
5824 WINAPI
5825 CM_Move_DevNode_Ex(
5826     _In_ DEVINST dnFromDevInst,
5827     _In_ DEVINST dnToDevInst,
5828     _In_ ULONG ulFlags,
5829     _In_opt_ HMACHINE hMachine)
5830 {
5831     RPC_BINDING_HANDLE BindingHandle = NULL;
5832     HSTRING_TABLE StringTable = NULL;
5833     LPWSTR lpFromDevInst;
5834     LPWSTR lpToDevInst;
5835     CONFIGRET ret;
5836 
5837     FIXME("CM_Move_DevNode_Ex(%lx %lx %lx %p)\n",
5838           dnFromDevInst, dnToDevInst, ulFlags, hMachine);
5839 
5840     if (!pSetupIsUserAdmin())
5841         return CR_ACCESS_DENIED;
5842 
5843     if (dnFromDevInst == 0 || dnToDevInst == 0)
5844         return CR_INVALID_DEVNODE;
5845 
5846     if (ulFlags != 0)
5847         return CR_INVALID_FLAG;
5848 
5849     if (hMachine != NULL)
5850     {
5851         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5852         if (BindingHandle == NULL)
5853             return CR_FAILURE;
5854 
5855         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5856         if (StringTable == 0)
5857             return CR_FAILURE;
5858     }
5859     else
5860     {
5861         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5862             return CR_FAILURE;
5863     }
5864 
5865     lpFromDevInst = pSetupStringTableStringFromId(StringTable, dnFromDevInst);
5866     if (lpFromDevInst == NULL)
5867         return CR_INVALID_DEVNODE;
5868 
5869     lpToDevInst = pSetupStringTableStringFromId(StringTable, dnToDevInst);
5870     if (lpToDevInst == NULL)
5871         return CR_INVALID_DEVNODE;
5872 
5873     RpcTryExcept
5874     {
5875         ret = PNP_DeviceInstanceAction(BindingHandle,
5876                                        PNP_DEVINST_MOVE,
5877                                        ulFlags,
5878                                        lpFromDevInst,
5879                                        lpToDevInst);
5880     }
5881     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5882     {
5883         ret = RpcStatusToCmStatus(RpcExceptionCode());
5884     }
5885     RpcEndExcept;
5886 
5887     return ret;
5888 }
5889 
5890 
5891 /***********************************************************************
5892  * CM_Next_Range [SETUPAPI.@]
5893  */
5894 CONFIGRET
5895 WINAPI
5896 CM_Next_Range(
5897     _Inout_ PRANGE_ELEMENT preElement,
5898     _Out_ PDWORDLONG pullStart,
5899     _Out_ PDWORDLONG pullEnd,
5900     _In_ ULONG ulFlags)
5901 {
5902     FIXME("CM_Next_Range(%p %p %p %lx)\n",
5903           preElement, pullStart, pullEnd, ulFlags);
5904 
5905     return CR_CALL_NOT_IMPLEMENTED;
5906 }
5907 
5908 
5909 /***********************************************************************
5910  * CM_Open_Class_KeyA [SETUPAPI.@]
5911  */
5912 CONFIGRET
5913 WINAPI
5914 CM_Open_Class_KeyA(
5915     _In_opt_ LPGUID pClassGuid,
5916     _In_opt_ LPCSTR pszClassName,
5917     _In_ REGSAM samDesired,
5918     _In_ REGDISPOSITION Disposition,
5919     _Out_ PHKEY phkClass,
5920     _In_ ULONG ulFlags)
5921 {
5922     TRACE("CM_Open_Class_KeyA(%p %s %lx %lx %p %lx)\n",
5923           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
5924           samDesired, Disposition, phkClass, ulFlags);
5925 
5926     return CM_Open_Class_Key_ExA(pClassGuid, pszClassName, samDesired,
5927                                  Disposition, phkClass, ulFlags, NULL);
5928 }
5929 
5930 
5931 /***********************************************************************
5932  * CM_Open_Class_KeyW [SETUPAPI.@]
5933  */
5934 CONFIGRET
5935 WINAPI
5936 CM_Open_Class_KeyW(
5937     _In_opt_ LPGUID pClassGuid,
5938     _In_opt_ LPCWSTR pszClassName,
5939     _In_ REGSAM samDesired,
5940     _In_ REGDISPOSITION Disposition,
5941     _Out_ PHKEY phkClass,
5942     _In_ ULONG ulFlags)
5943 {
5944     TRACE("CM_Open_Class_KeyW%p %s %lx %lx %p %lx)\n",
5945           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
5946           samDesired, Disposition, phkClass, ulFlags);
5947 
5948     return CM_Open_Class_Key_ExW(pClassGuid, pszClassName, samDesired,
5949                                  Disposition, phkClass, ulFlags, NULL);
5950 }
5951 
5952 
5953 /***********************************************************************
5954  * CM_Open_Class_Key_ExA [SETUPAPI.@]
5955  */
5956 CONFIGRET
5957 WINAPI
5958 CM_Open_Class_Key_ExA(
5959     _In_opt_ LPGUID pClassGuid,
5960     _In_opt_ LPCSTR pszClassName,
5961     _In_ REGSAM samDesired,
5962     _In_ REGDISPOSITION Disposition,
5963     _Out_ PHKEY phkClass,
5964     _In_ ULONG ulFlags,
5965     _In_opt_ HMACHINE hMachine)
5966 {
5967     LPWSTR pszClassNameW = NULL;
5968     CONFIGRET ret;
5969 
5970     TRACE("CM_Open_Class_Key_ExA(%p %s %lx %lx %p %lx %p)\n",
5971           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
5972           samDesired, Disposition, phkClass, ulFlags, hMachine);
5973 
5974     if (pszClassName != NULL)
5975     {
5976        if (pSetupCaptureAndConvertAnsiArg(pszClassName, &pszClassNameW))
5977          return CR_INVALID_DATA;
5978     }
5979 
5980     ret = CM_Open_Class_Key_ExW(pClassGuid, pszClassNameW, samDesired,
5981                                 Disposition, phkClass, ulFlags, hMachine);
5982 
5983     if (pszClassNameW != NULL)
5984         MyFree(pszClassNameW);
5985 
5986     return ret;
5987 }
5988 
5989 
5990 /***********************************************************************
5991  * CM_Open_Class_Key_ExW [SETUPAPI.@]
5992  */
5993 CONFIGRET
5994 WINAPI
5995 CM_Open_Class_Key_ExW(
5996     _In_opt_ LPGUID pClassGuid,
5997     _In_opt_ LPCWSTR pszClassName,
5998     _In_ REGSAM samDesired,
5999     _In_ REGDISPOSITION Disposition,
6000     _Out_ PHKEY phkClass,
6001     _In_ ULONG ulFlags,
6002     _In_opt_ HMACHINE hMachine)
6003 {
6004     WCHAR szKeyName[MAX_PATH];
6005     LPWSTR lpGuidString;
6006     DWORD dwDisposition;
6007     DWORD dwError;
6008     HKEY hKey;
6009 
6010     TRACE("CM_Open_Class_Key_ExW(%p %s %lx %lx %p %lx %p)\n",
6011           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
6012           samDesired, Disposition, phkClass, ulFlags, hMachine);
6013 
6014     /* Check Disposition and ulFlags */
6015     if ((Disposition & ~RegDisposition_Bits) ||
6016         (ulFlags & ~CM_OPEN_CLASS_KEY_BITS))
6017         return CR_INVALID_FLAG;
6018 
6019     /* Check phkClass */
6020     if (phkClass == NULL)
6021         return CR_INVALID_POINTER;
6022 
6023     *phkClass = NULL;
6024 
6025     if (ulFlags == CM_OPEN_CLASS_KEY_INTERFACE &&
6026         pszClassName != NULL)
6027         return CR_INVALID_DATA;
6028 
6029     if (hMachine == NULL)
6030     {
6031         hKey = HKEY_LOCAL_MACHINE;
6032     }
6033     else
6034     {
6035         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6036                                 HKEY_LOCAL_MACHINE,
6037                                 &hKey))
6038             return CR_REGISTRY_ERROR;
6039     }
6040 
6041     if (ulFlags & CM_OPEN_CLASS_KEY_INTERFACE)
6042     {
6043         lstrcpyW(szKeyName, DeviceClasses);
6044     }
6045     else
6046     {
6047         lstrcpyW(szKeyName, ControlClass);
6048     }
6049 
6050     if (pClassGuid != NULL)
6051     {
6052         if (UuidToStringW((UUID*)pClassGuid, &lpGuidString) != RPC_S_OK)
6053         {
6054             RegCloseKey(hKey);
6055             return CR_INVALID_DATA;
6056         }
6057 
6058         lstrcatW(szKeyName, Backslash);
6059         lstrcatW(szKeyName, lpGuidString);
6060     }
6061 
6062     if (Disposition == RegDisposition_OpenAlways)
6063     {
6064         dwError = RegCreateKeyExW(hKey, szKeyName, 0, NULL, 0, samDesired,
6065                                   NULL, phkClass, &dwDisposition);
6066     }
6067     else
6068     {
6069         dwError = RegOpenKeyExW(hKey, szKeyName, 0, samDesired, phkClass);
6070     }
6071 
6072     RegCloseKey(hKey);
6073 
6074     if (pClassGuid != NULL)
6075         RpcStringFreeW(&lpGuidString);
6076 
6077     if (dwError != ERROR_SUCCESS)
6078     {
6079         *phkClass = NULL;
6080         return CR_NO_SUCH_REGISTRY_KEY;
6081     }
6082 
6083     if (pszClassName != NULL)
6084     {
6085         RegSetValueExW(*phkClass, Class, 0, REG_SZ, (LPBYTE)pszClassName,
6086                        (lstrlenW(pszClassName) + 1) * sizeof(WCHAR));
6087     }
6088 
6089     return CR_SUCCESS;
6090 }
6091 
6092 
6093 /***********************************************************************
6094  * CM_Open_DevNode_Key [SETUPAPI.@]
6095  */
6096 CONFIGRET
6097 WINAPI
6098 CM_Open_DevNode_Key(
6099     _In_ DEVINST dnDevNode,
6100     _In_ REGSAM samDesired,
6101     _In_ ULONG ulHardwareProfile,
6102     _In_ REGDISPOSITION Disposition,
6103     _Out_ PHKEY phkDevice,
6104     _In_ ULONG ulFlags)
6105 {
6106     TRACE("CM_Open_DevNode_Key(%lx %lx %lu %lx %p %lx)\n",
6107           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags);
6108 
6109     return CM_Open_DevNode_Key_Ex(dnDevNode, samDesired, ulHardwareProfile,
6110                                   Disposition, phkDevice, ulFlags, NULL);
6111 }
6112 
6113 
6114 /***********************************************************************
6115  * CM_Open_DevNode_Key_Ex [SETUPAPI.@]
6116  */
6117 CONFIGRET
6118 WINAPI
6119 CM_Open_DevNode_Key_Ex(
6120     _In_ DEVINST dnDevNode,
6121     _In_ REGSAM samDesired,
6122     _In_ ULONG ulHardwareProfile,
6123     _In_ REGDISPOSITION Disposition,
6124     _Out_ PHKEY phkDevice,
6125     _In_ ULONG ulFlags,
6126     _In_opt_ HMACHINE hMachine)
6127 {
6128     RPC_BINDING_HANDLE BindingHandle = NULL;
6129     HSTRING_TABLE StringTable = NULL;
6130     LPWSTR pszDevInst, pszKeyPath = NULL, pszInstancePath = NULL;
6131     LONG lError;
6132     DWORD dwDisposition;
6133     HKEY hRootKey = NULL;
6134     CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
6135 
6136     TRACE("CM_Open_DevNode_Key_Ex(%lx %lx %lu %lx %p %lx %p)\n",
6137           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags, hMachine);
6138 
6139     if (phkDevice == NULL)
6140         return CR_INVALID_POINTER;
6141 
6142     *phkDevice = NULL;
6143 
6144     if (dnDevNode == 0)
6145         return CR_INVALID_DEVNODE;
6146 
6147     if (ulFlags & ~CM_REGISTRY_BITS)
6148         return CR_INVALID_FLAG;
6149 
6150     if (Disposition & ~RegDisposition_Bits)
6151         return CR_INVALID_DATA;
6152 
6153     if (hMachine != NULL)
6154     {
6155         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6156         if (BindingHandle == NULL)
6157             return CR_FAILURE;
6158 
6159         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6160         if (StringTable == 0)
6161             return CR_FAILURE;
6162     }
6163     else
6164     {
6165         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6166             return CR_FAILURE;
6167     }
6168 
6169     pszDevInst = pSetupStringTableStringFromId(StringTable, dnDevNode);
6170     if (pszDevInst == NULL)
6171         return CR_INVALID_DEVNODE;
6172 
6173     TRACE("pszDevInst: %S\n", pszDevInst);
6174 
6175     pszKeyPath = MyMalloc(512 * sizeof(WCHAR));
6176     if (pszKeyPath == NULL)
6177     {
6178         ret = CR_OUT_OF_MEMORY;
6179         goto done;
6180     }
6181 
6182     pszInstancePath = MyMalloc(512 * sizeof(WCHAR));
6183     if (pszInstancePath == NULL)
6184     {
6185         ret = CR_OUT_OF_MEMORY;
6186         goto done;
6187     }
6188 
6189     ret = GetDeviceInstanceKeyPath(BindingHandle,
6190                                    pszDevInst,
6191                                    pszKeyPath,
6192                                    pszInstancePath,
6193                                    ulHardwareProfile,
6194                                    ulFlags);
6195     if (ret != CR_SUCCESS)
6196         goto done;
6197 
6198     TRACE("pszKeyPath: %S\n", pszKeyPath);
6199     TRACE("pszInstancePath: %S\n", pszInstancePath);
6200 
6201     wcscat(pszKeyPath, L"\\");
6202     wcscat(pszKeyPath, pszInstancePath);
6203 
6204     TRACE("pszKeyPath: %S\n", pszKeyPath);
6205 
6206     if (hMachine == NULL)
6207     {
6208         hRootKey = HKEY_LOCAL_MACHINE;
6209     }
6210     else
6211     {
6212         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6213                                 HKEY_LOCAL_MACHINE,
6214                                 &hRootKey))
6215         {
6216             ret = CR_REGISTRY_ERROR;
6217             goto done;
6218         }
6219     }
6220 
6221     if (Disposition == RegDisposition_OpenAlways)
6222     {
6223         lError = RegCreateKeyExW(hRootKey,
6224                                  pszKeyPath,
6225                                  0,
6226                                  NULL,
6227                                  0,
6228                                  samDesired,
6229                                  NULL,
6230                                  phkDevice,
6231                                  &dwDisposition);
6232     }
6233     else
6234     {
6235         lError = RegOpenKeyExW(hRootKey,
6236                                pszKeyPath,
6237                                0,
6238                                samDesired,
6239                                phkDevice);
6240     }
6241 
6242     if (lError != ERROR_SUCCESS)
6243     {
6244         *phkDevice = NULL;
6245         ret = CR_NO_SUCH_REGISTRY_KEY;
6246     }
6247 
6248 done:
6249     if ((hRootKey != NULL) && (hRootKey != HKEY_LOCAL_MACHINE))
6250         RegCloseKey(hRootKey);
6251 
6252     if (pszInstancePath != NULL)
6253         MyFree(pszInstancePath);
6254 
6255     if (pszKeyPath != NULL)
6256         MyFree(pszKeyPath);
6257 
6258     return ret;
6259 }
6260 
6261 
6262 /***********************************************************************
6263  * CM_Query_And_Remove_SubTreeA [SETUPAPI.@]
6264  */
6265 CONFIGRET
6266 WINAPI
6267 CM_Query_And_Remove_SubTreeA(
6268     _In_ DEVINST dnAncestor,
6269     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6270     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6271     _In_ ULONG ulNameLength,
6272     _In_ ULONG ulFlags)
6273 {
6274     TRACE("CM_Query_And_Remove_SubTreeA(%lx %p %s %lu %lx)\n",
6275           dnAncestor, pVetoType, pszVetoName, ulNameLength, ulFlags);
6276 
6277     return CM_Query_And_Remove_SubTree_ExA(dnAncestor, pVetoType, pszVetoName,
6278                                            ulNameLength, ulFlags, NULL);
6279 }
6280 
6281 
6282 /***********************************************************************
6283  * CM_Query_And_Remove_SubTreeW [SETUPAPI.@]
6284  */
6285 CONFIGRET
6286 WINAPI
6287 CM_Query_And_Remove_SubTreeW(
6288     _In_ DEVINST dnAncestor,
6289     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6290     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6291     _In_ ULONG ulNameLength,
6292     _In_ ULONG ulFlags)
6293 {
6294     TRACE("CM_Query_And_Remove_SubTreeW(%lx %p %s %lu %lx)\n",
6295           dnAncestor, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags);
6296 
6297     return CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, pszVetoName,
6298                                            ulNameLength, ulFlags, NULL);
6299 }
6300 
6301 
6302 /***********************************************************************
6303  * CM_Query_And_Remove_SubTree_ExA [SETUPAPI.@]
6304  */
6305 CONFIGRET
6306 WINAPI
6307 CM_Query_And_Remove_SubTree_ExA(
6308     _In_ DEVINST dnAncestor,
6309     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6310     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6311     _In_ ULONG ulNameLength,
6312     _In_ ULONG ulFlags,
6313     _In_opt_ HMACHINE hMachine)
6314 {
6315     LPWSTR lpLocalVetoName;
6316     CONFIGRET ret;
6317 
6318     TRACE("CM_Query_And_Remove_SubTree_ExA(%lx %p %s %lu %lx %p)\n",
6319           dnAncestor, pVetoType, debugstr_a(pszVetoName), ulNameLength,
6320           ulFlags, hMachine);
6321 
6322     if (pszVetoName == NULL && ulNameLength == 0)
6323         return CR_INVALID_POINTER;
6324 
6325     lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
6326     if (lpLocalVetoName == NULL)
6327         return CR_OUT_OF_MEMORY;
6328 
6329     ret = CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, lpLocalVetoName,
6330                                           ulNameLength, ulFlags, hMachine);
6331     if (ret == CR_REMOVE_VETOED)
6332     {
6333         if (WideCharToMultiByte(CP_ACP,
6334                                 0,
6335                                 lpLocalVetoName,
6336                                 ulNameLength,
6337                                 pszVetoName,
6338                                 ulNameLength,
6339                                 NULL,
6340                                 NULL) == 0)
6341             ret = CR_FAILURE;
6342     }
6343 
6344     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
6345 
6346     return ret;
6347 }
6348 
6349 
6350 /***********************************************************************
6351  * CM_Query_And_Remove_SubTree_ExW [SETUPAPI.@]
6352  */
6353 CONFIGRET
6354 WINAPI
6355 CM_Query_And_Remove_SubTree_ExW(
6356     _In_ DEVINST dnAncestor,
6357     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6358     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6359     _In_ ULONG ulNameLength,
6360     _In_ ULONG ulFlags,
6361     _In_opt_ HMACHINE hMachine)
6362 {
6363     RPC_BINDING_HANDLE BindingHandle = NULL;
6364     HSTRING_TABLE StringTable = NULL;
6365     LPWSTR lpDevInst;
6366     CONFIGRET ret;
6367 
6368     TRACE("CM_Query_And_Remove_SubTree_ExW(%lx %p %s %lu %lx %p)\n",
6369           dnAncestor, pVetoType, debugstr_w(pszVetoName), ulNameLength,
6370           ulFlags, hMachine);
6371 
6372     if (dnAncestor == 0)
6373         return CR_INVALID_DEVNODE;
6374 
6375     if (ulFlags & ~CM_REMOVE_BITS)
6376         return CR_INVALID_FLAG;
6377 
6378     if (pszVetoName == NULL && ulNameLength == 0)
6379         return CR_INVALID_POINTER;
6380 
6381     if (hMachine != NULL)
6382     {
6383         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6384         if (BindingHandle == NULL)
6385             return CR_FAILURE;
6386 
6387         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6388         if (StringTable == 0)
6389             return CR_FAILURE;
6390     }
6391     else
6392     {
6393         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6394             return CR_FAILURE;
6395     }
6396 
6397     lpDevInst = pSetupStringTableStringFromId(StringTable, dnAncestor);
6398     if (lpDevInst == NULL)
6399         return CR_INVALID_DEVNODE;
6400 
6401     RpcTryExcept
6402     {
6403         ret = PNP_QueryRemove(BindingHandle,
6404                               lpDevInst,
6405                               pVetoType,
6406                               pszVetoName,
6407                               ulNameLength,
6408                               ulFlags);
6409     }
6410     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6411     {
6412         ret = RpcStatusToCmStatus(RpcExceptionCode());
6413     }
6414     RpcEndExcept;
6415 
6416     return ret;
6417 }
6418 
6419 
6420 /***********************************************************************
6421  * CM_Query_Arbitrator_Free_Data [SETUPAPI.@]
6422  */
6423 CONFIGRET
6424 WINAPI
6425 CM_Query_Arbitrator_Free_Data(
6426     _Out_writes_bytes_(DataLen) PVOID pData,
6427     _In_ ULONG DataLen,
6428     _In_ DEVINST dnDevInst,
6429     _In_ RESOURCEID ResourceID,
6430     _In_ ULONG ulFlags)
6431 {
6432     TRACE("CM_Query_Arbitrator_Free_Data(%p %lu %lx %lu 0x%08lx)\n",
6433           pData, DataLen, dnDevInst, ResourceID, ulFlags);
6434 
6435     return CM_Query_Arbitrator_Free_Data_Ex(pData, DataLen, dnDevInst,
6436                                             ResourceID, ulFlags, NULL);
6437 }
6438 
6439 
6440 /***********************************************************************
6441  * CM_Query_Arbitrator_Free_Data_Ex [SETUPAPI.@]
6442  */
6443 CONFIGRET
6444 WINAPI
6445 CM_Query_Arbitrator_Free_Data_Ex(
6446     _Out_writes_bytes_(DataLen) PVOID pData,
6447     _In_ ULONG DataLen,
6448     _In_ DEVINST dnDevInst,
6449     _In_ RESOURCEID ResourceID,
6450     _In_ ULONG ulFlags,
6451     _In_opt_ HMACHINE hMachine)
6452 {
6453     RPC_BINDING_HANDLE BindingHandle = NULL;
6454     HSTRING_TABLE StringTable = NULL;
6455     LPWSTR lpDevInst;
6456     CONFIGRET ret;
6457 
6458     TRACE("CM_Query_Arbitrator_Free_Data_Ex(%p %lu %lx %lu 0x%08lx %p)\n",
6459           pData, DataLen, dnDevInst, ResourceID, ulFlags, hMachine);
6460 
6461     if (pData == NULL || DataLen == 0)
6462         return CR_INVALID_POINTER;
6463 
6464     if (dnDevInst == 0)
6465         return CR_INVALID_DEVINST;
6466 
6467     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6468         return CR_INVALID_FLAG;
6469 
6470     if (hMachine != NULL)
6471     {
6472         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6473         if (BindingHandle == NULL)
6474             return CR_FAILURE;
6475 
6476         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6477         if (StringTable == 0)
6478             return CR_FAILURE;
6479     }
6480     else
6481     {
6482         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6483             return CR_FAILURE;
6484     }
6485 
6486     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6487     if (lpDevInst == NULL)
6488         return CR_INVALID_DEVNODE;
6489 
6490     RpcTryExcept
6491     {
6492         ret = PNP_QueryArbitratorFreeData(BindingHandle,
6493                                           pData,
6494                                           DataLen,
6495                                           lpDevInst,
6496                                           ResourceID,
6497                                           ulFlags);
6498     }
6499     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6500     {
6501         ret = RpcStatusToCmStatus(RpcExceptionCode());
6502     }
6503     RpcEndExcept;
6504 
6505     return ret;
6506 }
6507 
6508 
6509 /***********************************************************************
6510  * CM_Query_Arbitrator_Free_Size [SETUPAPI.@]
6511  */
6512 CONFIGRET
6513 WINAPI
6514 CM_Query_Arbitrator_Free_Size(
6515     _Out_ PULONG pulSize,
6516     _In_ DEVINST dnDevInst,
6517     _In_ RESOURCEID ResourceID,
6518     _In_ ULONG ulFlags)
6519 {
6520     TRACE("CM_Query_Arbitrator_Free_Size(%p %lu %lx 0x%08lx)\n",
6521           pulSize, dnDevInst,ResourceID, ulFlags);
6522 
6523     return CM_Query_Arbitrator_Free_Size_Ex(pulSize, dnDevInst, ResourceID,
6524                                             ulFlags, NULL);
6525 }
6526 
6527 
6528 /***********************************************************************
6529  * CM_Query_Arbitrator_Free_Size_Ex [SETUPAPI.@]
6530  */
6531 CONFIGRET
6532 WINAPI
6533 CM_Query_Arbitrator_Free_Size_Ex(
6534     _Out_ PULONG pulSize,
6535     _In_ DEVINST dnDevInst,
6536     _In_ RESOURCEID ResourceID,
6537     _In_ ULONG ulFlags,
6538     _In_opt_ HMACHINE hMachine)
6539 {
6540     RPC_BINDING_HANDLE BindingHandle = NULL;
6541     HSTRING_TABLE StringTable = NULL;
6542     LPWSTR lpDevInst;
6543     CONFIGRET ret;
6544 
6545     TRACE("CM_Query_Arbitrator_Free_Size_Ex(%p %lu %lx 0x%08lx %p)\n",
6546           pulSize, dnDevInst,ResourceID, ulFlags, hMachine);
6547 
6548     if (pulSize == NULL)
6549         return CR_INVALID_POINTER;
6550 
6551     if (dnDevInst == 0)
6552         return CR_INVALID_DEVINST;
6553 
6554     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6555         return CR_INVALID_FLAG;
6556 
6557     if (hMachine != NULL)
6558     {
6559         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6560         if (BindingHandle == NULL)
6561             return CR_FAILURE;
6562 
6563         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6564         if (StringTable == 0)
6565             return CR_FAILURE;
6566     }
6567     else
6568     {
6569         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6570             return CR_FAILURE;
6571     }
6572 
6573     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6574     if (lpDevInst == NULL)
6575         return CR_INVALID_DEVNODE;
6576 
6577     RpcTryExcept
6578     {
6579         ret = PNP_QueryArbitratorFreeSize(BindingHandle,
6580                                           pulSize,
6581                                           lpDevInst,
6582                                           ResourceID,
6583                                           ulFlags);
6584     }
6585     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6586     {
6587         ret = RpcStatusToCmStatus(RpcExceptionCode());
6588     }
6589     RpcEndExcept;
6590 
6591     return ret;
6592 }
6593 
6594 
6595 /***********************************************************************
6596  * CM_Query_Remove_SubTree [SETUPAPI.@]
6597  *
6598  * This function is obsolete in Windows XP and above.
6599  */
6600 CONFIGRET
6601 WINAPI
6602 CM_Query_Remove_SubTree(
6603     _In_ DEVINST dnAncestor,
6604     _In_ ULONG ulFlags)
6605 {
6606     TRACE("CM_Query_Remove_SubTree(%lx %lx)\n",
6607           dnAncestor, ulFlags);
6608 
6609     return CR_CALL_NOT_IMPLEMENTED;
6610 }
6611 
6612 
6613 /***********************************************************************
6614  * CM_Query_Remove_SubTree_Ex [SETUPAPI.@]
6615  *
6616  * This function is obsolete in Windows XP and above.
6617  */
6618 CONFIGRET
6619 WINAPI
6620 CM_Query_Remove_SubTree_Ex(
6621     _In_ DEVINST dnAncestor,
6622     _In_ ULONG ulFlags,
6623     _In_opt_ HMACHINE hMachine)
6624 {
6625     TRACE("CM_Query_Remove_SubTree_Ex(%lx %lx %p)\n",
6626           dnAncestor, ulFlags, hMachine);
6627 
6628     return CR_CALL_NOT_IMPLEMENTED;
6629 }
6630 
6631 
6632 /***********************************************************************
6633  * CM_Query_Resource_Conflict_List [SETUPAPI.@]
6634  */
6635 CONFIGRET
6636 WINAPI
6637 CM_Query_Resource_Conflict_List(
6638     _Out_ PCONFLICT_LIST pclConflictList,
6639     _In_ DEVINST dnDevInst,
6640     _In_ RESOURCEID ResourceID,
6641     _In_ PCVOID ResourceData,
6642     _In_ ULONG ResourceLen,
6643     _In_ ULONG ulFlags,
6644     _In_opt_ HMACHINE hMachine)
6645 {
6646     RPC_BINDING_HANDLE BindingHandle = NULL;
6647     HSTRING_TABLE StringTable = NULL;
6648     PPNP_CONFLICT_LIST pConflictBuffer = NULL;
6649     PCONFLICT_DATA pConflictData = NULL;
6650     ULONG ulBufferLength;
6651     LPWSTR lpDevInst;
6652     CONFIGRET ret;
6653 
6654     FIXME("CM_Query_Resource_Conflict_List(%p %lx %lu %p %lu %lx %p)\n",
6655           pclConflictList, dnDevInst, ResourceID, ResourceData,
6656           ResourceLen, ulFlags, hMachine);
6657 
6658     if (dnDevInst == 0)
6659         return CR_INVALID_DEVNODE;
6660 
6661     if (ulFlags & ~CM_RESDES_WIDTH_BITS)
6662         return CR_INVALID_FLAG;
6663 
6664     if (pclConflictList == NULL ||
6665         ResourceData == NULL ||
6666         ResourceLen == 0)
6667         return CR_INVALID_POINTER;
6668 
6669     if (ResourceID == 0)
6670         return CR_INVALID_RESOURCEID;
6671 
6672     *pclConflictList = 0;
6673 
6674     if (hMachine != NULL)
6675     {
6676         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6677         if (BindingHandle == NULL)
6678             return CR_FAILURE;
6679 
6680         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6681         if (StringTable == 0)
6682             return CR_FAILURE;
6683     }
6684     else
6685     {
6686         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6687             return CR_FAILURE;
6688     }
6689 
6690     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6691     if (lpDevInst == NULL)
6692         return CR_INVALID_DEVNODE;
6693 
6694     pConflictData = MyMalloc(sizeof(CONFLICT_DATA));
6695     if (pConflictData == NULL)
6696     {
6697         ret = CR_OUT_OF_MEMORY;
6698         goto done;
6699     }
6700 
6701     ulBufferLength = sizeof(PNP_CONFLICT_LIST) +
6702                      sizeof(PNP_CONFLICT_STRINGS) +
6703                      (sizeof(wchar_t) * 200);
6704     pConflictBuffer = MyMalloc(ulBufferLength);
6705     if (pConflictBuffer == NULL)
6706     {
6707         ret = CR_OUT_OF_MEMORY;
6708         goto done;
6709     }
6710 
6711     RpcTryExcept
6712     {
6713         ret = PNP_QueryResConfList(BindingHandle,
6714                                    lpDevInst,
6715                                    ResourceID,
6716                                    (PBYTE)ResourceData,
6717                                    ResourceLen,
6718                                    (PBYTE)pConflictBuffer,
6719                                    ulBufferLength,
6720                                    ulFlags);
6721     }
6722     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6723     {
6724         ret = RpcStatusToCmStatus(RpcExceptionCode());
6725     }
6726     RpcEndExcept;
6727 
6728     if (ret != CR_SUCCESS)
6729         goto done;
6730 
6731     pConflictData->ulMagic = CONFLICT_MAGIC;
6732     pConflictData->pConflictList = pConflictBuffer;
6733 
6734     *pclConflictList = (CONFLICT_LIST)pConflictData;
6735 
6736 done:
6737     if (ret != CR_SUCCESS)
6738     {
6739         if (pConflictBuffer != NULL)
6740             MyFree(pConflictBuffer);
6741 
6742         if (pConflictData != NULL)
6743             MyFree(pConflictData);
6744     }
6745 
6746     return ret;
6747 }
6748 
6749 
6750 /***********************************************************************
6751  * CM_Reenumerate_DevNode [SETUPAPI.@]
6752  */
6753 CONFIGRET
6754 WINAPI
6755 CM_Reenumerate_DevNode(
6756     _In_ DEVINST dnDevInst,
6757     _In_ ULONG ulFlags)
6758 {
6759     TRACE("CM_Reenumerate_DevNode(%lx %lx)\n",
6760           dnDevInst, ulFlags);
6761 
6762     return CM_Reenumerate_DevNode_Ex(dnDevInst, ulFlags, NULL);
6763 }
6764 
6765 
6766 /***********************************************************************
6767  * CM_Reenumerate_DevNode_Ex [SETUPAPI.@]
6768  */
6769 CONFIGRET WINAPI
6770 CM_Reenumerate_DevNode_Ex(
6771     _In_ DEVINST dnDevInst,
6772     _In_ ULONG ulFlags,
6773     _In_opt_ HMACHINE hMachine)
6774 {
6775     RPC_BINDING_HANDLE BindingHandle = NULL;
6776     HSTRING_TABLE StringTable = NULL;
6777     LPWSTR lpDevInst;
6778     CONFIGRET ret;
6779 
6780     FIXME("CM_Reenumerate_DevNode_Ex(%lx %lx %p)\n",
6781           dnDevInst, ulFlags, hMachine);
6782 
6783     if (dnDevInst == 0)
6784         return CR_INVALID_DEVNODE;
6785 
6786     if (ulFlags & ~CM_REENUMERATE_BITS)
6787         return CR_INVALID_FLAG;
6788 
6789     if (hMachine != NULL)
6790     {
6791         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6792         if (BindingHandle == NULL)
6793             return CR_FAILURE;
6794 
6795         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6796         if (StringTable == 0)
6797             return CR_FAILURE;
6798     }
6799     else
6800     {
6801         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6802             return CR_FAILURE;
6803     }
6804 
6805     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6806     if (lpDevInst == NULL)
6807         return CR_INVALID_DEVNODE;
6808 
6809     RpcTryExcept
6810     {
6811         ret = PNP_DeviceInstanceAction(BindingHandle,
6812                                        PNP_DEVINST_REENUMERATE,
6813                                        ulFlags,
6814                                        lpDevInst,
6815                                        NULL);
6816     }
6817     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6818     {
6819         ret = RpcStatusToCmStatus(RpcExceptionCode());
6820     }
6821     RpcEndExcept;
6822 
6823     return ret;
6824 }
6825 
6826 
6827 /***********************************************************************
6828  * CM_Register_Device_Driver [SETUPAPI.@]
6829  */
6830 CONFIGRET
6831 WINAPI
6832 CM_Register_Device_Driver(
6833     _In_ DEVINST dnDevInst,
6834     _In_ ULONG ulFlags)
6835 {
6836     TRACE("CM_Register_Device_Driver(%lx 0x%08lx)\n",
6837           dnDevInst, ulFlags);
6838 
6839     return CM_Register_Device_Driver_Ex(dnDevInst, ulFlags, NULL);
6840 }
6841 
6842 
6843 /***********************************************************************
6844  * CM_Register_Device_Driver_Ex [SETUPAPI.@]
6845  */
6846 CONFIGRET
6847 WINAPI
6848 CM_Register_Device_Driver_Ex(
6849     _In_ DEVINST dnDevInst,
6850     _In_ ULONG ulFlags,
6851     _In_opt_ HMACHINE hMachine)
6852 {
6853     RPC_BINDING_HANDLE BindingHandle = NULL;
6854     HSTRING_TABLE StringTable = NULL;
6855     LPWSTR lpDevInst;
6856     CONFIGRET ret;
6857 
6858     TRACE("CM_Register_Device_Driver_Ex(%lx 0x%08lx %p)\n",
6859           dnDevInst, ulFlags, hMachine);
6860 
6861     if (dnDevInst == 0)
6862         return CR_INVALID_DEVNODE;
6863 
6864     if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
6865         return CR_INVALID_FLAG;
6866 
6867     if (hMachine != NULL)
6868     {
6869         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6870         if (BindingHandle == NULL)
6871             return CR_FAILURE;
6872 
6873         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6874         if (StringTable == 0)
6875             return CR_FAILURE;
6876     }
6877     else
6878     {
6879         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6880             return CR_FAILURE;
6881     }
6882 
6883     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6884     if (lpDevInst == NULL)
6885         return CR_INVALID_DEVNODE;
6886 
6887     RpcTryExcept
6888     {
6889         ret = PNP_RegisterDriver(BindingHandle,
6890                                  lpDevInst,
6891                                  ulFlags);
6892     }
6893     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6894     {
6895         ret = RpcStatusToCmStatus(RpcExceptionCode());
6896     }
6897     RpcEndExcept;
6898 
6899     return ret;
6900 }
6901 
6902 
6903 /***********************************************************************
6904  * CM_Register_Device_InterfaceA [SETUPAPI.@]
6905  */
6906 CONFIGRET
6907 WINAPI
6908 CM_Register_Device_InterfaceA(
6909     _In_ DEVINST dnDevInst,
6910     _In_ LPGUID InterfaceClassGuid,
6911     _In_opt_ LPCSTR pszReference,
6912     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
6913     _Inout_ PULONG pulLength,
6914     _In_ ULONG ulFlags)
6915 {
6916     TRACE("CM_Register_Device_InterfaceA(%lx %s %s %p %p %lx)\n",
6917           dnDevInst, debugstr_guid(InterfaceClassGuid),
6918           pszReference, pszDeviceInterface, pulLength, ulFlags);
6919 
6920     return CM_Register_Device_Interface_ExA(dnDevInst, InterfaceClassGuid,
6921                                             pszReference, pszDeviceInterface,
6922                                             pulLength, ulFlags, NULL);
6923 }
6924 
6925 
6926 /***********************************************************************
6927  * CM_Register_Device_InterfaceW [SETUPAPI.@]
6928  */
6929 CONFIGRET
6930 WINAPI
6931 CM_Register_Device_InterfaceW(
6932     _In_ DEVINST dnDevInst,
6933     _In_ LPGUID InterfaceClassGuid,
6934     _In_opt_ LPCWSTR pszReference,
6935     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
6936     _Inout_ PULONG pulLength,
6937     _In_ ULONG ulFlags)
6938 {
6939     TRACE("CM_Register_Device_InterfaceW(%lx %s %s %p %p %lx)\n",
6940           dnDevInst, debugstr_guid(InterfaceClassGuid),
6941           debugstr_w(pszReference), pszDeviceInterface, pulLength, ulFlags);
6942 
6943     return CM_Register_Device_Interface_ExW(dnDevInst, InterfaceClassGuid,
6944                                             pszReference, pszDeviceInterface,
6945                                             pulLength, ulFlags, NULL);
6946 }
6947 
6948 
6949 /***********************************************************************
6950  * CM_Register_Device_Interface_ExA [SETUPAPI.@]
6951  */
6952 CONFIGRET
6953 WINAPI
6954 CM_Register_Device_Interface_ExA(
6955     _In_ DEVINST dnDevInst,
6956     _In_ LPGUID InterfaceClassGuid,
6957     _In_opt_ LPCSTR pszReference,
6958     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
6959     _Inout_ PULONG pulLength,
6960     _In_ ULONG ulFlags,
6961     _In_opt_ HMACHINE hMachine)
6962 {
6963     LPWSTR pszReferenceW = NULL;
6964     LPWSTR pszDeviceInterfaceW = NULL;
6965     ULONG ulLength;
6966     CONFIGRET ret;
6967 
6968     TRACE("CM_Register_Device_Interface_ExA(%lx %s %s %p %p %lx %p)\n",
6969           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_a(pszReference),
6970           pszDeviceInterface, pulLength, ulFlags, hMachine);
6971 
6972     if (pulLength == NULL || pszDeviceInterface == NULL)
6973         return CR_INVALID_POINTER;
6974 
6975     if (pszReference != NULL)
6976     {
6977         if (pSetupCaptureAndConvertAnsiArg(pszReference, &pszReferenceW))
6978             return CR_INVALID_DATA;
6979     }
6980 
6981     ulLength = *pulLength;
6982 
6983     pszDeviceInterfaceW = HeapAlloc(GetProcessHeap(), 0, ulLength * sizeof(WCHAR));
6984     if (pszDeviceInterfaceW == NULL)
6985     {
6986         ret = CR_OUT_OF_MEMORY;
6987         goto Done;
6988     }
6989 
6990     ret = CM_Register_Device_Interface_ExW(dnDevInst,
6991                                            InterfaceClassGuid,
6992                                            pszReferenceW,
6993                                            pszDeviceInterfaceW,
6994                                            &ulLength,
6995                                            ulFlags,
6996                                            hMachine);
6997     if (ret == CR_SUCCESS)
6998     {
6999         if (WideCharToMultiByte(CP_ACP,
7000                                 0,
7001                                 pszDeviceInterfaceW,
7002                                 ulLength,
7003                                 pszDeviceInterface,
7004                                 *pulLength,
7005                                 NULL,
7006                                 NULL) == 0)
7007             ret = CR_FAILURE;
7008     }
7009 
7010     *pulLength = ulLength;
7011 
7012 Done:
7013     if (pszDeviceInterfaceW != NULL)
7014         HeapFree(GetProcessHeap(), 0, pszDeviceInterfaceW);
7015 
7016     if (pszReferenceW != NULL)
7017         MyFree(pszReferenceW);
7018 
7019     return ret;
7020 }
7021 
7022 
7023 /***********************************************************************
7024  * CM_Register_Device_Interface_ExW [SETUPAPI.@]
7025  */
7026 CONFIGRET
7027 WINAPI
7028 CM_Register_Device_Interface_ExW(
7029     _In_ DEVINST dnDevInst,
7030     _In_ LPGUID InterfaceClassGuid,
7031     _In_opt_ LPCWSTR pszReference,
7032     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
7033     _Inout_ PULONG pulLength,
7034     _In_ ULONG ulFlags,
7035     _In_opt_ HMACHINE hMachine)
7036 {
7037     RPC_BINDING_HANDLE BindingHandle = NULL;
7038     HSTRING_TABLE StringTable = NULL;
7039     LPWSTR lpDevInst;
7040     ULONG ulTransferLength;
7041     CONFIGRET ret;
7042 
7043     TRACE("CM_Register_Device_Interface_ExW(%lx %s %s %p %p %lx %p)\n",
7044           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_w(pszReference),
7045           pszDeviceInterface, pulLength, ulFlags, hMachine);
7046 
7047     if (dnDevInst == 0)
7048         return CR_INVALID_DEVNODE;
7049 
7050     if (InterfaceClassGuid == NULL ||
7051         pszDeviceInterface == NULL ||
7052         pulLength == NULL)
7053         return CR_INVALID_POINTER;
7054 
7055     if (ulFlags != 0)
7056         return CR_INVALID_FLAG;
7057 
7058     if (hMachine != NULL)
7059     {
7060         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7061         if (BindingHandle == NULL)
7062             return CR_FAILURE;
7063 
7064         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7065         if (StringTable == 0)
7066             return CR_FAILURE;
7067     }
7068     else
7069     {
7070         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7071             return CR_FAILURE;
7072     }
7073 
7074     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7075     if (lpDevInst == NULL)
7076         return CR_INVALID_DEVNODE;
7077 
7078     ulTransferLength = *pulLength;
7079 
7080     RpcTryExcept
7081     {
7082         ret = PNP_RegisterDeviceClassAssociation(BindingHandle,
7083                                                  lpDevInst,
7084                                                  InterfaceClassGuid,
7085                                                  (LPWSTR)pszReference,
7086                                                  pszDeviceInterface,
7087                                                  pulLength,
7088                                                  &ulTransferLength,
7089                                                  0);
7090     }
7091     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7092     {
7093         ret = RpcStatusToCmStatus(RpcExceptionCode());
7094     }
7095     RpcEndExcept;
7096 
7097     return ret;
7098 }
7099 
7100 
7101 /***********************************************************************
7102  * CM_Remove_SubTree [SETUPAPI.@]
7103  *
7104  * This function is obsolete in Windows XP and above.
7105  */
7106 CONFIGRET
7107 WINAPI
7108 CM_Remove_SubTree(
7109     _In_ DEVINST dnAncestor,
7110     _In_ ULONG ulFlags)
7111 {
7112     TRACE("CM_Remove_SubTree(%lx %lx)\n",
7113           dnAncestor, ulFlags);
7114 
7115     return CR_CALL_NOT_IMPLEMENTED;
7116 }
7117 
7118 
7119 /***********************************************************************
7120  * CM_Remove_SubTree_Ex [SETUPAPI.@]
7121  *
7122  * This function is obsolete in Windows XP and above.
7123  */
7124 CONFIGRET
7125 WINAPI
7126 CM_Remove_SubTree_Ex(
7127     _In_ DEVINST dnAncestor,
7128     _In_ ULONG ulFlags,
7129     _In_opt_ HMACHINE hMachine)
7130 {
7131     TRACE("CM_Remove_SubTree_Ex(%lx %lx %p)\n",
7132           dnAncestor, ulFlags, hMachine);
7133 
7134     return CR_CALL_NOT_IMPLEMENTED;
7135 }
7136 
7137 
7138 /***********************************************************************
7139  * CM_Request_Device_EjectA [SETUPAPI.@]
7140  */
7141 CONFIGRET
7142 WINAPI
7143 CM_Request_Device_EjectA(
7144     _In_ DEVINST dnDevInst,
7145     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7146     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7147     _In_ ULONG ulNameLength,
7148     _In_ ULONG ulFlags)
7149 {
7150     TRACE("CM_Request_Device_EjectA(%lx %p %s %lu %lx)\n",
7151           dnDevInst, pVetoType, debugstr_a(pszVetoName), ulNameLength, ulFlags);
7152 
7153     return CM_Request_Device_Eject_ExA(dnDevInst, pVetoType, pszVetoName,
7154                                        ulNameLength, ulFlags, NULL);
7155 }
7156 
7157 
7158 /***********************************************************************
7159  * CM_Request_Device_EjectW [SETUPAPI.@]
7160  */
7161 CONFIGRET
7162 WINAPI
7163 CM_Request_Device_EjectW(
7164     _In_ DEVINST dnDevInst,
7165     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7166     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7167     _In_ ULONG ulNameLength,
7168     _In_ ULONG ulFlags)
7169 {
7170     TRACE("CM_Request_Device_EjectW(%lx %p %s %lu %lx)\n",
7171           dnDevInst, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags);
7172 
7173     return CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, pszVetoName,
7174                                        ulNameLength, ulFlags, NULL);
7175 }
7176 
7177 
7178 /***********************************************************************
7179  * CM_Request_Device_Eject_ExA [SETUPAPI.@]
7180  */
7181 CONFIGRET
7182 WINAPI
7183 CM_Request_Device_Eject_ExA(
7184     _In_ DEVINST dnDevInst,
7185     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7186     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7187     _In_ ULONG ulNameLength,
7188     _In_ ULONG ulFlags,
7189     _In_opt_ HMACHINE hMachine)
7190 {
7191     LPWSTR lpLocalVetoName;
7192     CONFIGRET ret;
7193 
7194     TRACE("CM_Request_Device_Eject_ExA(%lx %p %s %lu %lx %p)\n",
7195           dnDevInst, pVetoType, debugstr_a(pszVetoName), ulNameLength, ulFlags, hMachine);
7196 
7197     if (pszVetoName == NULL && ulNameLength == 0)
7198         return CR_INVALID_POINTER;
7199 
7200     lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
7201     if (lpLocalVetoName == NULL)
7202         return CR_OUT_OF_MEMORY;
7203 
7204     ret = CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, lpLocalVetoName,
7205                                       ulNameLength, ulFlags, hMachine);
7206     if (ret == CR_REMOVE_VETOED)
7207     {
7208         if (WideCharToMultiByte(CP_ACP,
7209                                 0,
7210                                 lpLocalVetoName,
7211                                 ulNameLength,
7212                                 pszVetoName,
7213                                 ulNameLength,
7214                                 NULL,
7215                                 NULL) == 0)
7216             ret = CR_FAILURE;
7217     }
7218 
7219     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
7220 
7221     return ret;
7222 }
7223 
7224 
7225 /***********************************************************************
7226  * CM_Request_Device_Eject_ExW [SETUPAPI.@]
7227  */
7228 CONFIGRET
7229 WINAPI
7230 CM_Request_Device_Eject_ExW(
7231     _In_ DEVINST dnDevInst,
7232     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7233     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7234     _In_ ULONG ulNameLength,
7235     _In_ ULONG ulFlags,
7236     _In_opt_ HMACHINE hMachine)
7237 {
7238     RPC_BINDING_HANDLE BindingHandle = NULL;
7239     HSTRING_TABLE StringTable = NULL;
7240     LPWSTR lpDevInst;
7241     CONFIGRET ret;
7242 
7243     TRACE("CM_Request_Device_Eject_ExW(%lx %p %s %lu %lx %p)\n",
7244           dnDevInst, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags, hMachine);
7245 
7246     if (dnDevInst == 0)
7247         return CR_INVALID_DEVNODE;
7248 
7249     if (ulFlags != 0)
7250         return CR_INVALID_FLAG;
7251 
7252     if (pszVetoName == NULL && ulNameLength == 0)
7253         return CR_INVALID_POINTER;
7254 
7255     if (hMachine != NULL)
7256     {
7257         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7258         if (BindingHandle == NULL)
7259             return CR_FAILURE;
7260 
7261         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7262         if (StringTable == 0)
7263             return CR_FAILURE;
7264     }
7265     else
7266     {
7267         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7268             return CR_FAILURE;
7269     }
7270 
7271     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7272     if (lpDevInst == NULL)
7273         return CR_INVALID_DEVNODE;
7274 
7275     RpcTryExcept
7276     {
7277         ret = PNP_RequestDeviceEject(BindingHandle,
7278                                      lpDevInst,
7279                                      pVetoType,
7280                                      pszVetoName,
7281                                      ulNameLength,
7282                                      ulFlags);
7283     }
7284     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7285     {
7286         ret = RpcStatusToCmStatus(RpcExceptionCode());
7287     }
7288     RpcEndExcept;
7289 
7290     return ret;
7291 }
7292 
7293 
7294 /***********************************************************************
7295  * CM_Request_Eject_PC [SETUPAPI.@]
7296  */
7297 CONFIGRET
7298 WINAPI
7299 CM_Request_Eject_PC(VOID)
7300 {
7301     TRACE("CM_Request_Eject_PC()\n");
7302 
7303     return CM_Request_Eject_PC_Ex(NULL);
7304 }
7305 
7306 
7307 /***********************************************************************
7308  * CM_Request_Eject_PC_Ex [SETUPAPI.@]
7309  */
7310 CONFIGRET
7311 WINAPI
7312 CM_Request_Eject_PC_Ex(
7313     _In_opt_ HMACHINE hMachine)
7314 {
7315     RPC_BINDING_HANDLE BindingHandle = NULL;
7316     CONFIGRET ret;
7317 
7318     TRACE("CM_Request_Eject_PC_Ex(%p)\n", hMachine);
7319 
7320     if (hMachine != NULL)
7321     {
7322         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7323         if (BindingHandle == NULL)
7324             return CR_FAILURE;
7325     }
7326     else
7327     {
7328         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7329             return CR_FAILURE;
7330     }
7331 
7332     RpcTryExcept
7333     {
7334         ret = PNP_RequestEjectPC(BindingHandle);
7335     }
7336     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7337     {
7338         ret = RpcStatusToCmStatus(RpcExceptionCode());
7339     }
7340     RpcEndExcept;
7341 
7342     return ret;
7343 }
7344 
7345 
7346 /***********************************************************************
7347  * CM_Run_Detection [SETUPAPI.@]
7348  */
7349 CONFIGRET
7350 WINAPI
7351 CM_Run_Detection(
7352     _In_ ULONG ulFlags)
7353 {
7354     TRACE("CM_Run_Detection(%lx)\n", ulFlags);
7355 
7356     return CM_Run_Detection_Ex(ulFlags, NULL);
7357 }
7358 
7359 
7360 /***********************************************************************
7361  * CM_Run_Detection_Ex [SETUPAPI.@]
7362  */
7363 CONFIGRET
7364 WINAPI
7365 CM_Run_Detection_Ex(
7366     _In_ ULONG ulFlags,
7367     _In_opt_ HMACHINE hMachine)
7368 {
7369     RPC_BINDING_HANDLE BindingHandle = NULL;
7370     CONFIGRET ret;
7371 
7372     TRACE("CM_Run_Detection_Ex(%lx %p)\n",
7373           ulFlags, hMachine);
7374 
7375     if (!pSetupIsUserAdmin())
7376         return CR_ACCESS_DENIED;
7377 
7378     if (ulFlags & ~CM_DETECT_BITS)
7379         return CR_INVALID_FLAG;
7380 
7381     if (hMachine != NULL)
7382     {
7383         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7384         if (BindingHandle == NULL)
7385             return CR_FAILURE;
7386     }
7387     else
7388     {
7389         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7390             return CR_FAILURE;
7391     }
7392 
7393     RpcTryExcept
7394     {
7395         ret = PNP_RunDetection(BindingHandle,
7396                                ulFlags);
7397     }
7398     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7399     {
7400         ret = RpcStatusToCmStatus(RpcExceptionCode());
7401     }
7402     RpcEndExcept;
7403 
7404     return ret;
7405 }
7406 
7407 
7408 /***********************************************************************
7409  * CM_Set_Class_Registry_PropertyA [SETUPAPI.@]
7410  */
7411 CONFIGRET
7412 WINAPI
7413 CM_Set_Class_Registry_PropertyA(
7414     _In_ LPGUID ClassGuid,
7415     _In_ ULONG ulProperty,
7416     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7417     _In_ ULONG ulLength,
7418     _In_ ULONG ulFlags,
7419     _In_opt_ HMACHINE hMachine)
7420 {
7421     FIXME("CM_Set_Class_Registry_PropertyA(%p %lx %p %lu %lx %p)\n",
7422           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7423 
7424     return CR_CALL_NOT_IMPLEMENTED;
7425 }
7426 
7427 
7428 /***********************************************************************
7429  * CM_Set_Class_Registry_PropertyW [SETUPAPI.@]
7430  */
7431 CONFIGRET
7432 WINAPI
7433 CM_Set_Class_Registry_PropertyW(
7434     _In_ LPGUID ClassGuid,
7435     _In_ ULONG ulProperty,
7436     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7437     _In_ ULONG ulLength,
7438     _In_ ULONG ulFlags,
7439     _In_opt_ HMACHINE hMachine)
7440 {
7441     FIXME("CM_Set_Class_Registry_PropertyW(%p %lx %p %lu %lx %p)\n",
7442           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7443 
7444     return CR_CALL_NOT_IMPLEMENTED;
7445 }
7446 
7447 
7448 /***********************************************************************
7449  * CM_Set_DevNode_Problem [SETUPAPI.@]
7450  */
7451 CONFIGRET
7452 WINAPI
7453 CM_Set_DevNode_Problem(
7454     _In_ DEVINST dnDevInst,
7455     _In_ ULONG ulProblem,
7456     _In_ ULONG ulFlags)
7457 {
7458     TRACE("CM_Set_DevNode_Problem(%lx %lx %lx)\n",
7459           dnDevInst, ulProblem, ulFlags);
7460 
7461     return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
7462 }
7463 
7464 
7465 /***********************************************************************
7466  * CM_Set_DevNode_Problem_Ex [SETUPAPI.@]
7467  */
7468 CONFIGRET
7469 WINAPI
7470 CM_Set_DevNode_Problem_Ex(
7471     _In_ DEVINST dnDevInst,
7472     _In_ ULONG ulProblem,
7473     _In_ ULONG ulFlags,
7474     _In_opt_ HMACHINE hMachine)
7475 {
7476     RPC_BINDING_HANDLE BindingHandle = NULL;
7477     HSTRING_TABLE StringTable = NULL;
7478     LPWSTR lpDevInst;
7479     CONFIGRET ret;
7480 
7481     TRACE("CM_Set_DevNode_Problem_Ex(%lx %lx %lx %p)\n",
7482           dnDevInst, ulProblem, ulFlags, hMachine);
7483 
7484     if (dnDevInst == 0)
7485         return CR_INVALID_DEVNODE;
7486 
7487     if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
7488         return CR_INVALID_FLAG;
7489 
7490     if (hMachine != NULL)
7491     {
7492         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7493         if (BindingHandle == NULL)
7494             return CR_FAILURE;
7495 
7496         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7497         if (StringTable == 0)
7498             return CR_FAILURE;
7499     }
7500     else
7501     {
7502         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7503             return CR_FAILURE;
7504     }
7505 
7506     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7507     if (lpDevInst == NULL)
7508         return CR_INVALID_DEVNODE;
7509 
7510     RpcTryExcept
7511     {
7512         ret = PNP_SetDeviceProblem(BindingHandle,
7513                                    lpDevInst,
7514                                    ulProblem,
7515                                    ulFlags);
7516     }
7517     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7518     {
7519         ret = RpcStatusToCmStatus(RpcExceptionCode());
7520     }
7521     RpcEndExcept;
7522 
7523     return ret;
7524 }
7525 
7526 
7527 /***********************************************************************
7528  * CM_Set_DevNode_Registry_PropertyA [SETUPAPI.@]
7529  */
7530 CONFIGRET
7531 WINAPI
7532 CM_Set_DevNode_Registry_PropertyA(
7533   _In_ DEVINST dnDevInst,
7534   _In_ ULONG ulProperty,
7535   _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7536   _In_ ULONG ulLength,
7537   _In_ ULONG ulFlags)
7538 {
7539     TRACE("CM_Set_DevNode_Registry_PropertyA(%lx %lu %p %lx %lx)\n",
7540           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7541 
7542     return CM_Set_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
7543                                                 Buffer, ulLength,
7544                                                 ulFlags, NULL);
7545 }
7546 
7547 
7548 /***********************************************************************
7549  * CM_Set_DevNode_Registry_PropertyW [SETUPAPI.@]
7550  */
7551 CONFIGRET
7552 WINAPI
7553 CM_Set_DevNode_Registry_PropertyW(
7554     _In_ DEVINST dnDevInst,
7555     _In_ ULONG ulProperty,
7556     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7557     _In_ ULONG ulLength,
7558     _In_ ULONG ulFlags)
7559 {
7560     TRACE("CM_Set_DevNode_Registry_PropertyW(%lx %lu %p %lx %lx)\n",
7561           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7562 
7563     return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
7564                                                 Buffer, ulLength,
7565                                                 ulFlags, NULL);
7566 }
7567 
7568 
7569 /***********************************************************************
7570  * CM_Set_DevNode_Registry_Property_ExA [SETUPAPI.@]
7571  */
7572 CONFIGRET
7573 WINAPI
7574 CM_Set_DevNode_Registry_Property_ExA(
7575     _In_ DEVINST dnDevInst,
7576     _In_ ULONG ulProperty,
7577     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7578     _In_ ULONG ulLength,
7579     _In_ ULONG ulFlags,
7580     _In_opt_ HMACHINE hMachine)
7581 {
7582     CONFIGRET ret = CR_SUCCESS;
7583     LPWSTR lpBuffer;
7584     ULONG ulType;
7585 
7586     FIXME("CM_Set_DevNode_Registry_Property_ExA(%lx %lu %p %lx %lx %p)\n",
7587           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7588 
7589     if (Buffer == NULL && ulLength != 0)
7590         return CR_INVALID_POINTER;
7591 
7592     if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7593         return CR_INVALID_PROPERTY;
7594 
7595     if (Buffer == NULL)
7596     {
7597         ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7598                                                    ulProperty,
7599                                                    NULL,
7600                                                    0,
7601                                                    ulFlags,
7602                                                    hMachine);
7603     }
7604     else
7605     {
7606         /* Get property type */
7607         ulType = GetRegistryPropertyType(ulProperty);
7608 
7609         /* Allocate buffer if needed */
7610         if (ulType == REG_SZ ||
7611             ulType == REG_MULTI_SZ)
7612         {
7613             lpBuffer = MyMalloc(ulLength * sizeof(WCHAR));
7614             if (lpBuffer == NULL)
7615             {
7616                 ret = CR_OUT_OF_MEMORY;
7617             }
7618             else
7619             {
7620                 if (!MultiByteToWideChar(CP_ACP, 0, Buffer,
7621                                          ulLength, lpBuffer, ulLength))
7622                 {
7623                     MyFree(lpBuffer);
7624                     ret = CR_FAILURE;
7625                 }
7626                 else
7627                 {
7628                     ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7629                                                                ulProperty,
7630                                                                lpBuffer,
7631                                                                ulLength * sizeof(WCHAR),
7632                                                                ulFlags,
7633                                                                hMachine);
7634                     MyFree(lpBuffer);
7635                 }
7636             }
7637         }
7638         else
7639         {
7640             ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7641                                                        ulProperty,
7642                                                        Buffer,
7643                                                        ulLength,
7644                                                        ulFlags,
7645                                                        hMachine);
7646         }
7647 
7648         ret = CR_CALL_NOT_IMPLEMENTED;
7649     }
7650 
7651     return ret;
7652 }
7653 
7654 
7655 /***********************************************************************
7656  * CM_Set_DevNode_Registry_Property_ExW [SETUPAPI.@]
7657  */
7658 CONFIGRET
7659 WINAPI
7660 CM_Set_DevNode_Registry_Property_ExW(
7661     _In_ DEVINST dnDevInst,
7662     _In_ ULONG ulProperty,
7663     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7664     _In_ ULONG ulLength,
7665     _In_ ULONG ulFlags,
7666     _In_opt_ HMACHINE hMachine)
7667 {
7668     RPC_BINDING_HANDLE BindingHandle = NULL;
7669     HSTRING_TABLE StringTable = NULL;
7670     LPWSTR lpDevInst;
7671     ULONG ulType;
7672     CONFIGRET ret;
7673 
7674     TRACE("CM_Set_DevNode_Registry_Property_ExW(%lx %lu %p %lx %lx %p)\n",
7675           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7676 
7677     if (dnDevInst == 0)
7678         return CR_INVALID_DEVNODE;
7679 
7680     if (ulProperty <  CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7681         return CR_INVALID_PROPERTY;
7682 
7683     if (Buffer != NULL && ulLength == 0)
7684         return CR_INVALID_POINTER;
7685 
7686     if (ulFlags != 0)
7687         return CR_INVALID_FLAG;
7688 
7689     if (hMachine != NULL)
7690     {
7691         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7692         if (BindingHandle == NULL)
7693             return CR_FAILURE;
7694 
7695         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7696         if (StringTable == 0)
7697             return CR_FAILURE;
7698     }
7699     else
7700     {
7701         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7702             return CR_FAILURE;
7703     }
7704 
7705     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7706     if (lpDevInst == NULL)
7707         return CR_INVALID_DEVNODE;
7708 
7709     /* Get property type */
7710     ulType = GetRegistryPropertyType(ulProperty);
7711 
7712     RpcTryExcept
7713     {
7714         ret = PNP_SetDeviceRegProp(BindingHandle,
7715                                    lpDevInst,
7716                                    ulProperty,
7717                                    ulType,
7718                                    (BYTE *)Buffer,
7719                                    ulLength,
7720                                    ulFlags);
7721     }
7722     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7723     {
7724         ret = RpcStatusToCmStatus(RpcExceptionCode());
7725     }
7726     RpcEndExcept;
7727 
7728     return ret;
7729 }
7730 
7731 
7732 /***********************************************************************
7733  * CM_Set_HW_Prof [SETUPAPI.@]
7734  */
7735 CONFIGRET
7736 WINAPI
7737 CM_Set_HW_Prof(
7738     _In_ ULONG ulHardwareProfile,
7739     _In_ ULONG ulFlags)
7740 {
7741     TRACE("CM_Set_HW_Prof(%lu %lx)\n",
7742           ulHardwareProfile, ulFlags);
7743 
7744     return CM_Set_HW_Prof_Ex(ulHardwareProfile, ulFlags, NULL);
7745 }
7746 
7747 
7748 /***********************************************************************
7749  * CM_Set_HW_Prof_Ex [SETUPAPI.@]
7750  */
7751 CONFIGRET
7752 WINAPI
7753 CM_Set_HW_Prof_Ex(
7754     _In_ ULONG ulHardwareProfile,
7755     _In_ ULONG ulFlags,
7756     _In_opt_ HMACHINE hMachine)
7757 {
7758     RPC_BINDING_HANDLE BindingHandle = NULL;
7759     CONFIGRET ret;
7760 
7761     TRACE("CM_Set_HW_Prof_Ex(%lu %lx %p)\n",
7762           ulHardwareProfile, ulFlags, hMachine);
7763 
7764     if (!pSetupIsUserAdmin())
7765         return CR_ACCESS_DENIED;
7766 
7767     if (ulFlags != 0)
7768         return CR_INVALID_FLAG;
7769 
7770     if (hMachine != NULL)
7771     {
7772         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7773         if (BindingHandle == NULL)
7774             return CR_FAILURE;
7775     }
7776     else
7777     {
7778         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7779             return CR_FAILURE;
7780     }
7781 
7782     RpcTryExcept
7783     {
7784         ret = PNP_SetHwProf(BindingHandle, ulHardwareProfile, ulFlags);
7785     }
7786     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7787     {
7788         ret = RpcStatusToCmStatus(RpcExceptionCode());
7789     }
7790     RpcEndExcept;
7791 
7792     return ret;
7793 }
7794 
7795 
7796 /***********************************************************************
7797  * CM_Set_HW_Prof_FlagsA [SETUPAPI.@]
7798  */
7799 CONFIGRET
7800 WINAPI
7801 CM_Set_HW_Prof_FlagsA(
7802     _In_ DEVINSTID_A szDevInstName,
7803     _In_ ULONG ulConfig,
7804     _In_ ULONG ulValue,
7805     _In_ ULONG ulFlags)
7806 {
7807     TRACE("CM_Set_HW_Prof_FlagsA(%s %lu %lu %lx)\n",
7808           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags);
7809 
7810     return CM_Set_HW_Prof_Flags_ExA(szDevInstName, ulConfig, ulValue,
7811                                     ulFlags, NULL);
7812 }
7813 
7814 
7815 /***********************************************************************
7816  * CM_Set_HW_Prof_FlagsW [SETUPAPI.@]
7817  */
7818 CONFIGRET
7819 WINAPI
7820 CM_Set_HW_Prof_FlagsW(
7821     _In_ DEVINSTID_W szDevInstName,
7822     _In_ ULONG ulConfig,
7823     _In_ ULONG ulValue,
7824     _In_ ULONG ulFlags)
7825 {
7826     TRACE("CM_Set_HW_Prof_FlagsW(%s %lu %lu %lx)\n",
7827           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags);
7828 
7829     return CM_Set_HW_Prof_Flags_ExW(szDevInstName, ulConfig, ulValue,
7830                                     ulFlags, NULL);
7831 }
7832 
7833 
7834 /***********************************************************************
7835  * CM_Set_HW_Prof_Flags_ExA [SETUPAPI.@]
7836  */
7837 CONFIGRET
7838 WINAPI
7839 CM_Set_HW_Prof_Flags_ExA(
7840     _In_ DEVINSTID_A szDevInstName,
7841     _In_ ULONG ulConfig,
7842     _In_ ULONG ulValue,
7843     _In_ ULONG ulFlags,
7844     _In_opt_ HMACHINE hMachine)
7845 {
7846     DEVINSTID_W pszDevIdW = NULL;
7847     CONFIGRET ret = CR_SUCCESS;
7848 
7849     TRACE("CM_Set_HW_Prof_Flags_ExA(%s %lu %lu %lx %p)\n",
7850           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
7851 
7852     if (szDevInstName != NULL)
7853     {
7854        if (pSetupCaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
7855          return CR_INVALID_DEVICE_ID;
7856     }
7857 
7858     ret = CM_Set_HW_Prof_Flags_ExW(pszDevIdW, ulConfig, ulValue,
7859                                    ulFlags, hMachine);
7860 
7861     if (pszDevIdW != NULL)
7862         MyFree(pszDevIdW);
7863 
7864     return ret;
7865 }
7866 
7867 
7868 /***********************************************************************
7869  * CM_Set_HW_Prof_Flags_ExW [SETUPAPI.@]
7870  */
7871 CONFIGRET
7872 WINAPI
7873 CM_Set_HW_Prof_Flags_ExW(
7874     _In_ DEVINSTID_W szDevInstName,
7875     _In_ ULONG ulConfig,
7876     _In_ ULONG ulValue,
7877     _In_ ULONG ulFlags,
7878     _In_opt_ HMACHINE hMachine)
7879 {
7880     RPC_BINDING_HANDLE BindingHandle = NULL;
7881     CONFIGRET ret;
7882 
7883     FIXME("CM_Set_HW_Prof_Flags_ExW(%s %lu %lu %lx %p)\n",
7884           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
7885 
7886     if (szDevInstName == NULL)
7887         return CR_INVALID_POINTER;
7888 
7889     if (ulFlags & ~ CM_SET_HW_PROF_FLAGS_BITS)
7890         return CR_INVALID_FLAG;
7891 
7892     /* FIXME: Check whether szDevInstName is valid */
7893 
7894     if (hMachine != NULL)
7895     {
7896         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7897         if (BindingHandle == NULL)
7898             return CR_FAILURE;
7899     }
7900     else
7901     {
7902         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7903             return CR_FAILURE;
7904     }
7905 
7906     RpcTryExcept
7907     {
7908         ret = PNP_HwProfFlags(BindingHandle, PNP_SET_HWPROFFLAGS, szDevInstName,
7909                               ulConfig, &ulValue, NULL, NULL, 0, 0);
7910     }
7911     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7912     {
7913         ret = RpcStatusToCmStatus(RpcExceptionCode());
7914     }
7915     RpcEndExcept;
7916 
7917     return ret;
7918 }
7919 
7920 
7921 /***********************************************************************
7922  * CM_Setup_DevNode [SETUPAPI.@]
7923  */
7924 CONFIGRET
7925 WINAPI
7926 CM_Setup_DevNode(
7927     _In_ DEVINST dnDevInst,
7928     _In_ ULONG ulFlags)
7929 {
7930     TRACE("CM_Setup_DevNode(%lx %lx)\n",
7931           dnDevInst, ulFlags);
7932 
7933     return CM_Setup_DevNode_Ex(dnDevInst, ulFlags, NULL);
7934 }
7935 
7936 
7937 /***********************************************************************
7938  * CM_Setup_DevNode_Ex [SETUPAPI.@]
7939  */
7940 CONFIGRET
7941 WINAPI
7942 CM_Setup_DevNode_Ex(
7943     _In_ DEVINST dnDevInst,
7944     _In_ ULONG ulFlags,
7945     _In_opt_ HMACHINE hMachine)
7946 {
7947     RPC_BINDING_HANDLE BindingHandle = NULL;
7948     HSTRING_TABLE StringTable = NULL;
7949     LPWSTR lpDevInst;
7950     CONFIGRET ret;
7951 
7952     FIXME("CM_Setup_DevNode_Ex(%lx %lx %p)\n",
7953           dnDevInst, ulFlags, hMachine);
7954 
7955     if (!pSetupIsUserAdmin())
7956         return CR_ACCESS_DENIED;
7957 
7958     if (dnDevInst == 0)
7959         return CR_INVALID_DEVNODE;
7960 
7961     if (ulFlags & ~CM_SETUP_BITS)
7962         return CR_INVALID_FLAG;
7963 
7964     if (hMachine != NULL)
7965     {
7966         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7967         if (BindingHandle == NULL)
7968             return CR_FAILURE;
7969 
7970         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7971         if (StringTable == 0)
7972             return CR_FAILURE;
7973     }
7974     else
7975     {
7976         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7977             return CR_FAILURE;
7978     }
7979 
7980     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7981     if (lpDevInst == NULL)
7982         return CR_INVALID_DEVNODE;
7983 
7984     RpcTryExcept
7985     {
7986         ret = PNP_DeviceInstanceAction(BindingHandle,
7987                                        PNP_DEVINST_SETUP,
7988                                        ulFlags,
7989                                        lpDevInst,
7990                                        NULL);
7991     }
7992     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7993     {
7994         ret = RpcStatusToCmStatus(RpcExceptionCode());
7995     }
7996     RpcEndExcept;
7997 
7998     return ret;
7999 }
8000 
8001 
8002 /***********************************************************************
8003  * CM_Test_Range_Available [SETUPAPI.@]
8004  */
8005 CONFIGRET
8006 WINAPI
8007 CM_Test_Range_Available(
8008     _In_ DWORDLONG ullStartValue,
8009     _In_ DWORDLONG ullEndValue,
8010     _In_ RANGE_LIST rlh,
8011     _In_ ULONG ulFlags)
8012 {
8013     FIXME("CM_Test_Range_Available(%I64u %I64u %p %lx)\n",
8014           ullStartValue, ullEndValue, rlh, ulFlags);
8015     return CR_CALL_NOT_IMPLEMENTED;
8016 }
8017 
8018 
8019 /***********************************************************************
8020  * CM_Uninstall_DevNode [SETUPAPI.@]
8021  */
8022 CONFIGRET
8023 WINAPI
8024 CM_Uninstall_DevNode(
8025     _In_ DEVINST dnPhantom,
8026     _In_ ULONG ulFlags)
8027 {
8028     TRACE("CM_Uninstall_DevNode(%lx %lx)\n",
8029           dnPhantom, ulFlags);
8030 
8031     return CM_Uninstall_DevNode_Ex(dnPhantom, ulFlags, NULL);
8032 }
8033 
8034 
8035 /***********************************************************************
8036  * CM_Uninstall_DevNode_Ex [SETUPAPI.@]
8037  */
8038 CONFIGRET
8039 WINAPI
8040 CM_Uninstall_DevNode_Ex(
8041     _In_ DEVINST dnPhantom,
8042     _In_ ULONG ulFlags,
8043     _In_opt_ HMACHINE hMachine)
8044 {
8045     RPC_BINDING_HANDLE BindingHandle = NULL;
8046     HSTRING_TABLE StringTable = NULL;
8047     LPWSTR lpDevInst;
8048     CONFIGRET ret;
8049 
8050     TRACE("CM_Uninstall_DevNode_Ex(%lx %lx %p)\n",
8051           dnPhantom, ulFlags, hMachine);
8052 
8053     if (dnPhantom == 0)
8054         return CR_INVALID_DEVNODE;
8055 
8056     if (ulFlags != 0)
8057         return CR_INVALID_FLAG;
8058 
8059     if (hMachine != NULL)
8060     {
8061         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8062         if (BindingHandle == NULL)
8063             return CR_FAILURE;
8064 
8065         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
8066         if (StringTable == 0)
8067             return CR_FAILURE;
8068     }
8069     else
8070     {
8071         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8072             return CR_FAILURE;
8073     }
8074 
8075     lpDevInst = pSetupStringTableStringFromId(StringTable, dnPhantom);
8076     if (lpDevInst == NULL)
8077         return CR_INVALID_DEVNODE;
8078 
8079     RpcTryExcept
8080     {
8081         ret = PNP_UninstallDevInst(BindingHandle,
8082                                    lpDevInst,
8083                                    ulFlags);
8084     }
8085     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8086     {
8087         ret = RpcStatusToCmStatus(RpcExceptionCode());
8088     }
8089     RpcEndExcept;
8090 
8091     return ret;
8092 }
8093 
8094 
8095 /***********************************************************************
8096  * CM_Unregister_Device_InterfaceA [SETUPAPI.@]
8097  */
8098 CONFIGRET
8099 WINAPI
8100 CM_Unregister_Device_InterfaceA(
8101     _In_ LPCSTR pszDeviceInterface,
8102     _In_ ULONG ulFlags)
8103 {
8104     TRACE("CM_Unregister_Device_InterfaceA(%s %lx)\n",
8105           debugstr_a(pszDeviceInterface), ulFlags);
8106 
8107     return CM_Unregister_Device_Interface_ExA(pszDeviceInterface,
8108                                               ulFlags, NULL);
8109 }
8110 
8111 
8112 /***********************************************************************
8113  * CM_Unregister_Device_InterfaceW [SETUPAPI.@]
8114  */
8115 CONFIGRET
8116 WINAPI
8117 CM_Unregister_Device_InterfaceW(
8118     _In_ LPCWSTR pszDeviceInterface,
8119     _In_ ULONG ulFlags)
8120 {
8121     TRACE("CM_Unregister_Device_InterfaceW(%s %lx)\n",
8122           debugstr_w(pszDeviceInterface), ulFlags);
8123 
8124     return CM_Unregister_Device_Interface_ExW(pszDeviceInterface,
8125                                               ulFlags, NULL);
8126 }
8127 
8128 
8129 /***********************************************************************
8130  * CM_Unregister_Device_Interface_ExA [SETUPAPI.@]
8131  */
8132 CONFIGRET
8133 WINAPI
8134 CM_Unregister_Device_Interface_ExA(
8135     _In_ LPCSTR pszDeviceInterface,
8136     _In_ ULONG ulFlags,
8137     _In_opt_ HMACHINE hMachine)
8138 {
8139     LPWSTR pszDeviceInterfaceW = NULL;
8140     CONFIGRET ret;
8141 
8142     TRACE("CM_Unregister_Device_Interface_ExA(%s %lx %p)\n",
8143           debugstr_a(pszDeviceInterface), ulFlags, hMachine);
8144 
8145     if (pszDeviceInterface == NULL)
8146         return CR_INVALID_POINTER;
8147 
8148     if (pSetupCaptureAndConvertAnsiArg(pszDeviceInterface, &pszDeviceInterfaceW))
8149         return CR_INVALID_DATA;
8150 
8151     ret = CM_Unregister_Device_Interface_ExW(pszDeviceInterfaceW,
8152                                              ulFlags, hMachine);
8153 
8154     if (pszDeviceInterfaceW != NULL)
8155         MyFree(pszDeviceInterfaceW);
8156 
8157     return ret;
8158 }
8159 
8160 
8161 /***********************************************************************
8162  * CM_Unregister_Device_Interface_ExW [SETUPAPI.@]
8163  */
8164 CONFIGRET
8165 WINAPI
8166 CM_Unregister_Device_Interface_ExW(
8167     _In_ LPCWSTR pszDeviceInterface,
8168     _In_ ULONG ulFlags,
8169     _In_opt_ HMACHINE hMachine)
8170 {
8171     RPC_BINDING_HANDLE BindingHandle = NULL;
8172     CONFIGRET ret;
8173 
8174     TRACE("CM_Unregister_Device_Interface_ExW(%s %lx %p)\n",
8175           debugstr_w(pszDeviceInterface), ulFlags, hMachine);
8176 
8177     if (pszDeviceInterface == NULL)
8178         return CR_INVALID_POINTER;
8179 
8180     if (ulFlags != 0)
8181         return CR_INVALID_FLAG;
8182 
8183     if (hMachine != NULL)
8184     {
8185         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8186         if (BindingHandle == NULL)
8187             return CR_FAILURE;
8188     }
8189     else
8190     {
8191         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8192             return CR_FAILURE;
8193     }
8194 
8195     RpcTryExcept
8196     {
8197         ret = PNP_UnregisterDeviceClassAssociation(BindingHandle,
8198                                                    (LPWSTR)pszDeviceInterface,
8199                                                    ulFlags);
8200     }
8201     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8202     {
8203         ret = RpcStatusToCmStatus(RpcExceptionCode());
8204     }
8205     RpcEndExcept;
8206 
8207     return ret;
8208 }
8209