xref: /reactos/dll/win32/setupapi/cfgmgr.c (revision 9cfd8dd9)
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 #include <winsvc.h>
27 
28 #include <pseh/pseh2.h>
29 
30 #include "rpc_private.h"
31 
32 DWORD
33 WINAPI
34 I_ScPnPGetServiceName(IN SERVICE_STATUS_HANDLE hServiceStatus,
35                       OUT LPWSTR lpServiceName,
36                       IN DWORD cchServiceName);
37 
38 
39 /* Registry key and value names */
40 static const WCHAR BackslashOpenBrace[] = {'\\', '{', 0};
41 static const WCHAR CloseBrace[] = {'}', 0};
42 static const WCHAR Class[]  = {'C','l','a','s','s',0};
43 
44 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
45                                      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
46                                      'C','o','n','t','r','o','l','\\',
47                                      'C','l','a','s','s',0};
48 
49 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
50                                       'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
51                                       'C','o','n','t','r','o','l','\\',
52                                       'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
53 
54 typedef struct _MACHINE_INFO
55 {
56     WCHAR szMachineName[SP_MAX_MACHINENAME_LENGTH];
57     RPC_BINDING_HANDLE BindingHandle;
58     HSTRING_TABLE StringTable;
59     BOOL bLocal;
60 } MACHINE_INFO, *PMACHINE_INFO;
61 
62 
63 typedef struct _LOG_CONF_INFO
64 {
65     ULONG ulMagic;
66     DEVINST dnDevInst;
67     ULONG ulType;
68     ULONG ulTag;
69 } LOG_CONF_INFO, *PLOG_CONF_INFO;
70 
71 #define LOG_CONF_MAGIC 0x464E434C  /* "LCNF" */
72 
73 
74 typedef struct _NOTIFY_DATA
75 {
76     ULONG ulMagic;
77     PVOID hNotifyHandle;
78 } NOTIFY_DATA, *PNOTIFY_DATA;
79 
80 #define NOTIFY_MAGIC 0x44556677
81 
82 
83 typedef struct _INTERNAL_RANGE
84 {
85     LIST_ENTRY ListEntry;
86     struct _INTERNAL_RANGE_LIST *pRangeList;
87     DWORDLONG ullStart;
88     DWORDLONG ullEnd;
89 } INTERNAL_RANGE, *PINTERNAL_RANGE;
90 
91 typedef struct _INTERNAL_RANGE_LIST
92 {
93     ULONG ulMagic;
94     HANDLE hMutex;
95     LIST_ENTRY ListHead;
96 } INTERNAL_RANGE_LIST, *PINTERNAL_RANGE_LIST;
97 
98 #define RANGE_LIST_MAGIC 0x33445566
99 
100 typedef struct _CONFLICT_DATA
101 {
102     ULONG ulMagic;
103     PPNP_CONFLICT_LIST pConflictList;
104 } CONFLICT_DATA, *PCONFLICT_DATA;
105 
106 #define CONFLICT_MAGIC 0x11225588
107 
108 
109 /* FUNCTIONS ****************************************************************/
110 
111 static
112 BOOL
113 GuidToString(
114     _In_ LPGUID Guid,
115     _Out_ LPWSTR String)
116 {
117     LPWSTR lpString;
118 
119     if (UuidToStringW(Guid, &lpString) != RPC_S_OK)
120         return FALSE;
121 
122     lstrcpyW(&String[1], lpString);
123 
124     String[0] = '{';
125     String[MAX_GUID_STRING_LEN - 2] = '}';
126     String[MAX_GUID_STRING_LEN - 1] = UNICODE_NULL;
127 
128     RpcStringFreeW(&lpString);
129 
130     return TRUE;
131 }
132 
133 
134 static
135 CONFIGRET
136 RpcStatusToCmStatus(
137     _In_ RPC_STATUS Status)
138 {
139     return CR_FAILURE;
140 }
141 
142 
143 static
144 ULONG
145 GetRegistryPropertyType(
146     _In_ ULONG ulProperty)
147 {
148     switch (ulProperty)
149     {
150         case CM_DRP_DEVICEDESC:
151         case CM_DRP_SERVICE:
152         case CM_DRP_CLASS:
153         case CM_DRP_CLASSGUID:
154         case CM_DRP_DRIVER:
155         case CM_DRP_MFG:
156         case CM_DRP_FRIENDLYNAME:
157         case CM_DRP_LOCATION_INFORMATION:
158         case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
159         case CM_DRP_ENUMERATOR_NAME:
160         case CM_DRP_SECURITY_SDS:
161         case CM_DRP_UI_NUMBER_DESC_FORMAT:
162             return REG_SZ;
163 
164         case CM_DRP_HARDWAREID:
165         case CM_DRP_COMPATIBLEIDS:
166         case CM_DRP_UPPERFILTERS:
167         case CM_DRP_LOWERFILTERS:
168             return REG_MULTI_SZ;
169 
170         case CM_DRP_CONFIGFLAGS:
171         case CM_DRP_CAPABILITIES:
172         case CM_DRP_UI_NUMBER:
173         case CM_DRP_LEGACYBUSTYPE:
174         case CM_DRP_BUSNUMBER:
175         case CM_DRP_DEVTYPE:
176         case CM_DRP_EXCLUSIVE:
177         case CM_DRP_CHARACTERISTICS:
178         case CM_DRP_ADDRESS:
179         case CM_DRP_REMOVAL_POLICY:
180         case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
181         case CM_DRP_REMOVAL_POLICY_OVERRIDE:
182         case CM_DRP_INSTALL_STATE:
183             return REG_DWORD;
184 
185         case CM_DRP_BUSTYPEGUID:
186         case CM_DRP_SECURITY:
187         case CM_DRP_DEVICE_POWER_DATA:
188         default:
189             return REG_BINARY;
190     }
191 
192     return REG_NONE;
193 }
194 
195 
196 static
197 VOID
198 SplitDeviceInstanceId(
199     _In_ PWSTR pszDeviceInstanceId,
200     _Out_ PWSTR pszDeviceId,
201     _Out_ PWSTR pszInstanceId)
202 {
203     PWCHAR ptr;
204 
205     wcscpy(pszDeviceId, pszDeviceInstanceId);
206 
207     ptr = wcschr(pszDeviceId, L'\\');
208     if (ptr != NULL)
209     {
210         *ptr = UNICODE_NULL;
211         ptr++;
212 
213         wcscpy(pszInstanceId, ptr);
214     }
215     else
216     {
217         *pszInstanceId = UNICODE_NULL;
218     }
219 }
220 
221 
222 static
223 CONFIGRET
224 GetDeviceInstanceKeyPath(
225     _In_ RPC_BINDING_HANDLE BindingHandle,
226     _In_ PWSTR pszDeviceInst,
227     _Out_ PWSTR pszKeyPath,
228     _Out_ PWSTR pszInstancePath,
229     _In_ ULONG ulHardwareProfile,
230     _In_ ULONG ulFlags)
231 {
232     PWSTR pszBuffer = NULL;
233     ULONG ulType = 0;
234     ULONG ulTransferLength, ulLength;
235     CONFIGRET ret = CR_SUCCESS;
236 
237     TRACE("GetDeviceInstanceKeyPath()\n");
238 
239     /* Allocate a buffer for the device id */
240     pszBuffer = MyMalloc(300 * sizeof(WCHAR));
241     if (pszBuffer == NULL)
242     {
243         ERR("MyMalloc() failed\n");
244         return CR_OUT_OF_MEMORY;
245     }
246 
247     if (ulFlags & CM_REGISTRY_SOFTWARE)
248     {
249         /* Software Key Path */
250 
251         ulTransferLength = 300 * sizeof(WCHAR);
252         ulLength = 300 * sizeof(WCHAR);
253 
254         RpcTryExcept
255         {
256             ret = PNP_GetDeviceRegProp(BindingHandle,
257                                        pszDeviceInst,
258                                        CM_DRP_DRIVER,
259                                        &ulType,
260                                        (PVOID)pszBuffer,
261                                        &ulTransferLength,
262                                        &ulLength,
263                                        0);
264         }
265         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
266         {
267             ret = RpcStatusToCmStatus(RpcExceptionCode());
268         }
269         RpcEndExcept;
270 
271         if (ret != CR_SUCCESS)
272         {
273             RpcTryExcept
274             {
275                 ret = PNP_GetClassInstance(BindingHandle,
276                                            pszDeviceInst,
277                                            (PVOID)pszBuffer,
278                                            300);
279             }
280             RpcExcept(EXCEPTION_EXECUTE_HANDLER)
281             {
282                 ret = RpcStatusToCmStatus(RpcExceptionCode());
283             }
284             RpcEndExcept;
285 
286             if (ret != CR_SUCCESS)
287             {
288                 goto done;
289             }
290         }
291 
292         TRACE("szBuffer: %S\n", pszBuffer);
293 
294         SplitDeviceInstanceId(pszBuffer,
295                               pszBuffer,
296                               pszInstancePath);
297 
298         TRACE("szBuffer: %S\n", pszBuffer);
299 
300         if (ulFlags & CM_REGISTRY_CONFIG)
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\\Control\\Class",
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\\Control\\Class",
318                           pszBuffer);
319             }
320         }
321         else
322         {
323             wsprintfW(pszKeyPath,
324                       L"%s\\%s",
325                       L"System\\CurrentControlSet\\Control\\Class",
326                       pszBuffer);
327         }
328     }
329     else
330     {
331         /* Hardware Key Path */
332 
333         if (ulFlags & CM_REGISTRY_CONFIG)
334         {
335             SplitDeviceInstanceId(pszDeviceInst,
336                                   pszBuffer,
337                                   pszInstancePath);
338 
339             if (ulHardwareProfile == 0)
340             {
341                 wsprintfW(pszKeyPath,
342                           L"%s\\%s\\%s\\%s",
343                           L"System\\CurrentControlSet\\Hardware Profiles",
344                           L"Current",
345                           L"System\\CurrentControlSet\\Enum",
346                           pszBuffer);
347             }
348             else
349             {
350                 wsprintfW(pszKeyPath,
351                           L"%s\\%04lu\\%s\\%s",
352                           L"System\\CurrentControlSet\\Hardware Profiles",
353                           ulHardwareProfile,
354                           L"System\\CurrentControlSet\\Enum",
355                           pszBuffer);
356             }
357         }
358         else if (ulFlags & CM_REGISTRY_USER)
359         {
360             wsprintfW(pszKeyPath,
361                       L"%s\\%s",
362                       L"System\\CurrentControlSet\\Enum",
363                       pszDeviceInst);
364 
365             wcscpy(pszInstancePath,
366                    L"Device Parameters");
367         }
368         else
369         {
370             SplitDeviceInstanceId(pszDeviceInst,
371                                   pszBuffer,
372                                   pszInstancePath);
373 
374             wsprintfW(pszKeyPath,
375                       L"%s\\%s",
376                       L"System\\CurrentControlSet\\Enum",
377                       pszBuffer);
378         }
379     }
380 
381 done:
382     if (pszBuffer != NULL)
383         MyFree(pszBuffer);
384 
385     return ret;
386 }
387 
388 
389 BOOL
390 IsValidRangeList(
391     _In_opt_ PINTERNAL_RANGE_LIST pRangeList)
392 {
393     BOOL bValid = TRUE;
394 
395     if (pRangeList == NULL)
396         return FALSE;
397 
398     _SEH2_TRY
399     {
400         if (pRangeList->ulMagic != RANGE_LIST_MAGIC)
401             bValid = FALSE;
402     }
403     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
404     {
405         bValid = FALSE;
406     }
407     _SEH2_END;
408 
409     return bValid;
410 }
411 
412 
413 BOOL
414 IsValidLogConf(
415     _In_opt_ PLOG_CONF_INFO pLogConfInfo)
416 {
417     BOOL bValid = TRUE;
418 
419     if (pLogConfInfo == NULL)
420         return FALSE;
421 
422     _SEH2_TRY
423     {
424         if (pLogConfInfo->ulMagic != LOG_CONF_MAGIC)
425             bValid = FALSE;
426     }
427     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
428     {
429         bValid = FALSE;
430     }
431     _SEH2_END;
432 
433     return bValid;
434 }
435 
436 
437 BOOL
438 IsValidConflictData(
439     _In_opt_ PCONFLICT_DATA pConflictData)
440 {
441     BOOL bValid = TRUE;
442 
443     if (pConflictData == NULL)
444         return FALSE;
445 
446     _SEH2_TRY
447     {
448         if (pConflictData->ulMagic != CONFLICT_MAGIC)
449             bValid = FALSE;
450     }
451     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
452     {
453         bValid = FALSE;
454     }
455     _SEH2_END;
456 
457     return bValid;
458 }
459 
460 
461 /***********************************************************************
462  * CMP_GetBlockedDriverInfo [SETUPAPI.@]
463  */
464 CONFIGRET
465 WINAPI
466 CMP_GetBlockedDriverInfo(
467     _Out_opt_ LPWSTR pszNames,
468     _Inout_ PULONG pulLength,
469     _In_ ULONG ulFlags,
470     _In_opt_ HMACHINE hMachine)
471 {
472     RPC_BINDING_HANDLE BindingHandle = NULL;
473     ULONG ulTransferLength;
474     CONFIGRET ret;
475 
476     TRACE("CMP_GetBlockedDriverInfo(%p %p %lx %p)\n",
477           pszNames, pulLength, ulFlags, hMachine);
478 
479     if (hMachine != NULL)
480     {
481         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
482         if (BindingHandle == NULL)
483             return CR_FAILURE;
484     }
485     else
486     {
487         if (!PnpGetLocalHandles(&BindingHandle, NULL))
488             return CR_FAILURE;
489     }
490 
491     ulTransferLength = *pulLength;
492 
493     RpcTryExcept
494     {
495         ret = PNP_GetBlockedDriverInfo(BindingHandle,
496                                        (PBYTE)pszNames,
497                                        &ulTransferLength,
498                                        pulLength,
499                                        ulFlags);
500     }
501     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
502     {
503         ret = RpcStatusToCmStatus(RpcExceptionCode());
504     }
505     RpcEndExcept;
506 
507     return ret;
508 }
509 
510 
511 /***********************************************************************
512  * CMP_GetServerSideDeviceInstallFlags [SETUPAPI.@]
513  */
514 CONFIGRET
515 WINAPI
516 CMP_GetServerSideDeviceInstallFlags(
517     _Out_ PULONG pulSSDIFlags,
518     _In_ ULONG ulFlags,
519     _In_opt_ HMACHINE hMachine)
520 {
521     RPC_BINDING_HANDLE BindingHandle = NULL;
522     CONFIGRET ret;
523 
524     TRACE("CMP_GetServerSideDeviceInstallFlags(%p %lx %p)\n",
525           pulSSDIFlags, ulFlags, hMachine);
526 
527     if (pulSSDIFlags == NULL)
528         return CR_INVALID_POINTER;
529 
530     if (ulFlags != 0)
531         return CR_INVALID_FLAG;
532 
533     if (hMachine != NULL)
534     {
535         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
536         if (BindingHandle == NULL)
537             return CR_FAILURE;
538     }
539     else
540     {
541         if (!PnpGetLocalHandles(&BindingHandle, NULL))
542             return CR_FAILURE;
543     }
544 
545     RpcTryExcept
546     {
547         ret = PNP_GetServerSideDeviceInstallFlags(BindingHandle,
548                                                   pulSSDIFlags,
549                                                   ulFlags);
550     }
551     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
552     {
553         ret = RpcStatusToCmStatus(RpcExceptionCode());
554     }
555     RpcEndExcept;
556 
557     return ret;
558 }
559 
560 
561 /***********************************************************************
562  * CMP_Init_Detection [SETUPAPI.@]
563  */
564 CONFIGRET
565 WINAPI
566 CMP_Init_Detection(
567     _In_ ULONG ulMagic)
568 {
569     RPC_BINDING_HANDLE BindingHandle = NULL;
570     CONFIGRET ret;
571 
572     TRACE("CMP_Init_Detection(%lu)\n", ulMagic);
573 
574     if (ulMagic != CMP_MAGIC)
575         return CR_INVALID_DATA;
576 
577     if (!PnpGetLocalHandles(&BindingHandle, NULL))
578         return CR_FAILURE;
579 
580     RpcTryExcept
581     {
582         ret = PNP_InitDetection(BindingHandle);
583     }
584     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
585     {
586         ret = RpcStatusToCmStatus(RpcExceptionCode());
587     }
588     RpcEndExcept;
589 
590     return ret;
591 }
592 
593 
594 /***********************************************************************
595  * CMP_RegisterNotification [SETUPAPI.@]
596  */
597 CONFIGRET
598 WINAPI
599 CMP_RegisterNotification(
600     _In_ HANDLE hRecipient,
601     _In_ LPVOID lpvNotificationFilter,
602     _In_ ULONG ulFlags,
603     _Out_ PHDEVNOTIFY phDevNotify)
604 {
605     RPC_BINDING_HANDLE BindingHandle = NULL;
606     PNOTIFY_DATA pNotifyData;
607     WCHAR szNameBuffer[256];
608     INT nLength;
609     DWORD ulUnknown9 = 0;
610     DWORD dwError;
611     CONFIGRET ret = CR_SUCCESS;
612 
613     FIXME("CMP_RegisterNotification(%p %p %lu %p)\n",
614           hRecipient, lpvNotificationFilter, ulFlags, phDevNotify);
615 
616     if ((hRecipient == NULL) ||
617         (lpvNotificationFilter == NULL) ||
618         (phDevNotify == NULL))
619         return CR_INVALID_POINTER;
620 
621     if (ulFlags & ~0x7)
622         return CR_INVALID_FLAG;
623 
624     if (((PDEV_BROADCAST_HDR)lpvNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR))
625         return CR_INVALID_DATA;
626 
627     if (!PnpGetLocalHandles(&BindingHandle, NULL))
628         return CR_FAILURE;
629 
630     pNotifyData = HeapAlloc(GetProcessHeap(),
631                             HEAP_ZERO_MEMORY,
632                             sizeof(NOTIFY_DATA));
633     if (pNotifyData == NULL)
634         return CR_OUT_OF_MEMORY;
635 
636     pNotifyData->ulMagic = NOTIFY_MAGIC;
637     pNotifyData->hNotifyHandle = NULL;
638 
639     ZeroMemory(szNameBuffer, sizeof(szNameBuffer));
640 
641     if ((ulFlags & DEVICE_NOTIFY_SERVICE_HANDLE) == DEVICE_NOTIFY_WINDOW_HANDLE)
642     {
643         FIXME("Register a window\n");
644 
645         nLength = GetWindowTextW((HWND)hRecipient,
646                                  szNameBuffer,
647                                  ARRAYSIZE(szNameBuffer));
648         if (nLength == 0)
649         {
650             szNameBuffer[0] = UNICODE_NULL;
651         }
652 
653         FIXME("Register window: %S\n", szNameBuffer);
654     }
655     else if ((ulFlags & DEVICE_NOTIFY_SERVICE_HANDLE) == DEVICE_NOTIFY_SERVICE_HANDLE)
656     {
657         FIXME("Register a service\n");
658 
659         dwError = I_ScPnPGetServiceName((SERVICE_STATUS_HANDLE)hRecipient,
660                                         szNameBuffer,
661                                         ARRAYSIZE(szNameBuffer));
662         if (dwError != ERROR_SUCCESS)
663         {
664             HeapFree(GetProcessHeap(), 0, pNotifyData);
665             return CR_INVALID_DATA;
666         }
667 
668         FIXME("Register service: %S\n", szNameBuffer);
669     }
670 
671     RpcTryExcept
672     {
673         ret = PNP_RegisterNotification(BindingHandle,
674                                        (DWORD_PTR)hRecipient,
675                                        szNameBuffer,
676                                        (BYTE*)lpvNotificationFilter,
677                                        ((DEV_BROADCAST_HDR*)lpvNotificationFilter)->dbch_size,
678                                        ulFlags,
679                                        &pNotifyData->hNotifyHandle,
680                                        GetCurrentProcessId(),
681                                        &ulUnknown9); /* ??? */
682     }
683     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
684     {
685         ret = RpcStatusToCmStatus(RpcExceptionCode());
686     }
687     RpcEndExcept;
688 
689     if (ret == CR_SUCCESS)
690     {
691         TRACE("hNotifyHandle: %p\n", pNotifyData->hNotifyHandle);
692         *phDevNotify = (HDEVNOTIFY)pNotifyData;
693     }
694     else
695     {
696         HeapFree(GetProcessHeap(), 0, pNotifyData);
697 
698         *phDevNotify = (HDEVNOTIFY)NULL;
699     }
700 
701     return ret;
702 }
703 
704 
705 /***********************************************************************
706  * CMP_Report_LogOn [SETUPAPI.@]
707  */
708 CONFIGRET
709 WINAPI
710 CMP_Report_LogOn(
711     _In_ DWORD dwMagic,
712     _In_ DWORD dwProcessId)
713 {
714     RPC_BINDING_HANDLE BindingHandle = NULL;
715     CONFIGRET ret = CR_SUCCESS;
716     BOOL bAdmin;
717     DWORD i;
718 
719     TRACE("CMP_Report_LogOn(%lu %lu)\n", dwMagic, dwProcessId);
720 
721     if (dwMagic != CMP_MAGIC)
722         return CR_INVALID_DATA;
723 
724     if (!PnpGetLocalHandles(&BindingHandle, NULL))
725         return CR_FAILURE;
726 
727     bAdmin = pSetupIsUserAdmin();
728 
729     for (i = 0; i < 30; i++)
730     {
731         RpcTryExcept
732         {
733             ret = PNP_ReportLogOn(BindingHandle,
734                                   bAdmin,
735                                   dwProcessId);
736         }
737         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
738         {
739             ret = RpcStatusToCmStatus(RpcExceptionCode());
740         }
741         RpcEndExcept;
742 
743         if (ret == CR_SUCCESS)
744             break;
745 
746         Sleep(5000);
747     }
748 
749     return ret;
750 }
751 
752 
753 /***********************************************************************
754  * CMP_UnregisterNotification [SETUPAPI.@]
755  */
756 CONFIGRET
757 WINAPI
758 CMP_UnregisterNotification(
759     _In_ HDEVNOTIFY hDevNotify)
760 {
761     RPC_BINDING_HANDLE BindingHandle = NULL;
762     PNOTIFY_DATA pNotifyData;
763     CONFIGRET ret = CR_SUCCESS;
764 
765     TRACE("CMP_UnregisterNotification(%p)\n", hDevNotify);
766 
767     pNotifyData = (PNOTIFY_DATA)hDevNotify;
768 
769     if ((pNotifyData == NULL) ||
770         (pNotifyData->ulMagic != NOTIFY_MAGIC))
771         return CR_INVALID_POINTER;
772 
773     if (!PnpGetLocalHandles(&BindingHandle, NULL))
774         return CR_FAILURE;
775 
776     RpcTryExcept
777     {
778         ret = PNP_UnregisterNotification(BindingHandle,
779                                          &pNotifyData->hNotifyHandle);
780     }
781     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
782     {
783         ret = RpcStatusToCmStatus(RpcExceptionCode());
784     }
785     RpcEndExcept;
786 
787     if (ret == CR_SUCCESS)
788     {
789         pNotifyData->hNotifyHandle = NULL;
790         HeapFree(GetProcessHeap(), 0, pNotifyData);
791     }
792 
793     return ret;
794 }
795 
796 
797 /***********************************************************************
798  * CMP_WaitNoPendingInstallEvents [SETUPAPI.@]
799  */
800 DWORD
801 WINAPI
802 CMP_WaitNoPendingInstallEvents(
803     _In_ DWORD dwTimeout)
804 {
805     HANDLE hEvent;
806     DWORD ret;
807 
808     TRACE("CMP_WaitNoPendingInstallEvents(%lu)\n", dwTimeout);
809 
810     hEvent = OpenEventW(SYNCHRONIZE, FALSE, L"Global\\PnP_No_Pending_Install_Events");
811     if (hEvent == NULL)
812        return WAIT_FAILED;
813 
814     ret = WaitForSingleObject(hEvent, dwTimeout);
815     CloseHandle(hEvent);
816     return ret;
817 }
818 
819 
820 /***********************************************************************
821  * CMP_WaitServicesAvailable [SETUPAPI.@]
822  */
823 CONFIGRET
824 WINAPI
825 CMP_WaitServicesAvailable(
826     _In_opt_ HMACHINE hMachine)
827 {
828     RPC_BINDING_HANDLE BindingHandle = NULL;
829     CONFIGRET ret = CR_SUCCESS;
830     WORD Version;
831 
832     TRACE("CMP_WaitServicesAvailable(%p)\n", hMachine);
833 
834     if (hMachine != NULL)
835     {
836         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
837         if (BindingHandle == NULL)
838             return CR_FAILURE;
839     }
840     else
841     {
842         if (!PnpGetLocalHandles(&BindingHandle, NULL))
843             return CR_FAILURE;
844     }
845 
846     RpcTryExcept
847     {
848         ret = PNP_GetVersion(BindingHandle, &Version);
849     }
850     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
851     {
852         ret = RpcStatusToCmStatus(RpcExceptionCode());
853     }
854     RpcEndExcept;
855 
856     return ret;
857 }
858 
859 
860 /***********************************************************************
861  * CM_Add_Empty_Log_Conf [SETUPAPI.@]
862  */
863 CONFIGRET
864 WINAPI
865 CM_Add_Empty_Log_Conf(
866     _Out_ PLOG_CONF plcLogConf,
867     _In_ DEVINST dnDevInst,
868     _In_ PRIORITY Priority,
869     _In_ ULONG ulFlags)
870 {
871     TRACE("CM_Add_Empty_Log_Conf(%p %p %lu %lx)\n",
872           plcLogConf, dnDevInst, Priority, ulFlags);
873 
874     return CM_Add_Empty_Log_Conf_Ex(plcLogConf, dnDevInst, Priority,
875                                     ulFlags, NULL);
876 }
877 
878 
879 /***********************************************************************
880  * CM_Add_Empty_Log_Conf_Ex [SETUPAPI.@]
881  */
882 CONFIGRET
883 WINAPI
884 CM_Add_Empty_Log_Conf_Ex(
885     _Out_ PLOG_CONF plcLogConf,
886     _In_ DEVINST dnDevInst,
887     _In_ PRIORITY Priority,
888     _In_ ULONG ulFlags,
889     _In_opt_ HMACHINE hMachine)
890 {
891     RPC_BINDING_HANDLE BindingHandle = NULL;
892     HSTRING_TABLE StringTable = NULL;
893     ULONG ulLogConfTag = 0;
894     LPWSTR lpDevInst;
895     PLOG_CONF_INFO pLogConfInfo;
896     CONFIGRET ret = CR_SUCCESS;
897 
898     FIXME("CM_Add_Empty_Log_Conf_Ex(%p %p %lu %lx %p)\n",
899           plcLogConf, dnDevInst, Priority, ulFlags, hMachine);
900 
901     if (!pSetupIsUserAdmin())
902         return CR_ACCESS_DENIED;
903 
904     if (plcLogConf == NULL)
905         return CR_INVALID_POINTER;
906 
907     if (dnDevInst == 0)
908         return CR_INVALID_DEVINST;
909 
910     if (Priority > 0xFFFF)
911         return CR_INVALID_PRIORITY;
912 
913     if (ulFlags & ~(LOG_CONF_BITS | PRIORITY_BIT))
914         return CR_INVALID_FLAG;
915 
916     if (hMachine != NULL)
917     {
918         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
919         if (BindingHandle == NULL)
920             return CR_FAILURE;
921 
922         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
923         if (StringTable == 0)
924             return CR_FAILURE;
925     }
926     else
927     {
928         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
929             return CR_FAILURE;
930     }
931 
932     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
933     if (lpDevInst == NULL)
934         return CR_INVALID_DEVNODE;
935 
936     RpcTryExcept
937     {
938         ret = PNP_AddEmptyLogConf(BindingHandle, lpDevInst, Priority,
939                                   &ulLogConfTag, ulFlags);
940     }
941     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
942     {
943         ret = RpcStatusToCmStatus(RpcExceptionCode());
944     }
945     RpcEndExcept;
946 
947     if (ret == CR_SUCCESS)
948     {
949         pLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
950         if (pLogConfInfo == NULL)
951         {
952             ret = CR_OUT_OF_MEMORY;
953         }
954         else
955         {
956             pLogConfInfo->ulMagic = LOG_CONF_MAGIC;
957             pLogConfInfo->dnDevInst = dnDevInst;
958             pLogConfInfo->ulType = ulFlags;
959             pLogConfInfo->ulTag = ulLogConfTag;
960 
961             *plcLogConf = (LOG_CONF)pLogConfInfo;
962 
963             ret = CR_SUCCESS;
964         }
965     }
966 
967     return ret;
968 }
969 
970 
971 /***********************************************************************
972  * CM_Add_IDA [SETUPAPI.@]
973  */
974 CONFIGRET
975 WINAPI
976 CM_Add_IDA(
977     _In_ DEVINST dnDevInst,
978     _In_ PSTR pszID,
979     _In_ ULONG ulFlags)
980 {
981     TRACE("CM_Add_IDA(%p %s %lx)\n",
982           dnDevInst, debugstr_a(pszID), ulFlags);
983 
984     return CM_Add_ID_ExA(dnDevInst, pszID, ulFlags, NULL);
985 }
986 
987 
988 /***********************************************************************
989  * CM_Add_IDW [SETUPAPI.@]
990  */
991 CONFIGRET
992 WINAPI
993 CM_Add_IDW(
994     _In_ DEVINST dnDevInst,
995     _In_ PWSTR pszID,
996     _In_ ULONG ulFlags)
997 {
998     TRACE("CM_Add_IDW(%p %s %lx)\n",
999           dnDevInst, debugstr_w(pszID), ulFlags);
1000 
1001     return CM_Add_ID_ExW(dnDevInst, pszID, ulFlags, NULL);
1002 }
1003 
1004 
1005 /***********************************************************************
1006  * CM_Add_ID_ExA [SETUPAPI.@]
1007  */
1008 CONFIGRET
1009 WINAPI
1010 CM_Add_ID_ExA(
1011     _In_ DEVINST dnDevInst,
1012     _In_ PSTR pszID,
1013     _In_ ULONG ulFlags,
1014     _In_opt_ HMACHINE hMachine)
1015 {
1016     PWSTR pszIDW;
1017     CONFIGRET ret;
1018 
1019     TRACE("CM_Add_ID_ExA(%p %s %lx %p)\n",
1020           dnDevInst, debugstr_a(pszID), ulFlags, hMachine);
1021 
1022     if (pSetupCaptureAndConvertAnsiArg(pszID, &pszIDW))
1023         return CR_INVALID_DATA;
1024 
1025     ret = CM_Add_ID_ExW(dnDevInst, pszIDW, ulFlags, hMachine);
1026 
1027     MyFree(pszIDW);
1028 
1029     return ret;
1030 }
1031 
1032 
1033 /***********************************************************************
1034  * CM_Add_ID_ExW [SETUPAPI.@]
1035  */
1036 CONFIGRET
1037 WINAPI
1038 CM_Add_ID_ExW(
1039     _In_ DEVINST dnDevInst,
1040     _In_ PWSTR pszID,
1041     _In_ ULONG ulFlags,
1042     _In_opt_ HMACHINE hMachine)
1043 {
1044     RPC_BINDING_HANDLE BindingHandle = NULL;
1045     HSTRING_TABLE StringTable = NULL;
1046     LPWSTR lpDevInst;
1047     CONFIGRET ret;
1048 
1049     TRACE("CM_Add_ID_ExW(%p %s %lx %p)\n",
1050           dnDevInst, debugstr_w(pszID), ulFlags, hMachine);
1051 
1052     if (!pSetupIsUserAdmin())
1053         return CR_ACCESS_DENIED;
1054 
1055     if (dnDevInst == 0)
1056         return CR_INVALID_DEVINST;
1057 
1058     if (pszID == NULL)
1059         return CR_INVALID_POINTER;
1060 
1061     if (ulFlags & ~CM_ADD_ID_BITS)
1062         return CR_INVALID_FLAG;
1063 
1064     if (hMachine != NULL)
1065     {
1066         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1067         if (BindingHandle == NULL)
1068             return CR_FAILURE;
1069 
1070         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1071         if (StringTable == 0)
1072             return CR_FAILURE;
1073     }
1074     else
1075     {
1076         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1077             return CR_FAILURE;
1078     }
1079 
1080     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1081     if (lpDevInst == NULL)
1082         return CR_INVALID_DEVNODE;
1083 
1084     RpcTryExcept
1085     {
1086         ret = PNP_AddID(BindingHandle,
1087                         lpDevInst,
1088                         pszID,
1089                         ulFlags);
1090     }
1091     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1092     {
1093         ret = RpcStatusToCmStatus(RpcExceptionCode());
1094     }
1095     RpcEndExcept;
1096 
1097     return ret;
1098 }
1099 
1100 
1101 /***********************************************************************
1102  * CM_Add_Range [SETUPAPI.@]
1103  */
1104 CONFIGRET
1105 WINAPI
1106 CM_Add_Range(
1107     _In_ DWORDLONG ullStartValue,
1108     _In_ DWORDLONG ullEndValue,
1109     _In_ RANGE_LIST rlh,
1110     _In_ ULONG ulFlags)
1111 {
1112     PINTERNAL_RANGE_LIST pRangeList;
1113     PINTERNAL_RANGE pRange;
1114     CONFIGRET ret = CR_SUCCESS;
1115 
1116     FIXME("CM_Add_Range(%I64u %I64u %p %lx)\n",
1117           ullStartValue, ullEndValue, rlh, ulFlags);
1118 
1119     pRangeList = (PINTERNAL_RANGE_LIST)rlh;
1120 
1121     if (!IsValidRangeList(pRangeList))
1122         return CR_INVALID_RANGE_LIST;
1123 
1124     if (ulFlags & ~CM_ADD_RANGE_BITS)
1125         return CR_INVALID_FLAG;
1126 
1127     if (ullEndValue < ullStartValue)
1128         return CR_INVALID_RANGE;
1129 
1130     /* Lock the range list */
1131     WaitForSingleObject(pRangeList->hMutex, INFINITE);
1132 
1133     /* Allocate the new range */
1134     pRange = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNAL_RANGE));
1135     if (pRange == NULL)
1136     {
1137         ret = CR_OUT_OF_MEMORY;
1138         goto done;
1139     }
1140 
1141     pRange->pRangeList = pRangeList;
1142     pRange->ullStart = ullStartValue;
1143     pRange->ullEnd = ullEndValue;
1144 
1145     /* Insert the range */
1146     if (IsListEmpty(&pRangeList->ListHead))
1147     {
1148         InsertTailList(&pRangeList->ListHead, &pRange->ListEntry);
1149     }
1150     else
1151     {
1152         HeapFree(GetProcessHeap(), 0, pRange);
1153         UNIMPLEMENTED;
1154     }
1155 
1156 done:
1157     /* Unlock the range list */
1158     ReleaseMutex(pRangeList->hMutex);
1159 
1160     return ret;
1161 }
1162 
1163 
1164 /***********************************************************************
1165  * CM_Add_Res_Des [SETUPAPI.@]
1166  */
1167 CONFIGRET
1168 WINAPI
1169 CM_Add_Res_Des(
1170     _Out_opt_ PRES_DES prdResDes,
1171     _In_ LOG_CONF lcLogConf,
1172     _In_ RESOURCEID ResourceID,
1173     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1174     _In_ ULONG ResourceLen,
1175     _In_ ULONG ulFlags)
1176 {
1177     TRACE("CM_Add_Res_Des(%p %p %lu %p %lu %lx)\n",
1178           prdResDes, lcLogConf, ResourceID, ResourceData, ResourceLen, ulFlags);
1179 
1180     return CM_Add_Res_Des_Ex(prdResDes, lcLogConf, ResourceID, ResourceData,
1181                              ResourceLen, ulFlags, NULL);
1182 }
1183 
1184 
1185 /***********************************************************************
1186  * CM_Add_Res_Des_Ex [SETUPAPI.@]
1187  */
1188 CONFIGRET
1189 WINAPI
1190 CM_Add_Res_Des_Ex(
1191     _Out_opt_ PRES_DES prdResDes,
1192     _In_ LOG_CONF lcLogConf,
1193     _In_ RESOURCEID ResourceID,
1194     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1195     _In_ ULONG ResourceLen,
1196     _In_ ULONG ulFlags,
1197     _In_opt_ HMACHINE hMachine)
1198 {
1199     FIXME("CM_Add_Res_Des_Ex(%p %p %lu %p %lu %lx %p)\n",
1200           prdResDes, lcLogConf, ResourceID,
1201           ResourceData, ResourceLen, ulFlags, hMachine);
1202 
1203     return CR_CALL_NOT_IMPLEMENTED;
1204 }
1205 
1206 
1207 /***********************************************************************
1208  * CM_Connect_MachineA [SETUPAPI.@]
1209  */
1210 CONFIGRET
1211 WINAPI
1212 CM_Connect_MachineA(
1213     _In_opt_ PCSTR UNCServerName,
1214     _Out_ PHMACHINE phMachine)
1215 {
1216     PWSTR pServerNameW;
1217     CONFIGRET ret;
1218 
1219     TRACE("CM_Connect_MachineA(%s %p)\n",
1220           debugstr_a(UNCServerName), phMachine);
1221 
1222     if (UNCServerName == NULL || *UNCServerName == 0)
1223         return CM_Connect_MachineW(NULL, phMachine);
1224 
1225     if (pSetupCaptureAndConvertAnsiArg(UNCServerName, &pServerNameW))
1226         return CR_INVALID_DATA;
1227 
1228     ret = CM_Connect_MachineW(pServerNameW, phMachine);
1229 
1230     MyFree(pServerNameW);
1231 
1232     return ret;
1233 }
1234 
1235 
1236 /***********************************************************************
1237  * CM_Connect_MachineW [SETUPAPI.@]
1238  */
1239 CONFIGRET
1240 WINAPI
1241 CM_Connect_MachineW(
1242     _In_opt_ PCWSTR UNCServerName,
1243     _Out_ PHMACHINE phMachine)
1244 {
1245     PMACHINE_INFO pMachine;
1246 
1247     TRACE("CM_Connect_MachineW(%s %p)\n",
1248           debugstr_w(UNCServerName), phMachine);
1249 
1250     if (phMachine == NULL)
1251         return CR_INVALID_POINTER;
1252 
1253     *phMachine = NULL;
1254 
1255     pMachine = HeapAlloc(GetProcessHeap(), 0, sizeof(MACHINE_INFO));
1256     if (pMachine == NULL)
1257         return CR_OUT_OF_MEMORY;
1258 
1259     if (UNCServerName == NULL || *UNCServerName == 0)
1260     {
1261         pMachine->bLocal = TRUE;
1262 
1263         /* FIXME: store the computers name in pMachine->szMachineName */
1264 
1265         if (!PnpGetLocalHandles(&pMachine->BindingHandle,
1266                                 &pMachine->StringTable))
1267         {
1268             HeapFree(GetProcessHeap(), 0, pMachine);
1269             return CR_FAILURE;
1270         }
1271     }
1272     else
1273     {
1274         pMachine->bLocal = FALSE;
1275         if (wcslen(UNCServerName) >= SP_MAX_MACHINENAME_LENGTH - 1)
1276         {
1277             HeapFree(GetProcessHeap(), 0, pMachine);
1278             return CR_INVALID_MACHINENAME;
1279         }
1280         lstrcpyW(pMachine->szMachineName, UNCServerName);
1281 
1282         pMachine->StringTable = pSetupStringTableInitialize();
1283         if (pMachine->StringTable == NULL)
1284         {
1285             HeapFree(GetProcessHeap(), 0, pMachine);
1286             return CR_FAILURE;
1287         }
1288 
1289         pSetupStringTableAddString(pMachine->StringTable, L"PLT", 1);
1290 
1291         if (!PnpBindRpc(UNCServerName, &pMachine->BindingHandle))
1292         {
1293             pSetupStringTableDestroy(pMachine->StringTable);
1294             HeapFree(GetProcessHeap(), 0, pMachine);
1295             return CR_INVALID_MACHINENAME;
1296         }
1297     }
1298 
1299     *phMachine = (PHMACHINE)pMachine;
1300 
1301     return CR_SUCCESS;
1302 }
1303 
1304 
1305 /***********************************************************************
1306  * CM_Create_DevNodeA [SETUPAPI.@]
1307  */
1308 CONFIGRET
1309 WINAPI
1310 CM_Create_DevNodeA(
1311     _Out_ PDEVINST pdnDevInst,
1312     _In_ DEVINSTID_A pDeviceID,
1313     _In_ DEVINST dnParent,
1314     _In_ ULONG ulFlags)
1315 {
1316     TRACE("CM_Create_DevNodeA(%p %s %p %lx)\n",
1317           pdnDevInst, debugstr_a(pDeviceID), dnParent, ulFlags);
1318 
1319     return CM_Create_DevNode_ExA(pdnDevInst, pDeviceID, dnParent,
1320                                  ulFlags, NULL);
1321 }
1322 
1323 
1324 /***********************************************************************
1325  * CM_Create_DevNodeW [SETUPAPI.@]
1326  */
1327 CONFIGRET
1328 WINAPI
1329 CM_Create_DevNodeW(
1330     _Out_ PDEVINST pdnDevInst,
1331     _In_ DEVINSTID_W pDeviceID,
1332     _In_ DEVINST dnParent,
1333     _In_ ULONG ulFlags)
1334 {
1335     TRACE("CM_Create_DevNodeW(%p %s %p %lx)\n",
1336           pdnDevInst, debugstr_w(pDeviceID), dnParent, ulFlags);
1337 
1338     return CM_Create_DevNode_ExW(pdnDevInst, pDeviceID, dnParent,
1339                                  ulFlags, NULL);
1340 }
1341 
1342 
1343 /***********************************************************************
1344  * CM_Create_DevNode_ExA [SETUPAPI.@]
1345  */
1346 CONFIGRET
1347 WINAPI
1348 CM_Create_DevNode_ExA(
1349     _Out_ PDEVINST pdnDevInst,
1350     _In_ DEVINSTID_A pDeviceID,
1351     _In_ DEVINST dnParent,
1352     _In_ ULONG ulFlags,
1353     _In_opt_ HANDLE hMachine)
1354 {
1355     DEVINSTID_W pDeviceIDW;
1356     CONFIGRET ret;
1357 
1358     TRACE("CM_Create_DevNode_ExA(%p %s %p %lx %p)\n",
1359           pdnDevInst, debugstr_a(pDeviceID), dnParent, ulFlags, hMachine);
1360 
1361     if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIDW))
1362         return CR_INVALID_DATA;
1363 
1364     ret = CM_Create_DevNode_ExW(pdnDevInst, pDeviceIDW, dnParent, ulFlags,
1365                                 hMachine);
1366 
1367     MyFree(pDeviceIDW);
1368 
1369     return ret;
1370 }
1371 
1372 
1373 /***********************************************************************
1374  * CM_Create_DevNode_ExW [SETUPAPI.@]
1375  */
1376 CONFIGRET
1377 WINAPI
1378 CM_Create_DevNode_ExW(
1379     _Out_ PDEVINST pdnDevInst,
1380     _In_ DEVINSTID_W pDeviceID,
1381     _In_ DEVINST dnParent,
1382     _In_ ULONG ulFlags,
1383     _In_opt_ HANDLE hMachine)
1384 {
1385     RPC_BINDING_HANDLE BindingHandle = NULL;
1386     HSTRING_TABLE StringTable = NULL;
1387     LPWSTR lpParentDevInst;
1388     CONFIGRET ret = CR_SUCCESS;
1389     WCHAR szLocalDeviceID[MAX_DEVICE_ID_LEN];
1390 
1391     TRACE("CM_Create_DevNode_ExW(%p %s %p %lx %p)\n",
1392           pdnDevInst, debugstr_w(pDeviceID), dnParent, ulFlags, hMachine);
1393 
1394     if (!pSetupIsUserAdmin())
1395         return CR_ACCESS_DENIED;
1396 
1397     if (pdnDevInst == NULL)
1398         return CR_INVALID_POINTER;
1399 
1400     if (pDeviceID == NULL || wcslen(pDeviceID) == 0 || wcslen(pDeviceID) >= MAX_DEVICE_ID_LEN)
1401         return CR_INVALID_DEVICE_ID;
1402 
1403     if (dnParent == 0)
1404         return CR_INVALID_DEVNODE;
1405 
1406     if (ulFlags & ~CM_CREATE_DEVNODE_BITS)
1407         return CR_INVALID_FLAG;
1408 
1409     if (hMachine != NULL)
1410     {
1411         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1412         if (BindingHandle == NULL)
1413             return CR_FAILURE;
1414 
1415         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1416         if (StringTable == 0)
1417             return CR_FAILURE;
1418     }
1419     else
1420     {
1421         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1422             return CR_FAILURE;
1423     }
1424 
1425     lpParentDevInst = pSetupStringTableStringFromId(StringTable, dnParent);
1426     if (lpParentDevInst == NULL)
1427         return CR_INVALID_DEVNODE;
1428 
1429     wcscpy(szLocalDeviceID, pDeviceID);
1430 
1431     RpcTryExcept
1432     {
1433         ret = PNP_CreateDevInst(BindingHandle,
1434                                 szLocalDeviceID,
1435                                 lpParentDevInst,
1436                                 MAX_DEVICE_ID_LEN,
1437                                 ulFlags);
1438     }
1439     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1440     {
1441         ret = RpcStatusToCmStatus(RpcExceptionCode());
1442     }
1443     RpcEndExcept;
1444 
1445     if (ret == CR_SUCCESS)
1446     {
1447         /* If CM_CREATE_DEVINST_GENERATE_ID was passed in, PNP_CreateDevInst
1448          * will return the generated device ID in szLocalDeviceID */
1449         *pdnDevInst = pSetupStringTableAddString(StringTable, szLocalDeviceID, 1);
1450         if (*pdnDevInst == 0)
1451             ret = CR_NO_SUCH_DEVNODE;
1452     }
1453 
1454     return ret;
1455 }
1456 
1457 
1458 /***********************************************************************
1459  * CM_Create_Range_List [SETUPAPI.@]
1460  */
1461 CONFIGRET
1462 WINAPI
1463 CM_Create_Range_List(
1464     _Out_ PRANGE_LIST prlh,
1465     _In_ ULONG ulFlags)
1466 {
1467     PINTERNAL_RANGE_LIST pRangeList;
1468 
1469     FIXME("CM_Create_Range_List(%p %lx)\n",
1470           prlh, ulFlags);
1471 
1472     if (ulFlags != 0)
1473         return CR_INVALID_FLAG;
1474 
1475     if (prlh == NULL)
1476         return CR_INVALID_POINTER;
1477 
1478     /* Allocate the range list */
1479     pRangeList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(INTERNAL_RANGE_LIST));
1480     if (pRangeList == NULL)
1481         return CR_OUT_OF_MEMORY;
1482 
1483     /* Set the magic value */
1484     pRangeList->ulMagic = RANGE_LIST_MAGIC;
1485 
1486     /* Initialize the mutex for synchonized access */
1487     pRangeList->hMutex = CreateMutex(NULL, FALSE, NULL);
1488     if (pRangeList->hMutex == NULL)
1489     {
1490         HeapFree(GetProcessHeap(), 0, pRangeList);
1491         return CR_FAILURE;
1492     }
1493 
1494     InitializeListHead(&pRangeList->ListHead);
1495 
1496     *prlh = (RANGE_LIST)pRangeList;
1497 
1498     return CR_SUCCESS;
1499 }
1500 
1501 
1502 /***********************************************************************
1503  * CM_Delete_Class_Key [SETUPAPI.@]
1504  */
1505 CONFIGRET
1506 WINAPI
1507 CM_Delete_Class_Key(
1508     _In_ LPGUID ClassGuid,
1509     _In_ ULONG ulFlags)
1510 {
1511     TRACE("CM_Delete_Class_Key(%p %lx)\n",
1512           ClassGuid, ulFlags);
1513 
1514     return CM_Delete_Class_Key_Ex(ClassGuid, ulFlags, NULL);
1515 }
1516 
1517 
1518 /***********************************************************************
1519  * CM_Delete_Class_Key_Ex [SETUPAPI.@]
1520  */
1521 CONFIGRET
1522 WINAPI
1523 CM_Delete_Class_Key_Ex(
1524     _In_ LPGUID ClassGuid,
1525     _In_ ULONG ulFlags,
1526     _In_opt_ HANDLE hMachine)
1527 {
1528     WCHAR szGuidString[MAX_GUID_STRING_LEN];
1529     RPC_BINDING_HANDLE BindingHandle = NULL;
1530     CONFIGRET ret;
1531 
1532     TRACE("CM_Delete_Class_Key_Ex(%p %lx %p)\n",
1533           ClassGuid, ulFlags, hMachine);
1534 
1535     if (ClassGuid == NULL)
1536         return CR_INVALID_POINTER;
1537 
1538     if (ulFlags & ~CM_DELETE_CLASS_BITS)
1539         return CR_INVALID_FLAG;
1540 
1541     if (!GuidToString(ClassGuid, szGuidString))
1542         return CR_INVALID_DATA;
1543 
1544     if (hMachine != NULL)
1545     {
1546         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1547         if (BindingHandle == NULL)
1548             return CR_FAILURE;
1549     }
1550     else
1551     {
1552         if (!PnpGetLocalHandles(&BindingHandle, NULL))
1553             return CR_FAILURE;
1554     }
1555 
1556     RpcTryExcept
1557     {
1558         ret = PNP_DeleteClassKey(BindingHandle,
1559                                  szGuidString,
1560                                  ulFlags);
1561     }
1562     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1563     {
1564         ret = RpcStatusToCmStatus(RpcExceptionCode());
1565     }
1566     RpcEndExcept;
1567 
1568     return ret;
1569 }
1570 
1571 
1572 /***********************************************************************
1573  * CM_Delete_DevNode_Key [SETUPAPI.@]
1574  */
1575 CONFIGRET
1576 WINAPI
1577 CM_Delete_DevNode_Key(
1578     _In_ DEVINST dnDevInst,
1579     _In_ ULONG ulHardwareProfile,
1580     _In_ ULONG ulFlags)
1581 {
1582     TRACE("CM_Delete_DevNode_Key(%p %lu %lx)\n",
1583           dnDevInst, ulHardwareProfile, ulFlags);
1584 
1585     return CM_Delete_DevNode_Key_Ex(dnDevInst, ulHardwareProfile, ulFlags,
1586                                     NULL);
1587 }
1588 
1589 
1590 /***********************************************************************
1591  * CM_Delete_DevNode_Key_Ex [SETUPAPI.@]
1592  */
1593 CONFIGRET
1594 WINAPI
1595 CM_Delete_DevNode_Key_Ex(
1596     _In_ DEVINST dnDevInst,
1597     _In_ ULONG ulHardwareProfile,
1598     _In_ ULONG ulFlags,
1599     _In_opt_ HANDLE hMachine)
1600 {
1601     RPC_BINDING_HANDLE BindingHandle = NULL;
1602     HSTRING_TABLE StringTable = NULL;
1603     PWSTR pszDevInst, pszKeyPath = NULL, pszInstancePath = NULL;
1604     CONFIGRET ret;
1605 
1606     FIXME("CM_Delete_DevNode_Key_Ex(%p %lu %lx %p)\n",
1607           dnDevInst, ulHardwareProfile, ulFlags, hMachine);
1608 
1609     if (dnDevInst == 0)
1610         return CR_INVALID_DEVINST;
1611 
1612     if (ulFlags & ~CM_REGISTRY_BITS)
1613         return CR_INVALID_FLAG;
1614 
1615     if ((ulFlags & CM_REGISTRY_USER) && (ulFlags & CM_REGISTRY_CONFIG))
1616         return CR_INVALID_FLAG;
1617 
1618     if (hMachine != NULL)
1619     {
1620         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1621         if (BindingHandle == NULL)
1622             return CR_FAILURE;
1623 
1624         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1625         if (StringTable == 0)
1626             return CR_FAILURE;
1627     }
1628     else
1629     {
1630         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1631             return CR_FAILURE;
1632     }
1633 
1634     pszDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1635     if (pszDevInst == NULL)
1636         return CR_INVALID_DEVNODE;
1637 
1638     TRACE("pszDevInst: %S\n", pszDevInst);
1639 
1640     pszKeyPath = MyMalloc(512 * sizeof(WCHAR));
1641     if (pszKeyPath == NULL)
1642     {
1643         ret = CR_OUT_OF_MEMORY;
1644         goto done;
1645     }
1646 
1647     pszInstancePath = MyMalloc(512 * sizeof(WCHAR));
1648     if (pszInstancePath == NULL)
1649     {
1650         ret = CR_OUT_OF_MEMORY;
1651         goto done;
1652     }
1653 
1654     ret = GetDeviceInstanceKeyPath(BindingHandle,
1655                                    pszDevInst,
1656                                    pszKeyPath,
1657                                    pszInstancePath,
1658                                    ulHardwareProfile,
1659                                    ulFlags);
1660     if (ret != CR_SUCCESS)
1661         goto done;
1662 
1663     TRACE("pszKeyPath: %S\n", pszKeyPath);
1664     TRACE("pszInstancePath: %S\n", pszInstancePath);
1665 
1666     if (ulFlags & CM_REGISTRY_USER)
1667     {
1668         FIXME("The CM_REGISTRY_USER flag is not supported yet!\n");
1669     }
1670     else
1671     {
1672 #if 0
1673         if (!pSetupIsUserAdmin())
1674         {
1675             ret = CR_ACCESS_DENIED;
1676             goto done;
1677         }
1678 #endif
1679 
1680         if (!(ulFlags & CM_REGISTRY_CONFIG))
1681             ulHardwareProfile = 0;
1682 
1683         RpcTryExcept
1684         {
1685             ret = PNP_DeleteRegistryKey(BindingHandle,
1686                                         pszDevInst,
1687                                         pszKeyPath,
1688                                         pszInstancePath,
1689                                         ulHardwareProfile);
1690         }
1691         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1692         {
1693             ret = RpcStatusToCmStatus(RpcExceptionCode());
1694         }
1695         RpcEndExcept;
1696     }
1697 
1698 done:
1699     if (pszInstancePath != NULL)
1700         MyFree(pszInstancePath);
1701 
1702     if (pszKeyPath != NULL)
1703         MyFree(pszKeyPath);
1704 
1705     return ret;
1706 }
1707 
1708 
1709 /***********************************************************************
1710  * CM_Delete_Range [SETUPAPI.@]
1711  */
1712 CONFIGRET
1713 WINAPI
1714 CM_Delete_Range(
1715     _In_ DWORDLONG ullStartValue,
1716     _In_ DWORDLONG ullEndValue,
1717     _In_ RANGE_LIST rlh,
1718     _In_ ULONG ulFlags)
1719 {
1720     FIXME("CM_Delete_Range(%I64u %I64u %p %lx)\n",
1721           ullStartValue, ullEndValue, rlh, ulFlags);
1722 
1723     return CR_CALL_NOT_IMPLEMENTED;
1724 }
1725 
1726 
1727 /***********************************************************************
1728  * CM_Detect_Resource_Conflict [SETUPAPI.@]
1729  */
1730 CONFIGRET
1731 WINAPI
1732 CM_Detect_Resource_Conflict(
1733     _In_ DEVINST dnDevInst,
1734     _In_ RESOURCEID ResourceID,
1735     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1736     _In_ ULONG ResourceLen,
1737     _Out_ PBOOL pbConflictDetected,
1738     _In_ ULONG ulFlags)
1739 {
1740     TRACE("CM_Detect_Resource_Conflict(%p %lu %p %lu %p 0x%lx)\n",
1741           dnDevInst, ResourceID, ResourceData, ResourceLen,
1742           pbConflictDetected, ulFlags);
1743 
1744     return CM_Detect_Resource_Conflict_Ex(dnDevInst,
1745                                           ResourceID,
1746                                           ResourceData,
1747                                           ResourceLen,
1748                                           pbConflictDetected,
1749                                           ulFlags,
1750                                           NULL);
1751 }
1752 
1753 
1754 /***********************************************************************
1755  * CM_Detect_Resource_Conflict_Ex [SETUPAPI.@]
1756  */
1757 CONFIGRET
1758 WINAPI
1759 CM_Detect_Resource_Conflict_Ex(
1760     _In_ DEVINST dnDevInst,
1761     _In_ RESOURCEID ResourceID,
1762     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
1763     _In_ ULONG ResourceLen,
1764     _Out_ PBOOL pbConflictDetected,
1765     _In_ ULONG ulFlags,
1766     _In_opt_ HMACHINE hMachine)
1767 {
1768     FIXME("CM_Detect_Resource_Conflict_Ex(%p %lu %p %lu %p 0x%lx %p)\n",
1769           dnDevInst, ResourceID, ResourceData, ResourceLen,
1770           pbConflictDetected, ulFlags, hMachine);
1771 
1772     return CR_CALL_NOT_IMPLEMENTED;
1773 }
1774 
1775 
1776 /***********************************************************************
1777  * CM_Disable_DevNode [SETUPAPI.@]
1778  */
1779 CONFIGRET
1780 WINAPI
1781 CM_Disable_DevNode(
1782     _In_ DEVINST dnDevInst,
1783     _In_ ULONG ulFlags)
1784 {
1785     TRACE("CM_Disable_DevNode(%p %lx)\n",
1786           dnDevInst, ulFlags);
1787 
1788     return CM_Disable_DevNode_Ex(dnDevInst, ulFlags, NULL);
1789 }
1790 
1791 
1792 /***********************************************************************
1793  * CM_Disable_DevNode_Ex [SETUPAPI.@]
1794  */
1795 CONFIGRET
1796 WINAPI
1797 CM_Disable_DevNode_Ex(
1798     _In_ DEVINST dnDevInst,
1799     _In_ ULONG ulFlags,
1800     _In_opt_ HMACHINE hMachine)
1801 {
1802     RPC_BINDING_HANDLE BindingHandle = NULL;
1803     HSTRING_TABLE StringTable = NULL;
1804     LPWSTR lpDevInst;
1805     CONFIGRET ret;
1806 
1807     TRACE("CM_Disable_DevNode_Ex(%p %lx %p)\n",
1808           dnDevInst, ulFlags, hMachine);
1809 
1810     if (!pSetupIsUserAdmin())
1811         return CR_ACCESS_DENIED;
1812 
1813     if (dnDevInst == 0)
1814         return CR_INVALID_DEVINST;
1815 
1816     if (ulFlags != 0)
1817         return CR_INVALID_FLAG;
1818 
1819     if (hMachine != NULL)
1820     {
1821         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1822         if (BindingHandle == NULL)
1823             return CR_FAILURE;
1824 
1825         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1826         if (StringTable == 0)
1827             return CR_FAILURE;
1828     }
1829     else
1830     {
1831         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1832             return CR_FAILURE;
1833     }
1834 
1835     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1836     if (lpDevInst == NULL)
1837         return CR_INVALID_DEVNODE;
1838 
1839     RpcTryExcept
1840     {
1841         ret = PNP_DisableDevInst(BindingHandle,
1842                                  lpDevInst,
1843                                  NULL,
1844                                  NULL,
1845                                  0,
1846                                  ulFlags);
1847     }
1848     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1849     {
1850         ret = RpcStatusToCmStatus(RpcExceptionCode());
1851     }
1852     RpcEndExcept;
1853 
1854     return ret;
1855 }
1856 
1857 
1858 /***********************************************************************
1859  * CM_Disconnect_Machine [SETUPAPI.@]
1860  */
1861 CONFIGRET
1862 WINAPI
1863 CM_Disconnect_Machine(
1864     _In_opt_ HMACHINE hMachine)
1865 {
1866     PMACHINE_INFO pMachine;
1867 
1868     TRACE("CM_Disconnect_Machine(%p)\n", hMachine);
1869 
1870     pMachine = (PMACHINE_INFO)hMachine;
1871     if (pMachine == NULL)
1872         return CR_SUCCESS;
1873 
1874     if (pMachine->bLocal == FALSE)
1875     {
1876         if (pMachine->StringTable != NULL)
1877             pSetupStringTableDestroy(pMachine->StringTable);
1878 
1879         if (!PnpUnbindRpc(pMachine->BindingHandle))
1880             return CR_ACCESS_DENIED;
1881     }
1882 
1883     HeapFree(GetProcessHeap(), 0, pMachine);
1884 
1885     return CR_SUCCESS;
1886 }
1887 
1888 
1889 /***********************************************************************
1890  * CM_Dup_Range_List [SETUPAPI.@]
1891  */
1892 CONFIGRET
1893 WINAPI
1894 CM_Dup_Range_List(
1895     _In_ RANGE_LIST rlhOld,
1896     _In_ RANGE_LIST rlhNew,
1897     _In_ ULONG ulFlags)
1898 {
1899     FIXME("CM_Dup_Range_List(%p %p %lx)\n",
1900           rlhOld, rlhNew, ulFlags);
1901 
1902     return CR_CALL_NOT_IMPLEMENTED;
1903 }
1904 
1905 
1906 /***********************************************************************
1907  * CM_Enable_DevNode [SETUPAPI.@]
1908  */
1909 CONFIGRET
1910 WINAPI
1911 CM_Enable_DevNode(
1912     _In_ DEVINST dnDevInst,
1913     _In_ ULONG ulFlags)
1914 {
1915     TRACE("CM_Enable_DevNode(%p %lx)\n",
1916           dnDevInst, ulFlags);
1917 
1918     return CM_Enable_DevNode_Ex(dnDevInst, ulFlags, NULL);
1919 }
1920 
1921 
1922 /***********************************************************************
1923  * CM_Enable_DevNode_Ex [SETUPAPI.@]
1924  */
1925 CONFIGRET
1926 WINAPI
1927 CM_Enable_DevNode_Ex(
1928     _In_ DEVINST dnDevInst,
1929     _In_ ULONG ulFlags,
1930     _In_opt_ HMACHINE hMachine)
1931 {
1932     RPC_BINDING_HANDLE BindingHandle = NULL;
1933     HSTRING_TABLE StringTable = NULL;
1934     LPWSTR lpDevInst;
1935     CONFIGRET ret;
1936 
1937     TRACE("CM_Enable_DevNode_Ex(%p %lx %p)\n",
1938           dnDevInst, ulFlags, hMachine);
1939 
1940     if (!pSetupIsUserAdmin())
1941         return CR_ACCESS_DENIED;
1942 
1943     if (dnDevInst == 0)
1944         return CR_INVALID_DEVINST;
1945 
1946     if (ulFlags != 0)
1947         return CR_INVALID_FLAG;
1948 
1949     if (hMachine != NULL)
1950     {
1951         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1952         if (BindingHandle == NULL)
1953             return CR_FAILURE;
1954 
1955         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1956         if (StringTable == 0)
1957             return CR_FAILURE;
1958     }
1959     else
1960     {
1961         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1962             return CR_FAILURE;
1963     }
1964 
1965     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1966     if (lpDevInst == NULL)
1967         return CR_INVALID_DEVNODE;
1968 
1969     RpcTryExcept
1970     {
1971         ret = PNP_DeviceInstanceAction(BindingHandle,
1972                                        PNP_DEVINST_ENABLE,
1973                                        ulFlags,
1974                                        lpDevInst,
1975                                        NULL);
1976     }
1977     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1978     {
1979         ret = RpcStatusToCmStatus(RpcExceptionCode());
1980     }
1981     RpcEndExcept;
1982 
1983     return ret;
1984 }
1985 
1986 
1987 /***********************************************************************
1988  * CM_Enumerate_Classes [SETUPAPI.@]
1989  */
1990 CONFIGRET
1991 WINAPI
1992 CM_Enumerate_Classes(
1993     _In_ ULONG ulClassIndex,
1994     _Out_ LPGUID ClassGuid,
1995     _In_ ULONG ulFlags)
1996 {
1997     TRACE("CM_Enumerate_Classes(%lx %p %lx)\n",
1998           ulClassIndex, ClassGuid, ulFlags);
1999 
2000     return CM_Enumerate_Classes_Ex(ulClassIndex, ClassGuid, ulFlags, NULL);
2001 }
2002 
2003 
2004 /***********************************************************************
2005  * CM_Enumerate_Classes_Ex [SETUPAPI.@]
2006  */
2007 CONFIGRET
2008 WINAPI
2009 CM_Enumerate_Classes_Ex(
2010     _In_ ULONG ulClassIndex,
2011     _Out_ LPGUID ClassGuid,
2012     _In_ ULONG ulFlags,
2013     _In_opt_ HMACHINE hMachine)
2014 {
2015     WCHAR szBuffer[MAX_GUID_STRING_LEN];
2016     RPC_BINDING_HANDLE BindingHandle = NULL;
2017     CONFIGRET ret = CR_SUCCESS;
2018     ULONG ulLength = MAX_GUID_STRING_LEN;
2019 
2020     TRACE("CM_Enumerate_Classes_Ex(%lx %p %lx %p)\n",
2021           ulClassIndex, ClassGuid, ulFlags, hMachine);
2022 
2023     if (ClassGuid == NULL)
2024         return CR_INVALID_POINTER;
2025 
2026     if (ulFlags != 0)
2027         return CR_INVALID_FLAG;
2028 
2029     if (hMachine != NULL)
2030     {
2031         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2032         if (BindingHandle == NULL)
2033             return CR_FAILURE;
2034     }
2035     else
2036     {
2037         if (!PnpGetLocalHandles(&BindingHandle, NULL))
2038             return CR_FAILURE;
2039     }
2040 
2041     RpcTryExcept
2042     {
2043         ret = PNP_EnumerateSubKeys(BindingHandle,
2044                                    PNP_CLASS_SUBKEYS,
2045                                    ulClassIndex,
2046                                    szBuffer,
2047                                    MAX_GUID_STRING_LEN,
2048                                    &ulLength,
2049                                    ulFlags);
2050     }
2051     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2052     {
2053         ret = RpcStatusToCmStatus(RpcExceptionCode());
2054     }
2055     RpcEndExcept;
2056 
2057     if (ret == CR_SUCCESS)
2058     {
2059         /* Remove the {} */
2060         szBuffer[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
2061 
2062         /* Convert the buffer to a GUID */
2063         if (UuidFromStringW(&szBuffer[1], ClassGuid) != RPC_S_OK)
2064             return CR_FAILURE;
2065     }
2066 
2067     return ret;
2068 }
2069 
2070 
2071 /***********************************************************************
2072  * CM_Enumerate_EnumeratorsA [SETUPAPI.@]
2073  */
2074 CONFIGRET
2075 WINAPI
2076 CM_Enumerate_EnumeratorsA(
2077     _In_ ULONG ulEnumIndex,
2078     _Out_writes_(*pulLength) PCHAR Buffer,
2079     _Inout_ PULONG pulLength,
2080     _In_ ULONG ulFlags)
2081 {
2082     TRACE("CM_Enumerate_EnumeratorsA(%lu %p %p %lx)\n",
2083           ulEnumIndex, Buffer, pulLength, ulFlags);
2084 
2085     return CM_Enumerate_Enumerators_ExA(ulEnumIndex, Buffer, pulLength,
2086                                         ulFlags, NULL);
2087 }
2088 
2089 
2090 /***********************************************************************
2091  * CM_Enumerate_EnumeratorsW [SETUPAPI.@]
2092  */
2093 CONFIGRET
2094 WINAPI
2095 CM_Enumerate_EnumeratorsW(
2096     _In_ ULONG ulEnumIndex,
2097     _Out_writes_(*pulLength) PWCHAR Buffer,
2098     _Inout_ PULONG pulLength,
2099     _In_ ULONG ulFlags)
2100 {
2101     TRACE("CM_Enumerate_EnumeratorsW(%lu %p %p %lx)\n",
2102           ulEnumIndex, Buffer, pulLength, ulFlags);
2103 
2104     return CM_Enumerate_Enumerators_ExW(ulEnumIndex, Buffer, pulLength,
2105                                         ulFlags, NULL);
2106 }
2107 
2108 
2109 /***********************************************************************
2110  * CM_Enumerate_Enumerators_ExA [SETUPAPI.@]
2111  */
2112 CONFIGRET
2113 WINAPI
2114 CM_Enumerate_Enumerators_ExA(
2115     _In_ ULONG ulEnumIndex,
2116     _Out_writes_(*pulLength) PCHAR Buffer,
2117     _Inout_ PULONG pulLength,
2118     _In_ ULONG ulFlags,
2119     _In_opt_ HMACHINE hMachine)
2120 {
2121     WCHAR szBuffer[MAX_DEVICE_ID_LEN];
2122     ULONG ulOrigLength;
2123     ULONG ulLength;
2124     CONFIGRET ret = CR_SUCCESS;
2125 
2126     TRACE("CM_Enumerate_Enumerators_ExA(%lu %p %p %lx %p)\n",
2127           ulEnumIndex, Buffer, pulLength, ulFlags, hMachine);
2128 
2129     if (Buffer == NULL || pulLength == NULL)
2130         return CR_INVALID_POINTER;
2131 
2132     if (ulFlags != 0)
2133         return CR_INVALID_FLAG;
2134 
2135     ulOrigLength = *pulLength;
2136     *pulLength = 0;
2137 
2138     ulLength = MAX_DEVICE_ID_LEN;
2139     ret = CM_Enumerate_Enumerators_ExW(ulEnumIndex, szBuffer, &ulLength,
2140                                        ulFlags, hMachine);
2141     if (ret == CR_SUCCESS)
2142     {
2143         if (WideCharToMultiByte(CP_ACP,
2144                                 0,
2145                                 szBuffer,
2146                                 ulLength,
2147                                 Buffer,
2148                                 ulOrigLength,
2149                                 NULL,
2150                                 NULL) == 0)
2151             ret = CR_FAILURE;
2152         else
2153             *pulLength = lstrlenA(Buffer) + 1;
2154     }
2155 
2156     return ret;
2157 }
2158 
2159 
2160 /***********************************************************************
2161  * CM_Enumerate_Enumerators_ExW [SETUPAPI.@]
2162  */
2163 CONFIGRET
2164 WINAPI
2165 CM_Enumerate_Enumerators_ExW(
2166     _In_ ULONG ulEnumIndex,
2167     _Out_writes_(*pulLength) PWCHAR Buffer,
2168     _Inout_ PULONG pulLength,
2169     _In_ ULONG ulFlags,
2170     _In_opt_ HMACHINE hMachine)
2171 {
2172     RPC_BINDING_HANDLE BindingHandle = NULL;
2173     CONFIGRET ret;
2174 
2175     TRACE("CM_Enumerate_Enumerators_ExW(%lu %p %p %lx %p)\n",
2176           ulEnumIndex, Buffer, pulLength, ulFlags, hMachine);
2177 
2178     if (Buffer == NULL || pulLength == NULL)
2179         return CR_INVALID_POINTER;
2180 
2181     if (ulFlags != 0)
2182         return CR_INVALID_FLAG;
2183 
2184     *Buffer = UNICODE_NULL;
2185 
2186     if (hMachine != NULL)
2187     {
2188         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2189         if (BindingHandle == NULL)
2190             return CR_FAILURE;
2191     }
2192     else
2193     {
2194         if (!PnpGetLocalHandles(&BindingHandle, NULL))
2195             return CR_FAILURE;
2196     }
2197 
2198     RpcTryExcept
2199     {
2200         ret = PNP_EnumerateSubKeys(BindingHandle,
2201                                    PNP_ENUMERATOR_SUBKEYS,
2202                                    ulEnumIndex,
2203                                    Buffer,
2204                                    *pulLength,
2205                                    pulLength,
2206                                    ulFlags);
2207     }
2208     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2209     {
2210         ret = RpcStatusToCmStatus(RpcExceptionCode());
2211     }
2212     RpcEndExcept;
2213 
2214     return ret;
2215 }
2216 
2217 
2218 /***********************************************************************
2219  * CM_Find_Range [SETUPAPI.@]
2220  */
2221 CONFIGRET
2222 WINAPI
2223 CM_Find_Range(
2224     _Out_ PDWORDLONG pullStart,
2225     _In_ DWORDLONG ullStart,
2226     _In_ ULONG ulLength,
2227     _In_ DWORDLONG ullAlignment,
2228     _In_ DWORDLONG ullEnd,
2229     _In_ RANGE_LIST rlh,
2230     _In_ ULONG ulFlags)
2231 {
2232     FIXME("CM_Find_Range(%p %I64u %lu %I64u %I64u %p %lx)\n",
2233           pullStart, ullStart, ulLength, ullAlignment, ullEnd, rlh, ulFlags);
2234 
2235     return CR_CALL_NOT_IMPLEMENTED;
2236 }
2237 
2238 
2239 /***********************************************************************
2240  * CM_First_Range [SETUPAPI.@]
2241  */
2242 CONFIGRET
2243 WINAPI
2244 CM_First_Range(
2245     _In_ RANGE_LIST rlh,
2246     _Out_ PDWORDLONG pullStart,
2247     _Out_ PDWORDLONG pullEnd,
2248     _Out_ PRANGE_ELEMENT preElement,
2249     _In_ ULONG ulFlags)
2250 {
2251     PINTERNAL_RANGE_LIST pRangeList;
2252     PINTERNAL_RANGE pRange;
2253     PLIST_ENTRY ListEntry;
2254     CONFIGRET ret = CR_SUCCESS;
2255 
2256     FIXME("CM_First_Range(%p %p %p %p %lx)\n",
2257           rlh, pullStart, pullEnd, preElement, ulFlags);
2258 
2259     pRangeList = (PINTERNAL_RANGE_LIST)rlh;
2260 
2261     if (!IsValidRangeList(pRangeList))
2262         return CR_INVALID_RANGE_LIST;
2263 
2264     if (pullStart == NULL || pullEnd == NULL || preElement == NULL)
2265         return CR_INVALID_POINTER;
2266 
2267     if (ulFlags != 0)
2268         return CR_INVALID_FLAG;
2269 
2270     /* Lock the range list */
2271     WaitForSingleObject(pRangeList->hMutex, INFINITE);
2272 
2273     /* Fail, if the list is empty */
2274     if (IsListEmpty(&pRangeList->ListHead))
2275     {
2276         ret = CR_FAILURE;
2277         goto done;
2278     }
2279 
2280     /* Get the first range */
2281     ListEntry = pRangeList->ListHead.Flink;
2282     pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
2283 
2284     /* Return the range data */
2285     *pullStart = pRange->ullStart;
2286     *pullEnd = pRange->ullEnd;
2287     *preElement = (RANGE_ELEMENT)pRange;
2288 
2289 done:
2290     /* Unlock the range list */
2291     ReleaseMutex(pRangeList->hMutex);
2292 
2293     return ret;
2294 }
2295 
2296 
2297 /***********************************************************************
2298  * CM_Free_Log_Conf [SETUPAPI.@]
2299  */
2300 CONFIGRET
2301 WINAPI
2302 CM_Free_Log_Conf(
2303     _In_ LOG_CONF lcLogConfToBeFreed,
2304     _In_ ULONG ulFlags)
2305 {
2306     TRACE("CM_Free_Log_Conf(%lx %lx)\n",
2307           lcLogConfToBeFreed, ulFlags);
2308 
2309     return CM_Free_Log_Conf_Ex(lcLogConfToBeFreed, ulFlags, NULL);
2310 }
2311 
2312 
2313 /***********************************************************************
2314  * CM_Free_Log_Conf_Ex [SETUPAPI.@]
2315  */
2316 CONFIGRET
2317 WINAPI
2318 CM_Free_Log_Conf_Ex(
2319     _In_ LOG_CONF lcLogConfToBeFreed,
2320     _In_ ULONG ulFlags,
2321     _In_opt_ HMACHINE hMachine)
2322 {
2323     RPC_BINDING_HANDLE BindingHandle = NULL;
2324     HSTRING_TABLE StringTable = NULL;
2325     LPWSTR lpDevInst;
2326     PLOG_CONF_INFO pLogConfInfo;
2327     CONFIGRET ret;
2328 
2329     TRACE("CM_Free_Log_Conf_Ex(%lx %lx %p)\n",
2330           lcLogConfToBeFreed, ulFlags, hMachine);
2331 
2332     if (!pSetupIsUserAdmin())
2333         return CR_ACCESS_DENIED;
2334 
2335     pLogConfInfo = (PLOG_CONF_INFO)lcLogConfToBeFreed;
2336     if (!IsValidLogConf(pLogConfInfo))
2337         return CR_INVALID_LOG_CONF;
2338 
2339     if (ulFlags != 0)
2340         return CR_INVALID_FLAG;
2341 
2342     if (hMachine != NULL)
2343     {
2344         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2345         if (BindingHandle == NULL)
2346             return CR_FAILURE;
2347 
2348         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
2349         if (StringTable == 0)
2350             return CR_FAILURE;
2351     }
2352     else
2353     {
2354         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
2355             return CR_FAILURE;
2356     }
2357 
2358     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
2359     if (lpDevInst == NULL)
2360         return CR_INVALID_DEVNODE;
2361 
2362     RpcTryExcept
2363     {
2364         ret = PNP_FreeLogConf(BindingHandle,
2365                               lpDevInst,
2366                               pLogConfInfo->ulType,
2367                               pLogConfInfo->ulTag,
2368                               0);
2369     }
2370     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2371     {
2372         ret = RpcStatusToCmStatus(RpcExceptionCode());
2373     }
2374     RpcEndExcept;
2375 
2376     return ret;
2377 }
2378 
2379 
2380 /***********************************************************************
2381  * CM_Free_Log_Conf_Handle [SETUPAPI.@]
2382  */
2383 CONFIGRET
2384 WINAPI
2385 CM_Free_Log_Conf_Handle(
2386     _In_ LOG_CONF lcLogConf)
2387 {
2388     PLOG_CONF_INFO pLogConfInfo;
2389 
2390     TRACE("CM_Free_Log_Conf_Handle(%lx)\n", lcLogConf);
2391 
2392     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
2393     if (!IsValidLogConf(pLogConfInfo))
2394         return CR_INVALID_LOG_CONF;
2395 
2396     HeapFree(GetProcessHeap(), 0, pLogConfInfo);
2397 
2398     return CR_SUCCESS;
2399 }
2400 
2401 
2402 /***********************************************************************
2403  * CM_Free_Range_List [SETUPAPI.@]
2404  */
2405 CONFIGRET
2406 WINAPI
2407 CM_Free_Range_List(
2408     _In_ RANGE_LIST RangeList,
2409     _In_ ULONG ulFlags)
2410 {
2411     PINTERNAL_RANGE_LIST pRangeList;
2412     PINTERNAL_RANGE pRange;
2413     PLIST_ENTRY ListEntry;
2414 
2415     FIXME("CM_Free_Range_List(%p %lx)\n",
2416           RangeList, ulFlags);
2417 
2418     pRangeList = (PINTERNAL_RANGE_LIST)RangeList;
2419 
2420     if (!IsValidRangeList(pRangeList))
2421         return CR_INVALID_RANGE_LIST;
2422 
2423     if (ulFlags != 0)
2424         return CR_INVALID_FLAG;
2425 
2426     /* Lock the range list */
2427     WaitForSingleObject(pRangeList->hMutex, INFINITE);
2428 
2429     /* Free the list of ranges */
2430     while (!IsListEmpty(&pRangeList->ListHead))
2431     {
2432         ListEntry = RemoveHeadList(&pRangeList->ListHead);
2433         pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
2434         HeapFree(GetProcessHeap(), 0, pRange);
2435     }
2436 
2437     /* Unlock the range list */
2438     ReleaseMutex(pRangeList->hMutex);
2439 
2440     /* Close the mutex */
2441     CloseHandle(pRangeList->hMutex);
2442 
2443     /* Free the range list */
2444     HeapFree(GetProcessHeap(), 0, pRangeList);
2445 
2446     return CR_SUCCESS;
2447 }
2448 
2449 
2450 /***********************************************************************
2451  * CM_Free_Res_Des [SETUPAPI.@]
2452  */
2453 CONFIGRET
2454 WINAPI
2455 CM_Free_Res_Des(
2456     _Out_ PRES_DES prdResDes,
2457     _In_ RES_DES rdResDes,
2458     _In_ ULONG ulFlags)
2459 {
2460     TRACE("CM_Free_Res_Des(%p %p %lx)\n",
2461           prdResDes, rdResDes, ulFlags);
2462 
2463     return CM_Free_Res_Des_Ex(prdResDes, rdResDes, ulFlags, NULL);
2464 }
2465 
2466 
2467 /***********************************************************************
2468  * CM_Free_Res_Des_Ex [SETUPAPI.@]
2469  */
2470 CONFIGRET
2471 WINAPI
2472 CM_Free_Res_Des_Ex(
2473     _Out_ PRES_DES prdResDes,
2474     _In_ RES_DES rdResDes,
2475     _In_ ULONG ulFlags,
2476     _In_opt_ HMACHINE hMachine)
2477 {
2478     FIXME("CM_Free_Res_Des_Ex(%p %p %lx %p)\n",
2479           prdResDes, rdResDes, ulFlags, hMachine);
2480 
2481     return CR_CALL_NOT_IMPLEMENTED;
2482 }
2483 
2484 
2485 /***********************************************************************
2486  * CM_Free_Res_Des_Handle [SETUPAPI.@]
2487  */
2488 CONFIGRET
2489 WINAPI
2490 CM_Free_Res_Des_Handle(
2491     _In_ RES_DES rdResDes)
2492 {
2493     FIXME("CM_Free_Res_Des_Handle(%p)\n", rdResDes);
2494 
2495     return CR_CALL_NOT_IMPLEMENTED;
2496 }
2497 
2498 
2499 /***********************************************************************
2500  * CM_Free_Resource_Conflict_Handle [SETUPAPI.@]
2501  */
2502 CONFIGRET
2503 WINAPI
2504 CM_Free_Resource_Conflict_Handle(
2505     _In_ CONFLICT_LIST clConflictList)
2506 {
2507     PCONFLICT_DATA pConflictData;
2508 
2509     FIXME("CM_Free_Resource_Conflict_Handle(%p)\n",
2510           clConflictList);
2511 
2512     pConflictData = (PCONFLICT_DATA)clConflictList;
2513     if (!IsValidConflictData(pConflictData))
2514         return CR_INVALID_CONFLICT_LIST;
2515 
2516     if (pConflictData->pConflictList != NULL)
2517         MyFree(pConflictData->pConflictList);
2518 
2519     MyFree(pConflictData);
2520 
2521     return CR_SUCCESS;
2522 }
2523 
2524 
2525 /***********************************************************************
2526  * CM_Get_Child [SETUPAPI.@]
2527  */
2528 CONFIGRET
2529 WINAPI
2530 CM_Get_Child(
2531     _Out_ PDEVINST pdnDevInst,
2532     _In_ DEVINST dnDevInst,
2533     _In_ ULONG ulFlags)
2534 {
2535     TRACE("CM_Get_Child(%p %p %lx)\n",
2536           pdnDevInst, dnDevInst, ulFlags);
2537 
2538     return CM_Get_Child_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
2539 }
2540 
2541 
2542 /***********************************************************************
2543  * CM_Get_Child_Ex [SETUPAPI.@]
2544  */
2545 CONFIGRET
2546 WINAPI
2547 CM_Get_Child_Ex(
2548     _Out_ PDEVINST pdnDevInst,
2549     _In_ DEVINST dnDevInst,
2550     _In_ ULONG ulFlags,
2551     _In_opt_ HMACHINE hMachine)
2552 {
2553     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
2554     RPC_BINDING_HANDLE BindingHandle = NULL;
2555     HSTRING_TABLE StringTable = NULL;
2556     LPWSTR lpDevInst;
2557     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
2558     CONFIGRET ret;
2559 
2560     TRACE("CM_Get_Child_Ex(%p %lx %lx %p)\n",
2561           pdnDevInst, dnDevInst, ulFlags, hMachine);
2562 
2563     if (pdnDevInst == NULL)
2564         return CR_INVALID_POINTER;
2565 
2566     if (dnDevInst == 0)
2567         return CR_INVALID_DEVINST;
2568 
2569     if (ulFlags != 0)
2570         return CR_INVALID_FLAG;
2571 
2572     *pdnDevInst = -1;
2573 
2574     if (hMachine != NULL)
2575     {
2576         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2577         if (BindingHandle == NULL)
2578             return CR_FAILURE;
2579 
2580         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
2581         if (StringTable == 0)
2582             return CR_FAILURE;
2583     }
2584     else
2585     {
2586         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
2587             return CR_FAILURE;
2588     }
2589 
2590     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
2591     if (lpDevInst == NULL)
2592         return CR_INVALID_DEVNODE;
2593 
2594     RpcTryExcept
2595     {
2596         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
2597                                            PNP_GET_CHILD_DEVICE_INSTANCE,
2598                                            lpDevInst,
2599                                            szRelatedDevInst,
2600                                            &dwLength,
2601                                            0);
2602     }
2603     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2604     {
2605         ret = RpcStatusToCmStatus(RpcExceptionCode());
2606     }
2607     RpcEndExcept;
2608 
2609     if (ret != CR_SUCCESS)
2610         return ret;
2611 
2612     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
2613 
2614     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
2615     if (dwIndex == -1)
2616         return CR_FAILURE;
2617 
2618     *pdnDevInst = dwIndex;
2619 
2620     return CR_SUCCESS;
2621 }
2622 
2623 
2624 /***********************************************************************
2625  * CM_Get_Class_Key_NameA [SETUPAPI.@]
2626  */
2627 CONFIGRET
2628 WINAPI
2629 CM_Get_Class_Key_NameA(
2630     _In_ LPGUID ClassGuid,
2631     _Out_writes_opt_(*pulLength) LPSTR pszKeyName,
2632     _Inout_ PULONG pulLength,
2633     _In_ ULONG ulFlags)
2634 {
2635     TRACE("CM_Get_Class_Key_NameA(%p %p %p %lx)\n",
2636           ClassGuid, pszKeyName, pulLength, ulFlags);
2637 
2638     return CM_Get_Class_Key_Name_ExA(ClassGuid, pszKeyName, pulLength,
2639                                      ulFlags, NULL);
2640 }
2641 
2642 
2643 /***********************************************************************
2644  * CM_Get_Class_Key_NameW [SETUPAPI.@]
2645  */
2646 CONFIGRET
2647 WINAPI
2648 CM_Get_Class_Key_NameW(
2649     _In_ LPGUID ClassGuid,
2650     _Out_writes_opt_(*pulLength) LPWSTR pszKeyName,
2651     _Inout_ PULONG pulLength,
2652     _In_ ULONG ulFlags)
2653 {
2654     TRACE("CM_Get_Class_Key_NameW(%p %p %p %lx)\n",
2655           ClassGuid, pszKeyName, pulLength, ulFlags);
2656 
2657     return CM_Get_Class_Key_Name_ExW(ClassGuid, pszKeyName, pulLength,
2658                                      ulFlags, NULL);
2659 }
2660 
2661 
2662 /***********************************************************************
2663  * CM_Get_Class_Key_Name_ExA [SETUPAPI.@]
2664  */
2665 CONFIGRET
2666 WINAPI
2667 CM_Get_Class_Key_Name_ExA(
2668     _In_ LPGUID ClassGuid,
2669     _Out_writes_opt_(*pulLength) LPSTR pszKeyName,
2670     _Inout_ PULONG pulLength,
2671     _In_ ULONG ulFlags,
2672     _In_opt_ HMACHINE hMachine)
2673 {
2674     WCHAR szBuffer[MAX_GUID_STRING_LEN];
2675     CONFIGRET ret = CR_SUCCESS;
2676     ULONG ulLength;
2677     ULONG ulOrigLength;
2678 
2679     TRACE("CM_Get_Class_Key_Name_ExA(%p %p %p %lx %p)\n",
2680           ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
2681 
2682     if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
2683         return CR_INVALID_POINTER;
2684 
2685     ulOrigLength = *pulLength;
2686     *pulLength = 0;
2687 
2688     ulLength = MAX_GUID_STRING_LEN;
2689     ret = CM_Get_Class_Key_Name_ExW(ClassGuid, szBuffer, &ulLength,
2690                                     ulFlags, hMachine);
2691     if (ret == CR_SUCCESS)
2692     {
2693         if (WideCharToMultiByte(CP_ACP,
2694                                 0,
2695                                 szBuffer,
2696                                 ulLength,
2697                                 pszKeyName,
2698                                 ulOrigLength,
2699                                 NULL,
2700                                 NULL) == 0)
2701             ret = CR_FAILURE;
2702         else
2703             *pulLength = lstrlenA(pszKeyName) + 1;
2704     }
2705 
2706     return CR_SUCCESS;
2707 }
2708 
2709 
2710 /***********************************************************************
2711  * CM_Get_Class_Key_Name_ExW [SETUPAPI.@]
2712  */
2713 CONFIGRET
2714 WINAPI
2715 CM_Get_Class_Key_Name_ExW(
2716     _In_ LPGUID ClassGuid,
2717     _Out_writes_opt_(*pulLength) LPWSTR pszKeyName,
2718     _Inout_ PULONG pulLength,
2719     _In_ ULONG ulFlags,
2720     _In_opt_ HMACHINE hMachine)
2721 {
2722     TRACE("CM_Get_Class_Key_Name_ExW(%p %p %p %lx %p)\n",
2723           ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
2724 
2725     if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
2726         return CR_INVALID_POINTER;
2727 
2728     if (ulFlags != 0)
2729         return CR_INVALID_FLAG;
2730 
2731     if (*pulLength < MAX_GUID_STRING_LEN)
2732     {
2733         *pulLength = 0;
2734         return CR_BUFFER_SMALL;
2735     }
2736 
2737     if (!GuidToString(ClassGuid, pszKeyName))
2738         return CR_INVALID_DATA;
2739 
2740     *pulLength = MAX_GUID_STRING_LEN;
2741 
2742     return CR_SUCCESS;
2743 }
2744 
2745 
2746 /***********************************************************************
2747  * CM_Get_Class_NameA [SETUPAPI.@]
2748  */
2749 CONFIGRET
2750 WINAPI
2751 CM_Get_Class_NameA(
2752     _In_ LPGUID ClassGuid,
2753     _Out_writes_opt_(*pulLength) PCHAR Buffer,
2754     _Inout_ PULONG pulLength,
2755     _In_ ULONG ulFlags)
2756 {
2757     TRACE("CM_Get_Class_NameA(%p %p %p %lx)\n",
2758           ClassGuid, Buffer, pulLength, ulFlags);
2759 
2760     return CM_Get_Class_Name_ExA(ClassGuid, Buffer, pulLength, ulFlags,
2761                                  NULL);
2762 }
2763 
2764 
2765 /***********************************************************************
2766  * CM_Get_Class_NameW [SETUPAPI.@]
2767  */
2768 CONFIGRET
2769 WINAPI
2770 CM_Get_Class_NameW(
2771     _In_ LPGUID ClassGuid,
2772     _Out_writes_opt_(*pulLength) PWCHAR Buffer,
2773     _Inout_ PULONG pulLength,
2774     _In_ ULONG ulFlags)
2775 {
2776     TRACE("CM_Get_Class_NameW(%p %p %p %lx)\n",
2777           ClassGuid, Buffer, pulLength, ulFlags);
2778 
2779     return CM_Get_Class_Name_ExW(ClassGuid, Buffer, pulLength, ulFlags,
2780                                  NULL);
2781 }
2782 
2783 
2784 /***********************************************************************
2785  * CM_Get_Class_Name_ExA [SETUPAPI.@]
2786  */
2787 CONFIGRET
2788 WINAPI
2789 CM_Get_Class_Name_ExA(
2790     _In_ LPGUID ClassGuid,
2791     _Out_writes_opt_(*pulLength) PCHAR Buffer,
2792     _Inout_ PULONG pulLength,
2793     _In_ ULONG ulFlags,
2794     _In_opt_ HMACHINE hMachine)
2795 {
2796     WCHAR szBuffer[MAX_CLASS_NAME_LEN];
2797     CONFIGRET ret = CR_SUCCESS;
2798     ULONG ulLength;
2799     ULONG ulOrigLength;
2800 
2801     TRACE("CM_Get_Class_Name_ExA(%p %p %p %lx %p)\n",
2802           ClassGuid, Buffer, pulLength, ulFlags, hMachine);
2803 
2804     if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
2805         return CR_INVALID_POINTER;
2806 
2807     ulOrigLength = *pulLength;
2808     *pulLength = 0;
2809 
2810     ulLength = MAX_CLASS_NAME_LEN;
2811     ret = CM_Get_Class_Name_ExW(ClassGuid, szBuffer, &ulLength,
2812                                 ulFlags, hMachine);
2813     if (ret == CR_SUCCESS)
2814     {
2815         if (WideCharToMultiByte(CP_ACP,
2816                                 0,
2817                                 szBuffer,
2818                                 ulLength,
2819                                 Buffer,
2820                                 ulOrigLength,
2821                                 NULL,
2822                                 NULL) == 0)
2823             ret = CR_FAILURE;
2824         else
2825             *pulLength = lstrlenA(Buffer) + 1;
2826     }
2827 
2828     return ret;
2829 }
2830 
2831 
2832 /***********************************************************************
2833  * CM_Get_Class_Name_ExW [SETUPAPI.@]
2834  */
2835 CONFIGRET
2836 WINAPI
2837 CM_Get_Class_Name_ExW(
2838     _In_ LPGUID ClassGuid,
2839     _Out_writes_opt_(*pulLength) PWCHAR Buffer,
2840     _Inout_ PULONG pulLength,
2841     _In_ ULONG ulFlags,
2842     _In_opt_ HMACHINE hMachine)
2843 {
2844     WCHAR szGuidString[MAX_GUID_STRING_LEN];
2845     RPC_BINDING_HANDLE BindingHandle = NULL;
2846     CONFIGRET ret;
2847 
2848     TRACE("CM_Get_Class_Name_ExW(%p %p %p %lx %p\n",
2849           ClassGuid, Buffer, pulLength, ulFlags, hMachine);
2850 
2851     if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
2852         return CR_INVALID_POINTER;
2853 
2854     if (ulFlags != 0)
2855         return CR_INVALID_FLAG;
2856 
2857     if (!GuidToString(ClassGuid, szGuidString))
2858         return CR_INVALID_DATA;
2859 
2860     TRACE("Guid %s\n", debugstr_w(szGuidString));
2861 
2862     if (hMachine != NULL)
2863     {
2864         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2865         if (BindingHandle == NULL)
2866             return CR_FAILURE;
2867     }
2868     else
2869     {
2870         if (!PnpGetLocalHandles(&BindingHandle, NULL))
2871             return CR_FAILURE;
2872     }
2873 
2874     RpcTryExcept
2875     {
2876         ret = PNP_GetClassName(BindingHandle,
2877                                szGuidString,
2878                                Buffer,
2879                                pulLength,
2880                                ulFlags);
2881     }
2882     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2883     {
2884         ret = RpcStatusToCmStatus(RpcExceptionCode());
2885     }
2886     RpcEndExcept;
2887 
2888     return ret;
2889 }
2890 
2891 
2892 /***********************************************************************
2893  * CM_Get_Class_Registry_PropertyA [SETUPAPI.@]
2894  */
2895 CONFIGRET
2896 WINAPI
2897 CM_Get_Class_Registry_PropertyA(
2898     LPGUID ClassGuid,
2899     ULONG ulProperty,
2900     PULONG pulRegDataType,
2901     PVOID Buffer,
2902     PULONG pulLength,
2903     ULONG ulFlags,
2904     HMACHINE hMachine)
2905 {
2906     PWSTR BufferW;
2907     ULONG ulLength = 0;
2908     ULONG ulType;
2909     CONFIGRET ret;
2910 
2911     TRACE("CM_Get_Class_Registry_PropertyA(%p %lu %p %p %p %lx %p)\n",
2912           ClassGuid, ulProperty, pulRegDataType, Buffer, pulLength,
2913           ulFlags, hMachine);
2914 
2915     if (pulLength == NULL)
2916         return CR_INVALID_POINTER;
2917 
2918     if (ulProperty < CM_CRP_MIN || ulProperty > CM_CRP_MAX)
2919         return CR_INVALID_PROPERTY;
2920 
2921     ulType = GetRegistryPropertyType(ulProperty);
2922     if (ulType == REG_SZ || ulType == REG_MULTI_SZ)
2923     {
2924         /* Get the required buffer size */
2925         ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2926                                               NULL, &ulLength, ulFlags, hMachine);
2927         if (ret != CR_BUFFER_SMALL)
2928             return ret;
2929 
2930         /* Allocate the unicode buffer */
2931         BufferW = HeapAlloc(GetProcessHeap(), 0, ulLength);
2932         if (BufferW == NULL)
2933             return CR_OUT_OF_MEMORY;
2934 
2935         /* Get the property */
2936         ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2937                                               BufferW, &ulLength, ulFlags, hMachine);
2938         if (ret != CR_SUCCESS)
2939         {
2940             HeapFree(GetProcessHeap(), 0, BufferW);
2941             return ret;
2942         }
2943 
2944         /* Do W->A conversion */
2945         *pulLength = WideCharToMultiByte(CP_ACP,
2946                                          0,
2947                                          BufferW,
2948                                          ulLength,
2949                                          Buffer,
2950                                          *pulLength,
2951                                          NULL,
2952                                          NULL);
2953 
2954         /* Release the unicode buffer */
2955         HeapFree(GetProcessHeap(), 0, BufferW);
2956 
2957         if (*pulLength == 0)
2958             ret = CR_FAILURE;
2959     }
2960     else
2961     {
2962         /* Get the property */
2963         ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2964                                               Buffer, pulLength, ulFlags, hMachine);
2965     }
2966 
2967     return ret;
2968 }
2969 
2970 
2971 /***********************************************************************
2972  * CM_Get_Class_Registry_PropertyW [SETUPAPI.@]
2973  */
2974 CONFIGRET
2975 WINAPI
2976 CM_Get_Class_Registry_PropertyW(
2977     LPGUID ClassGuid,
2978     ULONG ulProperty,
2979     PULONG pulRegDataType,
2980     PVOID Buffer,
2981     PULONG pulLength,
2982     ULONG ulFlags,
2983     HMACHINE hMachine)
2984 {
2985     RPC_BINDING_HANDLE BindingHandle = NULL;
2986     WCHAR szGuidString[PNP_MAX_GUID_STRING_LEN + 1];
2987     ULONG ulType = 0;
2988     ULONG ulTransferLength = 0;
2989     CONFIGRET ret;
2990 
2991     TRACE("CM_Get_Class_Registry_PropertyW(%p %lu %p %p %p %lx %p)\n",
2992           ClassGuid, ulProperty, pulRegDataType, Buffer, pulLength,
2993           ulFlags, hMachine);
2994 
2995     if (ClassGuid == NULL || pulLength == NULL)
2996         return CR_INVALID_POINTER;
2997 
2998     if (ulFlags != 0)
2999         return CR_INVALID_FLAG;
3000 
3001     if (pSetupStringFromGuid(ClassGuid,
3002                              szGuidString,
3003                              PNP_MAX_GUID_STRING_LEN) != 0)
3004         return CR_INVALID_DATA;
3005 
3006     if (ulProperty < CM_CRP_MIN || ulProperty > CM_CRP_MAX)
3007         return CR_INVALID_PROPERTY;
3008 
3009     if (hMachine != NULL)
3010     {
3011         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3012         if (BindingHandle == NULL)
3013             return CR_FAILURE;
3014     }
3015     else
3016     {
3017         if (!PnpGetLocalHandles(&BindingHandle, NULL))
3018             return CR_FAILURE;
3019     }
3020 
3021     ulTransferLength = *pulLength;
3022 
3023     RpcTryExcept
3024     {
3025         ret = PNP_GetClassRegProp(BindingHandle,
3026                                   szGuidString,
3027                                   ulProperty,
3028                                   &ulType,
3029                                   Buffer,
3030                                   &ulTransferLength,
3031                                   pulLength,
3032                                   ulFlags);
3033     }
3034     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3035     {
3036         ret = RpcStatusToCmStatus(RpcExceptionCode());
3037     }
3038     RpcEndExcept;
3039 
3040     if (ret == CR_SUCCESS)
3041     {
3042         if (pulRegDataType != NULL)
3043             *pulRegDataType = ulType;
3044     }
3045 
3046     return ret;
3047 }
3048 
3049 
3050 /***********************************************************************
3051  * CM_Get_Depth [SETUPAPI.@]
3052  */
3053 CONFIGRET
3054 WINAPI
3055 CM_Get_Depth(
3056     _Out_ PULONG pulDepth,
3057     _In_ DEVINST dnDevInst,
3058     _In_ ULONG ulFlags)
3059 {
3060     TRACE("CM_Get_Depth(%p %lx %lx)\n",
3061           pulDepth, dnDevInst, ulFlags);
3062 
3063     return CM_Get_Depth_Ex(pulDepth, dnDevInst, ulFlags, NULL);
3064 }
3065 
3066 
3067 /***********************************************************************
3068  * CM_Get_Depth_Ex [SETUPAPI.@]
3069  */
3070 CONFIGRET
3071 WINAPI
3072 CM_Get_Depth_Ex(
3073     _Out_ PULONG pulDepth,
3074     _In_ DEVINST dnDevInst,
3075     _In_ ULONG ulFlags,
3076     _In_opt_ HMACHINE hMachine)
3077 {
3078     RPC_BINDING_HANDLE BindingHandle = NULL;
3079     HSTRING_TABLE StringTable = NULL;
3080     LPWSTR lpDevInst;
3081     CONFIGRET ret;
3082 
3083     TRACE("CM_Get_Depth_Ex(%p %lx %lx %p)\n",
3084           pulDepth, dnDevInst, ulFlags, hMachine);
3085 
3086     if (pulDepth == NULL)
3087         return CR_INVALID_POINTER;
3088 
3089     if (dnDevInst == 0)
3090         return CR_INVALID_DEVINST;
3091 
3092     if (ulFlags != 0)
3093         return CR_INVALID_FLAG;
3094 
3095     if (hMachine != NULL)
3096     {
3097         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3098         if (BindingHandle == NULL)
3099             return CR_FAILURE;
3100 
3101         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3102         if (StringTable == 0)
3103             return CR_FAILURE;
3104     }
3105     else
3106     {
3107         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3108             return CR_FAILURE;
3109     }
3110 
3111     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3112     if (lpDevInst == NULL)
3113         return CR_INVALID_DEVNODE;
3114 
3115     RpcTryExcept
3116     {
3117         ret = PNP_GetDepth(BindingHandle,
3118                            lpDevInst,
3119                            pulDepth,
3120                            ulFlags);
3121     }
3122     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3123     {
3124         ret = RpcStatusToCmStatus(RpcExceptionCode());
3125     }
3126     RpcEndExcept;
3127 
3128     return ret;
3129 }
3130 
3131 
3132 /***********************************************************************
3133  * CM_Get_DevNode_Custom_PropertyA [SETUPAPI.@]
3134  */
3135 CONFIGRET
3136 WINAPI
3137 CM_Get_DevNode_Custom_PropertyA(
3138     _In_ DEVINST dnDevInst,
3139     _In_ PCSTR pszCustomPropertyName,
3140     _Out_opt_ PULONG pulRegDataType,
3141     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3142     _Inout_ PULONG pulLength,
3143     _In_ ULONG ulFlags)
3144 {
3145     TRACE("CM_Get_DevNode_Custom_PropertyA(%lx %s %p %p %p %lx)\n",
3146           dnDevInst, pszCustomPropertyName, pulRegDataType,
3147           Buffer, pulLength, ulFlags);
3148 
3149     return CM_Get_DevNode_Custom_Property_ExA(dnDevInst, pszCustomPropertyName,
3150                                               pulRegDataType, Buffer,
3151                                               pulLength, ulFlags, NULL);
3152 }
3153 
3154 
3155 /***********************************************************************
3156  * CM_Get_DevNode_Custom_PropertyW [SETUPAPI.@]
3157  */
3158 CONFIGRET
3159 WINAPI
3160 CM_Get_DevNode_Custom_PropertyW(
3161     _In_ DEVINST dnDevInst,
3162     _In_ PCWSTR pszCustomPropertyName,
3163     _Out_opt_ PULONG pulRegDataType,
3164     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3165     _Inout_ PULONG pulLength,
3166     _In_ ULONG ulFlags)
3167 {
3168     TRACE("CM_Get_DevNode_Custom_PropertyW(%lx %s %p %p %p %lx)\n",
3169           dnDevInst, debugstr_w(pszCustomPropertyName), pulRegDataType,
3170           Buffer, pulLength, ulFlags);
3171 
3172     return CM_Get_DevNode_Custom_Property_ExW(dnDevInst, pszCustomPropertyName,
3173                                               pulRegDataType, Buffer,
3174                                               pulLength, ulFlags, NULL);
3175 }
3176 
3177 
3178 /***********************************************************************
3179  * CM_Get_DevNode_Custom_Property_ExA [SETUPAPI.@]
3180  */
3181 CONFIGRET
3182 WINAPI
3183 CM_Get_DevNode_Custom_Property_ExA(
3184     _In_ DEVINST dnDevInst,
3185     _In_ PCSTR pszCustomPropertyName,
3186     _Out_opt_ PULONG pulRegDataType,
3187     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3188     _Inout_ PULONG pulLength,
3189     _In_ ULONG ulFlags,
3190     _In_opt_ HMACHINE hMachine)
3191 {
3192     LPWSTR pszPropertyNameW;
3193     PVOID BufferW;
3194     ULONG ulLengthW;
3195     ULONG ulDataType = REG_NONE;
3196     CONFIGRET ret;
3197 
3198     TRACE("CM_Get_DevNode_Custom_Property_ExA(%lx %s %p %p %p %lx %p)\n",
3199           dnDevInst, pszCustomPropertyName, pulRegDataType,
3200           Buffer, pulLength, ulFlags, hMachine);
3201 
3202     if (!pulLength)
3203         return CR_INVALID_POINTER;
3204 
3205     ulLengthW = *pulLength * sizeof(WCHAR);
3206     BufferW = HeapAlloc(GetProcessHeap(), 0, ulLengthW);
3207     if (!BufferW)
3208         return CR_OUT_OF_MEMORY;
3209 
3210     pszPropertyNameW = pSetupMultiByteToUnicode(pszCustomPropertyName,
3211                                                 CP_ACP);
3212     if (pszPropertyNameW == NULL)
3213     {
3214         HeapFree(GetProcessHeap(), 0, BufferW);
3215         return CR_OUT_OF_MEMORY;
3216     }
3217 
3218     ret = CM_Get_DevNode_Custom_Property_ExW(dnDevInst,
3219                                              pszPropertyNameW,
3220                                              &ulDataType,
3221                                              BufferW,
3222                                              &ulLengthW,
3223                                              ulFlags,
3224                                              hMachine);
3225     if (ret == CR_SUCCESS)
3226     {
3227         if (ulDataType == REG_SZ ||
3228             ulDataType == REG_EXPAND_SZ ||
3229             ulDataType == REG_MULTI_SZ)
3230         {
3231             /* Do W->A conversion */
3232             *pulLength = WideCharToMultiByte(CP_ACP,
3233                                              0,
3234                                              BufferW,
3235                                              lstrlenW(BufferW) + 1,
3236                                              Buffer,
3237                                              *pulLength,
3238                                              NULL,
3239                                              NULL);
3240             if (*pulLength == 0)
3241                 ret = CR_FAILURE;
3242         }
3243         else
3244         {
3245             /* Directly copy the value */
3246             if (ulLengthW <= *pulLength)
3247                 memcpy(Buffer, BufferW, ulLengthW);
3248             else
3249             {
3250                 *pulLength = ulLengthW;
3251                 ret = CR_BUFFER_SMALL;
3252             }
3253         }
3254     }
3255 
3256     if (pulRegDataType)
3257         *pulRegDataType = ulDataType;
3258 
3259     HeapFree(GetProcessHeap(), 0, BufferW);
3260     MyFree(pszPropertyNameW);
3261 
3262     return ret;
3263 }
3264 
3265 
3266 /***********************************************************************
3267  * CM_Get_DevNode_Custom_Property_ExW [SETUPAPI.@]
3268  */
3269 CONFIGRET
3270 WINAPI
3271 CM_Get_DevNode_Custom_Property_ExW(
3272     _In_ DEVINST dnDevInst,
3273     _In_ PCWSTR pszCustomPropertyName,
3274     _Out_opt_ PULONG pulRegDataType,
3275     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3276     _Inout_ PULONG pulLength,
3277     _In_ ULONG ulFlags,
3278     _In_opt_ HMACHINE hMachine)
3279 {
3280     RPC_BINDING_HANDLE BindingHandle = NULL;
3281     HSTRING_TABLE StringTable = NULL;
3282     LPWSTR lpDevInst;
3283     ULONG ulDataType = REG_NONE;
3284     ULONG ulTransferLength;
3285     CONFIGRET ret = CR_SUCCESS;
3286 
3287     TRACE("CM_Get_DevNode_Custom_Property_ExW(%lx %s %p %p %p %lx %p)\n",
3288           dnDevInst, debugstr_w(pszCustomPropertyName), pulRegDataType,
3289           Buffer, pulLength, ulFlags, hMachine);
3290 
3291     if (dnDevInst == 0)
3292         return CR_INVALID_DEVNODE;
3293 
3294     if (pszCustomPropertyName == NULL ||
3295         pulLength == NULL ||
3296         *pulLength == 0)
3297         return CR_INVALID_POINTER;
3298 
3299     if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
3300         return CR_INVALID_FLAG;
3301 
3302     if (hMachine != NULL)
3303     {
3304         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3305         if (BindingHandle == NULL)
3306             return CR_FAILURE;
3307 
3308         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3309         if (StringTable == 0)
3310             return CR_FAILURE;
3311     }
3312     else
3313     {
3314         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3315             return CR_FAILURE;
3316     }
3317 
3318     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3319     if (lpDevInst == NULL)
3320         return CR_INVALID_DEVNODE;
3321 
3322     ulTransferLength = *pulLength;
3323 
3324     RpcTryExcept
3325     {
3326         ret = PNP_GetCustomDevProp(BindingHandle,
3327                                    lpDevInst,
3328                                    (LPWSTR)pszCustomPropertyName,
3329                                    &ulDataType,
3330                                    Buffer,
3331                                    &ulTransferLength,
3332                                    pulLength,
3333                                    ulFlags);
3334     }
3335     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3336     {
3337         ret = RpcStatusToCmStatus(RpcExceptionCode());
3338     }
3339     RpcEndExcept;
3340 
3341     if (ret == CR_SUCCESS)
3342     {
3343         if (pulRegDataType != NULL)
3344             *pulRegDataType = ulDataType;
3345     }
3346 
3347     return ret;
3348 }
3349 
3350 
3351 /***********************************************************************
3352  * CM_Get_DevNode_Registry_PropertyA [SETUPAPI.@]
3353  */
3354 CONFIGRET
3355 WINAPI
3356 CM_Get_DevNode_Registry_PropertyA(
3357     _In_ DEVINST dnDevInst,
3358     _In_ ULONG ulProperty,
3359     _Out_opt_ PULONG pulRegDataType,
3360     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3361     _Inout_ PULONG pulLength,
3362     _In_ ULONG ulFlags)
3363 {
3364     TRACE("CM_Get_DevNode_Registry_PropertyA(%lx %lu %p %p %p %lx)\n",
3365           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
3366 
3367     return CM_Get_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
3368                                                 pulRegDataType, Buffer,
3369                                                 pulLength, ulFlags, NULL);
3370 }
3371 
3372 
3373 /***********************************************************************
3374  * CM_Get_DevNode_Registry_PropertyW [SETUPAPI.@]
3375  */
3376 CONFIGRET
3377 WINAPI
3378 CM_Get_DevNode_Registry_PropertyW(
3379     _In_ DEVINST dnDevInst,
3380     _In_ ULONG ulProperty,
3381     _Out_opt_ PULONG pulRegDataType,
3382     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3383     _Inout_ PULONG pulLength,
3384     _In_ ULONG ulFlags)
3385 {
3386     TRACE("CM_Get_DevNode_Registry_PropertyW(%lx %lu %p %p %p %lx)\n",
3387           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
3388 
3389     return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
3390                                                 pulRegDataType, Buffer,
3391                                                 pulLength, ulFlags, NULL);
3392 }
3393 
3394 
3395 /***********************************************************************
3396  * CM_Get_DevNode_Registry_Property_ExA [SETUPAPI.@]
3397  */
3398 CONFIGRET
3399 WINAPI
3400 CM_Get_DevNode_Registry_Property_ExA(
3401     _In_ DEVINST dnDevInst,
3402     _In_ ULONG ulProperty,
3403     _Out_opt_ PULONG pulRegDataType,
3404     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3405     _Inout_ PULONG pulLength,
3406     _In_ ULONG ulFlags,
3407     _In_opt_ HMACHINE hMachine)
3408 {
3409     PVOID BufferW;
3410     ULONG LengthW;
3411     ULONG ulDataType = REG_NONE;
3412     CONFIGRET ret;
3413 
3414     TRACE("CM_Get_DevNode_Registry_Property_ExA(%lx %lu %p %p %p %lx %p)\n",
3415           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
3416           ulFlags, hMachine);
3417 
3418     if (!pulLength)
3419         return CR_INVALID_POINTER;
3420 
3421     LengthW = *pulLength * sizeof(WCHAR);
3422     BufferW = HeapAlloc(GetProcessHeap(), 0, LengthW);
3423     if (!BufferW)
3424         return CR_OUT_OF_MEMORY;
3425 
3426     ret = CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
3427                                                ulProperty,
3428                                                &ulDataType,
3429                                                BufferW,
3430                                                &LengthW,
3431                                                ulFlags,
3432                                                hMachine);
3433 
3434     if (ret == CR_SUCCESS)
3435     {
3436         if (ulDataType == REG_SZ ||
3437             ulDataType == REG_EXPAND_SZ ||
3438             ulDataType == REG_MULTI_SZ)
3439         {
3440             /* Do W->A conversion */
3441             *pulLength = WideCharToMultiByte(CP_ACP,
3442                                              0,
3443                                              BufferW,
3444                                              lstrlenW(BufferW) + 1,
3445                                              Buffer,
3446                                              *pulLength,
3447                                              NULL,
3448                                              NULL);
3449             if (*pulLength == 0)
3450                 ret = CR_FAILURE;
3451         }
3452         else
3453         {
3454             /* Directly copy the value */
3455             if (LengthW <= *pulLength)
3456                 memcpy(Buffer, BufferW, LengthW);
3457             else
3458             {
3459                 *pulLength = LengthW;
3460                 ret = CR_BUFFER_SMALL;
3461             }
3462         }
3463     }
3464 
3465     if (pulRegDataType)
3466         *pulRegDataType = ulDataType;
3467 
3468     HeapFree(GetProcessHeap(), 0, BufferW);
3469 
3470     return ret;
3471 }
3472 
3473 
3474 /***********************************************************************
3475  * CM_Get_DevNode_Registry_Property_ExW [SETUPAPI.@]
3476  */
3477 CONFIGRET
3478 WINAPI
3479 CM_Get_DevNode_Registry_Property_ExW(
3480     _In_ DEVINST dnDevInst,
3481     _In_ ULONG ulProperty,
3482     _Out_opt_ PULONG pulRegDataType,
3483     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3484     _Inout_ PULONG pulLength,
3485     _In_ ULONG ulFlags,
3486     _In_opt_ HMACHINE hMachine)
3487 {
3488     RPC_BINDING_HANDLE BindingHandle = NULL;
3489     HSTRING_TABLE StringTable = NULL;
3490     CONFIGRET ret = CR_SUCCESS;
3491     LPWSTR lpDevInst;
3492     ULONG ulDataType = REG_NONE;
3493     ULONG ulTransferLength = 0;
3494 
3495     TRACE("CM_Get_DevNode_Registry_Property_ExW(%lx %lu %p %p %p %lx %p)\n",
3496           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
3497           ulFlags, hMachine);
3498 
3499     if (dnDevInst == 0)
3500         return CR_INVALID_DEVNODE;
3501 
3502     if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
3503         return CR_INVALID_PROPERTY;
3504 
3505     /* pulRegDataType is optional */
3506 
3507     /* Buffer is optional */
3508 
3509     if (pulLength == NULL)
3510         return CR_INVALID_POINTER;
3511 
3512     if (*pulLength == 0)
3513         return CR_INVALID_POINTER;
3514 
3515     if (ulFlags != 0)
3516         return CR_INVALID_FLAG;
3517 
3518     if (hMachine != NULL)
3519     {
3520         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3521         if (BindingHandle == NULL)
3522             return CR_FAILURE;
3523 
3524         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3525         if (StringTable == 0)
3526             return CR_FAILURE;
3527     }
3528     else
3529     {
3530         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3531             return CR_FAILURE;
3532     }
3533 
3534     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3535     if (lpDevInst == NULL)
3536         return CR_INVALID_DEVNODE;
3537 
3538     ulTransferLength = *pulLength;
3539 
3540     RpcTryExcept
3541     {
3542         ret = PNP_GetDeviceRegProp(BindingHandle,
3543                                    lpDevInst,
3544                                    ulProperty,
3545                                    &ulDataType,
3546                                    Buffer,
3547                                    &ulTransferLength,
3548                                    pulLength,
3549                                    ulFlags);
3550     }
3551     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3552     {
3553         ret = RpcStatusToCmStatus(RpcExceptionCode());
3554     }
3555     RpcEndExcept;
3556 
3557     if (ret == CR_SUCCESS)
3558     {
3559         if (pulRegDataType != NULL)
3560             *pulRegDataType = ulDataType;
3561     }
3562 
3563     return ret;
3564 }
3565 
3566 
3567 /***********************************************************************
3568  * CM_Get_DevNode_Status [SETUPAPI.@]
3569  */
3570 CONFIGRET
3571 WINAPI
3572 CM_Get_DevNode_Status(
3573     _Out_ PULONG pulStatus,
3574     _Out_ PULONG pulProblemNumber,
3575     _In_ DEVINST dnDevInst,
3576     _In_ ULONG ulFlags)
3577 {
3578     TRACE("CM_Get_DevNode_Status(%p %p %lx %lx)\n",
3579           pulStatus, pulProblemNumber, dnDevInst, ulFlags);
3580 
3581     return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber, dnDevInst,
3582                                     ulFlags, NULL);
3583 }
3584 
3585 
3586 /***********************************************************************
3587  * CM_Get_DevNode_Status_Ex [SETUPAPI.@]
3588  */
3589 CONFIGRET
3590 WINAPI
3591 CM_Get_DevNode_Status_Ex(
3592     _Out_ PULONG pulStatus,
3593     _Out_ PULONG pulProblemNumber,
3594     _In_ DEVINST dnDevInst,
3595     _In_ ULONG ulFlags,
3596     _In_opt_ HMACHINE hMachine)
3597 {
3598     RPC_BINDING_HANDLE BindingHandle = NULL;
3599     HSTRING_TABLE StringTable = NULL;
3600     LPWSTR lpDevInst;
3601     CONFIGRET ret;
3602 
3603     TRACE("CM_Get_DevNode_Status_Ex(%p %p %lx %lx %p)\n",
3604           pulStatus, pulProblemNumber, dnDevInst, ulFlags, hMachine);
3605 
3606     if (pulStatus == NULL || pulProblemNumber == NULL)
3607         return CR_INVALID_POINTER;
3608 
3609     if (dnDevInst == 0)
3610         return CR_INVALID_DEVINST;
3611 
3612     if (ulFlags != 0)
3613         return CR_INVALID_FLAG;
3614 
3615     if (hMachine != NULL)
3616     {
3617         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3618         if (BindingHandle == NULL)
3619             return CR_FAILURE;
3620 
3621         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3622         if (StringTable == 0)
3623             return CR_FAILURE;
3624     }
3625     else
3626     {
3627         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3628             return CR_FAILURE;
3629     }
3630 
3631     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3632     if (lpDevInst == NULL)
3633         return CR_INVALID_DEVNODE;
3634 
3635     RpcTryExcept
3636     {
3637         ret = PNP_GetDeviceStatus(BindingHandle,
3638                                   lpDevInst,
3639                                   pulStatus,
3640                                   pulProblemNumber,
3641                                   ulFlags);
3642     }
3643     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3644     {
3645         ret = RpcStatusToCmStatus(RpcExceptionCode());
3646     }
3647     RpcEndExcept;
3648 
3649     return ret;
3650 }
3651 
3652 
3653 /***********************************************************************
3654  * CM_Get_Device_IDA [SETUPAPI.@]
3655  */
3656 CONFIGRET
3657 WINAPI
3658 CM_Get_Device_IDA(
3659     _In_ DEVINST dnDevInst,
3660     _Out_writes_(BufferLen) PCHAR Buffer,
3661     _In_ ULONG BufferLen,
3662     _In_ ULONG ulFlags)
3663 {
3664     TRACE("CM_Get_Device_IDA(%lx %p %lu %lx)\n",
3665           dnDevInst, Buffer, BufferLen, ulFlags);
3666 
3667     return CM_Get_Device_ID_ExA(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
3668 }
3669 
3670 
3671 /***********************************************************************
3672  * CM_Get_Device_IDW [SETUPAPI.@]
3673  */
3674 CONFIGRET
3675 WINAPI
3676 CM_Get_Device_IDW(
3677     _In_ DEVINST dnDevInst,
3678     _Out_writes_(BufferLen) PWCHAR Buffer,
3679     _In_ ULONG BufferLen,
3680     _In_ ULONG ulFlags)
3681 {
3682     TRACE("CM_Get_Device_IDW(%lx %p %lu %lx)\n",
3683           dnDevInst, Buffer, BufferLen, ulFlags);
3684 
3685     return CM_Get_Device_ID_ExW(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
3686 }
3687 
3688 
3689 /***********************************************************************
3690  * CM_Get_Device_ID_ExA [SETUPAPI.@]
3691  */
3692 CONFIGRET
3693 WINAPI
3694 CM_Get_Device_ID_ExA(
3695     _In_ DEVINST dnDevInst,
3696     _Out_writes_(BufferLen) PCHAR Buffer,
3697     _In_ ULONG BufferLen,
3698     _In_ ULONG ulFlags,
3699     _In_opt_ HMACHINE hMachine)
3700 {
3701     WCHAR szBufferW[MAX_DEVICE_ID_LEN];
3702     CONFIGRET ret = CR_SUCCESS;
3703 
3704     TRACE("CM_Get_Device_ID_ExA(%lx %p %lu %lx %p)\n",
3705           dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
3706 
3707     if (Buffer == NULL)
3708         return CR_INVALID_POINTER;
3709 
3710     ret = CM_Get_Device_ID_ExW(dnDevInst,
3711                                szBufferW,
3712                                MAX_DEVICE_ID_LEN,
3713                                ulFlags,
3714                                hMachine);
3715     if (ret == CR_SUCCESS)
3716     {
3717         if (WideCharToMultiByte(CP_ACP,
3718                                 0,
3719                                 szBufferW,
3720                                 lstrlenW(szBufferW) + 1,
3721                                 Buffer,
3722                                 BufferLen,
3723                                 NULL,
3724                                 NULL) == 0)
3725             ret = CR_FAILURE;
3726     }
3727 
3728     return ret;
3729 }
3730 
3731 
3732 /***********************************************************************
3733  * CM_Get_Device_ID_ExW [SETUPAPI.@]
3734  */
3735 CONFIGRET
3736 WINAPI
3737 CM_Get_Device_ID_ExW(
3738     _In_ DEVINST dnDevInst,
3739     _Out_writes_(BufferLen) PWCHAR Buffer,
3740     _In_ ULONG BufferLen,
3741     _In_ ULONG ulFlags,
3742     _In_opt_ HMACHINE hMachine)
3743 {
3744     HSTRING_TABLE StringTable = NULL;
3745 
3746     TRACE("CM_Get_Device_ID_ExW(%lx %p %lu %lx %p)\n",
3747           dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
3748 
3749     if (dnDevInst == 0)
3750         return CR_INVALID_DEVINST;
3751 
3752     if (Buffer == NULL)
3753         return CR_INVALID_POINTER;
3754 
3755     if (ulFlags != 0)
3756         return CR_INVALID_FLAG;
3757 
3758     if (hMachine != NULL)
3759     {
3760         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3761         if (StringTable == NULL)
3762             return CR_FAILURE;
3763     }
3764     else
3765     {
3766         if (!PnpGetLocalHandles(NULL, &StringTable))
3767             return CR_FAILURE;
3768     }
3769 
3770     if (!pSetupStringTableStringFromIdEx(StringTable,
3771                                          dnDevInst,
3772                                          Buffer,
3773                                          &BufferLen))
3774         return CR_FAILURE;
3775 
3776     return CR_SUCCESS;
3777 }
3778 
3779 
3780 /***********************************************************************
3781  * CM_Get_Device_ID_ListA [SETUPAPI.@]
3782  */
3783 CONFIGRET
3784 WINAPI
3785 CM_Get_Device_ID_ListA(
3786     _In_ PCSTR pszFilter,
3787     _Out_writes_(BufferLen) PCHAR Buffer,
3788     _In_ ULONG BufferLen,
3789     _In_ ULONG ulFlags)
3790 {
3791     TRACE("CM_Get_Device_ID_ListA(%p %p %lu %lx)\n",
3792           pszFilter, Buffer, BufferLen, ulFlags);
3793 
3794     return CM_Get_Device_ID_List_ExA(pszFilter, Buffer, BufferLen,
3795                                      ulFlags, NULL);
3796 }
3797 
3798 
3799 /***********************************************************************
3800  * CM_Get_Device_ID_ListW [SETUPAPI.@]
3801  */
3802 CONFIGRET
3803 WINAPI
3804 CM_Get_Device_ID_ListW(
3805     _In_ PCWSTR pszFilter,
3806     _Out_writes_(BufferLen) PWCHAR Buffer,
3807     _In_ ULONG BufferLen,
3808     _In_ ULONG ulFlags)
3809 {
3810     TRACE("CM_Get_Device_ID_ListW(%p %p %lu %lx)\n",
3811           pszFilter, Buffer, BufferLen, ulFlags);
3812 
3813     return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen,
3814                                      ulFlags, NULL);
3815 }
3816 
3817 
3818 /***********************************************************************
3819  * CM_Get_Device_ID_List_ExA [SETUPAPI.@]
3820  */
3821 CONFIGRET
3822 WINAPI
3823 CM_Get_Device_ID_List_ExA(
3824     _In_ PCSTR pszFilter,
3825     _Out_writes_(BufferLen) PCHAR Buffer,
3826     _In_ ULONG BufferLen,
3827     _In_ ULONG ulFlags,
3828     _In_opt_ HMACHINE hMachine)
3829 {
3830     LPWSTR BufferW = NULL;
3831     LPWSTR pszFilterW = NULL;
3832     CONFIGRET ret = CR_SUCCESS;
3833 
3834     TRACE("CM_Get_Device_ID_List_ExA(%p %p %lu %lx %p)\n",
3835           pszFilter, Buffer, BufferLen, ulFlags, hMachine);
3836 
3837     BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
3838     if (BufferW == NULL)
3839         return CR_OUT_OF_MEMORY;
3840 
3841     if (pszFilter == NULL)
3842     {
3843         ret = CM_Get_Device_ID_List_ExW(NULL,
3844                                         BufferW,
3845                                         BufferLen,
3846                                         ulFlags,
3847                                         hMachine);
3848     }
3849     else
3850     {
3851         if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
3852         {
3853             ret = CR_INVALID_DEVICE_ID;
3854             goto Done;
3855         }
3856 
3857         ret = CM_Get_Device_ID_List_ExW(pszFilterW,
3858                                         BufferW,
3859                                         BufferLen,
3860                                         ulFlags,
3861                                         hMachine);
3862 
3863         MyFree(pszFilterW);
3864     }
3865 
3866     if (WideCharToMultiByte(CP_ACP,
3867                             0,
3868                             BufferW,
3869                             BufferLen,
3870                             Buffer,
3871                             BufferLen,
3872                             NULL,
3873                             NULL) == 0)
3874         ret = CR_FAILURE;
3875 
3876 Done:
3877     MyFree(BufferW);
3878 
3879     return ret;
3880 }
3881 
3882 
3883 /***********************************************************************
3884  * CM_Get_Device_ID_List_ExW [SETUPAPI.@]
3885  */
3886 CONFIGRET
3887 WINAPI
3888 CM_Get_Device_ID_List_ExW(
3889     _In_ PCWSTR pszFilter,
3890     _Out_writes_(BufferLen) PWCHAR Buffer,
3891     _In_ ULONG BufferLen,
3892     _In_ ULONG ulFlags,
3893     _In_opt_ HMACHINE hMachine)
3894 {
3895     RPC_BINDING_HANDLE BindingHandle = NULL;
3896     CONFIGRET ret;
3897 
3898     TRACE("CM_Get_Device_ID_List_ExW(%p %p %lu %lx %p)\n",
3899           pszFilter, Buffer, BufferLen, ulFlags, hMachine);
3900 
3901     if (Buffer == NULL || BufferLen == 0)
3902         return CR_INVALID_POINTER;
3903 
3904     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
3905         return CR_INVALID_FLAG;
3906 
3907     if (hMachine != NULL)
3908     {
3909         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3910         if (BindingHandle == NULL)
3911             return CR_FAILURE;
3912     }
3913     else
3914     {
3915         if (!PnpGetLocalHandles(&BindingHandle, NULL))
3916             return CR_FAILURE;
3917     }
3918 
3919     *Buffer = 0;
3920 
3921     RpcTryExcept
3922     {
3923         ret = PNP_GetDeviceList(BindingHandle,
3924                                 (LPWSTR)pszFilter,
3925                                 Buffer,
3926                                 &BufferLen,
3927                                 ulFlags);
3928     }
3929     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3930     {
3931         ret = RpcStatusToCmStatus(RpcExceptionCode());
3932     }
3933     RpcEndExcept;
3934 
3935     return ret;
3936 }
3937 
3938 
3939 /***********************************************************************
3940  * CM_Get_Device_ID_List_SizeA [SETUPAPI.@]
3941  */
3942 CONFIGRET
3943 WINAPI
3944 CM_Get_Device_ID_List_SizeA(
3945     _Out_ PULONG pulLen,
3946     _In_opt_ PCSTR pszFilter,
3947     _In_ ULONG ulFlags)
3948 {
3949     TRACE("CM_Get_Device_ID_List_SizeA(%p %s %lx)\n",
3950           pulLen, debugstr_a(pszFilter), ulFlags);
3951 
3952     return CM_Get_Device_ID_List_Size_ExA(pulLen, pszFilter, ulFlags, NULL);
3953 }
3954 
3955 
3956 /***********************************************************************
3957  * CM_Get_Device_ID_List_SizeW [SETUPAPI.@]
3958  */
3959 CONFIGRET
3960 WINAPI
3961 CM_Get_Device_ID_List_SizeW(
3962     _Out_ PULONG pulLen,
3963     _In_opt_ PCWSTR pszFilter,
3964     _In_ ULONG ulFlags)
3965 {
3966     TRACE("CM_Get_Device_ID_List_SizeW(%p %s %lx)\n",
3967           pulLen, debugstr_w(pszFilter), ulFlags);
3968 
3969     return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL);
3970 }
3971 
3972 
3973 /***********************************************************************
3974  * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@]
3975  */
3976 CONFIGRET
3977 WINAPI
3978 CM_Get_Device_ID_List_Size_ExA(
3979     _Out_ PULONG pulLen,
3980     _In_opt_ PCSTR pszFilter,
3981     _In_ ULONG ulFlags,
3982     _In_opt_ HMACHINE hMachine)
3983 {
3984     LPWSTR pszFilterW = NULL;
3985     CONFIGRET ret = CR_SUCCESS;
3986 
3987     FIXME("CM_Get_Device_ID_List_Size_ExA(%p %s %lx %p)\n",
3988           pulLen, debugstr_a(pszFilter), ulFlags, hMachine);
3989 
3990     if (pszFilter == NULL)
3991     {
3992         ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
3993                                              NULL,
3994                                              ulFlags,
3995                                              hMachine);
3996     }
3997     else
3998     {
3999         if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
4000             return CR_INVALID_DEVICE_ID;
4001 
4002         ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
4003                                              pszFilterW,
4004                                              ulFlags,
4005                                              hMachine);
4006 
4007         MyFree(pszFilterW);
4008     }
4009 
4010     return ret;
4011 }
4012 
4013 
4014 /***********************************************************************
4015  * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@]
4016  */
4017 CONFIGRET
4018 WINAPI
4019 CM_Get_Device_ID_List_Size_ExW(
4020     _Out_ PULONG pulLen,
4021     _In_opt_ PCWSTR pszFilter,
4022     _In_ ULONG ulFlags,
4023     _In_opt_ HMACHINE hMachine)
4024 {
4025     RPC_BINDING_HANDLE BindingHandle = NULL;
4026     CONFIGRET ret;
4027 
4028     FIXME("CM_Get_Device_ID_List_Size_ExW(%p %s %lx %p)\n",
4029           pulLen, debugstr_w(pszFilter), ulFlags, hMachine);
4030 
4031     if (pulLen == NULL)
4032         return CR_INVALID_POINTER;
4033 
4034     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
4035         return CR_INVALID_FLAG;
4036 
4037     if (hMachine != NULL)
4038     {
4039         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4040         if (BindingHandle == NULL)
4041             return CR_FAILURE;
4042     }
4043     else
4044     {
4045         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4046             return CR_FAILURE;
4047     }
4048 
4049     *pulLen = 0;
4050 
4051     RpcTryExcept
4052     {
4053         ret = PNP_GetDeviceListSize(BindingHandle,
4054                                     (LPWSTR)pszFilter,
4055                                     pulLen,
4056                                     ulFlags);
4057     }
4058     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4059     {
4060         ret = RpcStatusToCmStatus(RpcExceptionCode());
4061     }
4062     RpcEndExcept;
4063 
4064     return ret;
4065 }
4066 
4067 
4068 /***********************************************************************
4069  * CM_Get_Device_ID_Size [SETUPAPI.@]
4070  */
4071 CONFIGRET
4072 WINAPI
4073 CM_Get_Device_ID_Size(
4074     _Out_ PULONG pulLen,
4075     _In_ DEVINST dnDevInst,
4076     _In_ ULONG ulFlags)
4077 {
4078     TRACE("CM_Get_Device_ID_Size(%p %lx %lx)\n",
4079           pulLen, dnDevInst, ulFlags);
4080 
4081     return CM_Get_Device_ID_Size_Ex(pulLen, dnDevInst, ulFlags, NULL);
4082 }
4083 
4084 
4085 /***********************************************************************
4086  * CM_Get_Device_ID_Size_Ex [SETUPAPI.@]
4087  */
4088 CONFIGRET
4089 WINAPI
4090 CM_Get_Device_ID_Size_Ex(
4091     _Out_ PULONG pulLen,
4092     _In_ DEVINST dnDevInst,
4093     _In_ ULONG ulFlags,
4094     _In_opt_ HMACHINE hMachine)
4095 {
4096     HSTRING_TABLE StringTable = NULL;
4097     LPWSTR DeviceId;
4098 
4099     TRACE("CM_Get_Device_ID_Size_Ex(%p %lx %lx %p)\n",
4100           pulLen, dnDevInst, ulFlags, hMachine);
4101 
4102     if (pulLen == NULL)
4103         return CR_INVALID_POINTER;
4104 
4105     if (dnDevInst == 0)
4106         return CR_INVALID_DEVINST;
4107 
4108     if (ulFlags != 0)
4109         return CR_INVALID_FLAG;
4110 
4111     if (hMachine != NULL)
4112     {
4113         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
4114         if (StringTable == NULL)
4115             return CR_FAILURE;
4116     }
4117     else
4118     {
4119         if (!PnpGetLocalHandles(NULL, &StringTable))
4120             return CR_FAILURE;
4121     }
4122 
4123     DeviceId = pSetupStringTableStringFromId(StringTable, dnDevInst);
4124     if (DeviceId == NULL)
4125     {
4126         *pulLen = 0;
4127         return CR_SUCCESS;
4128     }
4129 
4130     *pulLen = lstrlenW(DeviceId);
4131 
4132     return CR_SUCCESS;
4133 }
4134 
4135 
4136 /***********************************************************************
4137  * CM_Get_Device_Interface_AliasA [SETUPAPI.@]
4138  */
4139 CONFIGRET
4140 WINAPI
4141 CM_Get_Device_Interface_AliasA(
4142     _In_ LPCSTR pszDeviceInterface,
4143     _In_ LPGUID AliasInterfaceGuid,
4144     _Out_writes_(*pulLength) LPSTR pszAliasDeviceInterface,
4145     _Inout_ PULONG pulLength,
4146     _In_ ULONG ulFlags)
4147 {
4148     TRACE("CM_Get_Device_Interface_AliasA(%p %p %p %p %lx)\n",
4149           pszDeviceInterface, AliasInterfaceGuid,
4150           pszAliasDeviceInterface, pulLength, ulFlags);
4151 
4152     return CM_Get_Device_Interface_Alias_ExA(pszDeviceInterface,
4153         AliasInterfaceGuid, pszAliasDeviceInterface, pulLength,
4154         ulFlags, NULL);
4155 }
4156 
4157 
4158 /***********************************************************************
4159  * CM_Get_Device_Interface_AliasW [SETUPAPI.@]
4160  */
4161 CONFIGRET
4162 WINAPI
4163 CM_Get_Device_Interface_AliasW(
4164     _In_ LPCWSTR pszDeviceInterface,
4165     _In_ LPGUID AliasInterfaceGuid,
4166     _Out_writes_(*pulLength) LPWSTR pszAliasDeviceInterface,
4167     _Inout_ PULONG pulLength,
4168     _In_ ULONG ulFlags)
4169 {
4170     TRACE("CM_Get_Device_Interface_AliasW(%p %p %p %p %lx)\n",
4171           pszDeviceInterface, AliasInterfaceGuid,
4172           pszAliasDeviceInterface, pulLength, ulFlags);
4173 
4174     return CM_Get_Device_Interface_Alias_ExW(pszDeviceInterface,
4175         AliasInterfaceGuid, pszAliasDeviceInterface, pulLength,
4176         ulFlags, NULL);
4177 }
4178 
4179 
4180 /***********************************************************************
4181  * CM_Get_Device_Interface_Alias_ExA [SETUPAPI.@]
4182  */
4183 CONFIGRET
4184 WINAPI
4185 CM_Get_Device_Interface_Alias_ExA(
4186     _In_ LPCSTR pszDeviceInterface,
4187     _In_ LPGUID AliasInterfaceGuid,
4188     _Out_writes_(*pulLength) LPSTR pszAliasDeviceInterface,
4189     _Inout_ PULONG pulLength,
4190     _In_ ULONG ulFlags,
4191     _In_opt_ HMACHINE hMachine)
4192 {
4193     FIXME("CM_Get_Device_Interface_Alias_ExA(%p %p %p %p %lx %p)\n",
4194           pszDeviceInterface, AliasInterfaceGuid,
4195           pszAliasDeviceInterface, pulLength, ulFlags, hMachine);
4196 
4197     return CR_CALL_NOT_IMPLEMENTED;
4198 }
4199 
4200 
4201 /***********************************************************************
4202  * CM_Get_Device_Interface_Alias_ExW [SETUPAPI.@]
4203  */
4204 CONFIGRET
4205 WINAPI
4206 CM_Get_Device_Interface_Alias_ExW(
4207     _In_ LPCWSTR pszDeviceInterface,
4208     _In_ LPGUID AliasInterfaceGuid,
4209     _Out_writes_(*pulLength) LPWSTR pszAliasDeviceInterface,
4210     _Inout_ PULONG pulLength,
4211     _In_ ULONG ulFlags,
4212     _In_opt_ HMACHINE hMachine)
4213 {
4214     RPC_BINDING_HANDLE BindingHandle = NULL;
4215     ULONG ulTransferLength;
4216     CONFIGRET ret = CR_SUCCESS;
4217 
4218     TRACE("CM_Get_Device_Interface_Alias_ExW(%p %p %p %p %lx %p)\n",
4219           pszDeviceInterface, AliasInterfaceGuid,
4220           pszAliasDeviceInterface, pulLength, ulFlags, hMachine);
4221 
4222     if (pszDeviceInterface == NULL ||
4223         AliasInterfaceGuid == NULL ||
4224         pszAliasDeviceInterface == NULL ||
4225         pulLength == NULL)
4226         return CR_INVALID_POINTER;
4227 
4228     if (ulFlags != 0)
4229         return CR_INVALID_FLAG;
4230 
4231     if (hMachine != NULL)
4232     {
4233         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4234         if (BindingHandle == NULL)
4235             return CR_FAILURE;
4236     }
4237     else
4238     {
4239         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4240             return CR_FAILURE;
4241     }
4242 
4243     ulTransferLength = *pulLength;
4244 
4245     RpcTryExcept
4246     {
4247         ret = PNP_GetInterfaceDeviceAlias(BindingHandle,
4248                                           (LPWSTR)pszDeviceInterface,
4249                                           AliasInterfaceGuid,
4250                                           pszAliasDeviceInterface,
4251                                           pulLength,
4252                                           &ulTransferLength,
4253                                           0);
4254     }
4255     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4256     {
4257         ret = RpcStatusToCmStatus(RpcExceptionCode());
4258     }
4259     RpcEndExcept;
4260 
4261     return ret;
4262 }
4263 
4264 
4265 /***********************************************************************
4266  *      CM_Get_Device_Interface_ListA (SETUPAPI.@)
4267  */
4268 CONFIGRET
4269 WINAPI
4270 CM_Get_Device_Interface_ListA(
4271     _In_ LPGUID InterfaceClassGuid,
4272     _In_opt_ DEVINSTID_A pDeviceID,
4273     _Out_writes_(BufferLen) PCHAR Buffer,
4274     _In_ ULONG BufferLen,
4275     _In_ ULONG ulFlags)
4276 {
4277     TRACE("CM_Get_Device_Interface_ListA(%s %s %p %lu 0x%08lx)\n",
4278           debugstr_guid(InterfaceClassGuid), debugstr_a(pDeviceID),
4279           Buffer, BufferLen, ulFlags);
4280 
4281     return CM_Get_Device_Interface_List_ExA(InterfaceClassGuid, pDeviceID,
4282                                             Buffer, BufferLen, ulFlags, NULL);
4283 }
4284 
4285 
4286 /***********************************************************************
4287  *      CM_Get_Device_Interface_ListW (SETUPAPI.@)
4288  */
4289 CONFIGRET
4290 WINAPI
4291 CM_Get_Device_Interface_ListW(
4292     _In_ LPGUID InterfaceClassGuid,
4293     _In_opt_ DEVINSTID_W pDeviceID,
4294     _Out_writes_(BufferLen) PWCHAR Buffer,
4295     _In_ ULONG BufferLen,
4296     _In_ ULONG ulFlags)
4297 {
4298     TRACE("CM_Get_Device_Interface_ListW(%s %s %p %lu 0x%08lx)\n",
4299           debugstr_guid(InterfaceClassGuid), debugstr_w(pDeviceID),
4300           Buffer, BufferLen, ulFlags);
4301 
4302     return CM_Get_Device_Interface_List_ExW(InterfaceClassGuid, pDeviceID,
4303                                             Buffer, BufferLen, ulFlags, NULL);
4304 }
4305 
4306 
4307 /***********************************************************************
4308  *      CM_Get_Device_Interface_List_ExA (SETUPAPI.@)
4309  */
4310 CONFIGRET
4311 WINAPI
4312 CM_Get_Device_Interface_List_ExA(
4313     _In_ LPGUID InterfaceClassGuid,
4314     _In_opt_ DEVINSTID_A pDeviceID,
4315     _Out_writes_(BufferLen) PCHAR Buffer,
4316     _In_ ULONG BufferLen,
4317     _In_ ULONG ulFlags,
4318     _In_opt_ HMACHINE hMachine)
4319 {
4320     DEVINSTID_W pDeviceIdW = NULL;
4321     PWCHAR BufferW = NULL;
4322     CONFIGRET ret = CR_SUCCESS;
4323 
4324     TRACE("CM_Get_Device_Interface_List_ExA(%s %s %p %lu 0x%08lx %p)\n",
4325           debugstr_guid(InterfaceClassGuid), debugstr_a(pDeviceID),
4326           Buffer, BufferLen, ulFlags, hMachine);
4327 
4328     if (Buffer == NULL ||
4329         BufferLen == 0)
4330         return CR_INVALID_POINTER;
4331 
4332     if (pDeviceID != NULL)
4333     {
4334         if (!pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIdW))
4335             return CR_INVALID_DEVICE_ID;
4336     }
4337 
4338     BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
4339     if (BufferW == NULL)
4340     {
4341         ret = CR_OUT_OF_MEMORY;
4342         goto Done;
4343     }
4344 
4345     ret = CM_Get_Device_Interface_List_ExW(InterfaceClassGuid, pDeviceIdW,
4346                                            BufferW, BufferLen, ulFlags,
4347                                            hMachine);
4348     if (ret != CR_SUCCESS)
4349         goto Done;
4350 
4351     if (WideCharToMultiByte(CP_ACP,
4352                             0,
4353                             BufferW,
4354                             BufferLen,
4355                             Buffer,
4356                             BufferLen,
4357                             NULL,
4358                             NULL) == 0)
4359         ret = CR_FAILURE;
4360 
4361 Done:
4362     if (BufferW != NULL)
4363         MyFree(BufferW);
4364 
4365     if (pDeviceIdW != NULL)
4366         MyFree(pDeviceIdW);
4367 
4368     return ret;
4369 }
4370 
4371 
4372 /***********************************************************************
4373  *      CM_Get_Device_Interface_List_ExW (SETUPAPI.@)
4374  */
4375 CONFIGRET
4376 WINAPI
4377 CM_Get_Device_Interface_List_ExW(
4378     _In_ LPGUID InterfaceClassGuid,
4379     _In_opt_ DEVINSTID_W pDeviceID,
4380     _Out_writes_(BufferLen) PWCHAR Buffer,
4381     _In_ ULONG BufferLen,
4382     _In_ ULONG ulFlags,
4383     _In_opt_ HMACHINE hMachine)
4384 {
4385     RPC_BINDING_HANDLE BindingHandle = NULL;
4386     PNP_RPC_BUFFER_SIZE BufferSize = 0;
4387     CONFIGRET ret = CR_SUCCESS;
4388 
4389     TRACE("CM_Get_Device_Interface_List_ExW(%s %s %p %lu 0x%08lx %p)\n",
4390           debugstr_guid(InterfaceClassGuid), debugstr_w(pDeviceID),
4391           Buffer, BufferLen, ulFlags, hMachine);
4392 
4393     if (Buffer == NULL ||
4394         BufferLen == 0)
4395         return CR_INVALID_POINTER;
4396 
4397     if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
4398         return CR_INVALID_FLAG;
4399 
4400     if (hMachine != NULL)
4401     {
4402         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4403         if (BindingHandle == NULL)
4404             return CR_FAILURE;
4405     }
4406     else
4407     {
4408         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4409             return CR_FAILURE;
4410     }
4411 
4412     *Buffer = 0;
4413     BufferSize = BufferLen;
4414 
4415     RpcTryExcept
4416     {
4417         ret = PNP_GetInterfaceDeviceList(BindingHandle,
4418                                          InterfaceClassGuid,
4419                                          pDeviceID,
4420                                          (LPBYTE)Buffer,
4421                                          &BufferSize,
4422                                          ulFlags);
4423     }
4424     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4425     {
4426         ret = RpcStatusToCmStatus(RpcExceptionCode());
4427     }
4428     RpcEndExcept;
4429 
4430     return ret;
4431 }
4432 
4433 
4434 /***********************************************************************
4435  *      CM_Get_Device_Interface_List_SizeA (SETUPAPI.@)
4436  */
4437 CONFIGRET
4438 WINAPI
4439 CM_Get_Device_Interface_List_SizeA(
4440     _Out_ PULONG pulLen,
4441     _In_ LPGUID InterfaceClassGuid,
4442     _In_opt_ DEVINSTID_A pDeviceID,
4443     _In_ ULONG ulFlags)
4444 {
4445     TRACE("CM_Get_Device_Interface_List_SizeA(%p %p %s 0x%08lx)\n",
4446           pulLen, InterfaceClassGuid, debugstr_a(pDeviceID), ulFlags);
4447 
4448     return CM_Get_Device_Interface_List_Size_ExA(pulLen, InterfaceClassGuid,
4449                                                  pDeviceID, ulFlags, NULL);
4450 }
4451 
4452 
4453 /***********************************************************************
4454  *      CM_Get_Device_Interface_List_SizeW (SETUPAPI.@)
4455  */
4456 CONFIGRET
4457 WINAPI
4458 CM_Get_Device_Interface_List_SizeW(
4459     _Out_ PULONG pulLen,
4460     _In_ LPGUID InterfaceClassGuid,
4461     _In_opt_ DEVINSTID_W pDeviceID,
4462     _In_ ULONG ulFlags)
4463 {
4464     TRACE("CM_Get_Device_Interface_List_SizeW(%p %p %s 0x%08lx)\n",
4465           pulLen, InterfaceClassGuid, debugstr_w(pDeviceID), ulFlags);
4466 
4467     return CM_Get_Device_Interface_List_Size_ExW(pulLen, InterfaceClassGuid,
4468                                                  pDeviceID, ulFlags, NULL);
4469 }
4470 
4471 
4472 /***********************************************************************
4473  *      CM_Get_Device_Interface_List_Size_ExA (SETUPAPI.@)
4474  */
4475 CONFIGRET
4476 WINAPI
4477 CM_Get_Device_Interface_List_Size_ExA(
4478     _Out_ PULONG pulLen,
4479     _In_ LPGUID InterfaceClassGuid,
4480     _In_opt_ DEVINSTID_A pDeviceID,
4481     _In_ ULONG ulFlags,
4482     _In_opt_ HMACHINE hMachine)
4483 {
4484     DEVINSTID_W pDeviceIdW = NULL;
4485     CONFIGRET ret = CR_SUCCESS;
4486 
4487     TRACE("CM_Get_Device_Interface_List_Size_ExA(%p %p %s 0x%08lx %p)\n",
4488           pulLen, InterfaceClassGuid, debugstr_a(pDeviceID), ulFlags, hMachine);
4489 
4490     if (pulLen == NULL)
4491         return CR_INVALID_POINTER;
4492 
4493     if (pDeviceID != NULL)
4494     {
4495         if (!pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIdW))
4496             return CR_INVALID_DEVICE_ID;
4497     }
4498 
4499     *pulLen = 0;
4500 
4501     ret = CM_Get_Device_Interface_List_Size_ExW(pulLen, InterfaceClassGuid,
4502                                                 pDeviceIdW, ulFlags, hMachine);
4503 
4504     if (pDeviceIdW != NULL)
4505         MyFree(pDeviceIdW);
4506 
4507     return ret;
4508 }
4509 
4510 
4511 /***********************************************************************
4512  *      CM_Get_Device_Interface_List_Size_ExW (SETUPAPI.@)
4513  */
4514 CONFIGRET
4515 WINAPI
4516 CM_Get_Device_Interface_List_Size_ExW(
4517     _Out_ PULONG pulLen,
4518     _In_ LPGUID InterfaceClassGuid,
4519     _In_opt_ DEVINSTID_W pDeviceID,
4520     _In_ ULONG ulFlags,
4521     _In_opt_ HMACHINE hMachine)
4522 {
4523     RPC_BINDING_HANDLE BindingHandle = NULL;
4524     CONFIGRET ret = CR_SUCCESS;
4525 
4526     TRACE("CM_Get_Device_Interface_List_Size_ExW(%p %p %s 0x%08lx %p)\n",
4527           pulLen, InterfaceClassGuid, debugstr_w(pDeviceID), ulFlags, hMachine);
4528 
4529     if (pulLen == NULL)
4530         return CR_INVALID_POINTER;
4531 
4532     if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
4533         return CR_INVALID_FLAG;
4534 
4535     if (hMachine != NULL)
4536     {
4537         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4538         if (BindingHandle == NULL)
4539             return CR_FAILURE;
4540     }
4541     else
4542     {
4543         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4544             return CR_FAILURE;
4545     }
4546 
4547     *pulLen = 0;
4548 
4549     RpcTryExcept
4550     {
4551         ret = PNP_GetInterfaceDeviceListSize(BindingHandle,
4552                                              pulLen,
4553                                              InterfaceClassGuid,
4554                                              pDeviceID,
4555                                              ulFlags);
4556     }
4557     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4558     {
4559         ret = RpcStatusToCmStatus(RpcExceptionCode());
4560     }
4561     RpcEndExcept;
4562 
4563     return ret;
4564 }
4565 
4566 
4567 /***********************************************************************
4568  * CM_Get_First_Log_Conf [SETUPAPI.@]
4569  */
4570 CONFIGRET
4571 WINAPI
4572 CM_Get_First_Log_Conf(
4573     _Out_opt_ PLOG_CONF plcLogConf,
4574     _In_ DEVINST dnDevInst,
4575     _In_ ULONG ulFlags)
4576 {
4577     TRACE("CM_Get_First_Log_Conf(%p %lx %lx)\n",
4578           plcLogConf, dnDevInst, ulFlags);
4579 
4580     return CM_Get_First_Log_Conf_Ex(plcLogConf, dnDevInst, ulFlags, NULL);
4581 }
4582 
4583 
4584 /***********************************************************************
4585  * CM_Get_First_Log_Conf_Ex [SETUPAPI.@]
4586  */
4587 CONFIGRET
4588 WINAPI
4589 CM_Get_First_Log_Conf_Ex(
4590     _Out_opt_ PLOG_CONF plcLogConf,
4591     _In_ DEVINST dnDevInst,
4592     _In_ ULONG ulFlags,
4593     _In_opt_ HMACHINE hMachine)
4594 {
4595     RPC_BINDING_HANDLE BindingHandle = NULL;
4596     HSTRING_TABLE StringTable = NULL;
4597     LPWSTR lpDevInst = NULL;
4598     CONFIGRET ret = CR_SUCCESS;
4599     ULONG ulTag;
4600     PLOG_CONF_INFO pLogConfInfo;
4601 
4602     FIXME("CM_Get_First_Log_Conf_Ex(%p %lx %lx %p)\n",
4603           plcLogConf, dnDevInst, ulFlags, hMachine);
4604 
4605     if (dnDevInst == 0)
4606         return CR_INVALID_DEVINST;
4607 
4608     if (ulFlags & ~LOG_CONF_BITS)
4609         return CR_INVALID_FLAG;
4610 
4611     if (plcLogConf)
4612         *plcLogConf = 0;
4613 
4614     if (hMachine != NULL)
4615     {
4616         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4617         if (BindingHandle == NULL)
4618             return CR_FAILURE;
4619 
4620         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
4621         if (StringTable == 0)
4622             return CR_FAILURE;
4623     }
4624     else
4625     {
4626         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
4627             return CR_FAILURE;
4628     }
4629 
4630     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
4631     if (lpDevInst == NULL)
4632         return CR_INVALID_DEVNODE;
4633 
4634     RpcTryExcept
4635     {
4636         ret = PNP_GetFirstLogConf(BindingHandle,
4637                                   lpDevInst,
4638                                   ulFlags,
4639                                   &ulTag,
4640                                   ulFlags);
4641     }
4642     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4643     {
4644         ret = RpcStatusToCmStatus(RpcExceptionCode());
4645     }
4646     RpcEndExcept;
4647 
4648     if (ret != CR_SUCCESS)
4649         return ret;
4650 
4651     if (plcLogConf)
4652     {
4653         pLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
4654         if (pLogConfInfo == NULL)
4655             return CR_OUT_OF_MEMORY;
4656 
4657         pLogConfInfo->ulMagic = LOG_CONF_MAGIC;
4658         pLogConfInfo->dnDevInst = dnDevInst;
4659         pLogConfInfo->ulType = ulFlags;
4660         pLogConfInfo->ulTag = ulTag;
4661 
4662         *plcLogConf = (LOG_CONF)pLogConfInfo;
4663     }
4664 
4665     return CR_SUCCESS;
4666 }
4667 
4668 
4669 /***********************************************************************
4670  * CM_Get_Global_State [SETUPAPI.@]
4671  */
4672 CONFIGRET
4673 WINAPI
4674 CM_Get_Global_State(
4675     _Out_ PULONG pulState,
4676     _In_ ULONG ulFlags)
4677 {
4678     TRACE("CM_Get_Global_State(%p %lx)\n",
4679           pulState, ulFlags);
4680 
4681     return CM_Get_Global_State_Ex(pulState, ulFlags, NULL);
4682 }
4683 
4684 
4685 /***********************************************************************
4686  * CM_Get_Global_State_Ex [SETUPAPI.@]
4687  */
4688 CONFIGRET
4689 WINAPI
4690 CM_Get_Global_State_Ex(
4691     _Out_ PULONG pulState,
4692     _In_ ULONG ulFlags,
4693     _In_opt_ HMACHINE hMachine)
4694 {
4695     RPC_BINDING_HANDLE BindingHandle = NULL;
4696     CONFIGRET ret;
4697 
4698     TRACE("CM_Get_Global_State_Ex(%p %lx %p)\n",
4699           pulState, ulFlags, hMachine);
4700 
4701     if (pulState == NULL)
4702         return CR_INVALID_POINTER;
4703 
4704     if (ulFlags != 0)
4705         return CR_INVALID_FLAG;
4706 
4707     if (hMachine != NULL)
4708     {
4709         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4710         if (BindingHandle == NULL)
4711             return CR_FAILURE;
4712     }
4713     else
4714     {
4715         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4716             return CR_FAILURE;
4717     }
4718 
4719     RpcTryExcept
4720     {
4721         ret = PNP_GetGlobalState(BindingHandle, pulState, ulFlags);
4722     }
4723     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4724     {
4725         ret = RpcStatusToCmStatus(RpcExceptionCode());
4726     }
4727     RpcEndExcept;
4728 
4729     return ret;
4730 }
4731 
4732 
4733 /***********************************************************************
4734  * CM_Get_HW_Prof_FlagsA [SETUPAPI.@]
4735  */
4736 CONFIGRET
4737 WINAPI
4738 CM_Get_HW_Prof_FlagsA(
4739     _In_ DEVINSTID_A szDevInstName,
4740     _In_ ULONG ulHardwareProfile,
4741     _Out_ PULONG pulValue,
4742     _In_ ULONG ulFlags)
4743 {
4744     TRACE("CM_Get_HW_Prof_FlagsA(%s %lu %p %lx)\n",
4745           debugstr_a(szDevInstName), ulHardwareProfile, pulValue, ulFlags);
4746 
4747     return CM_Get_HW_Prof_Flags_ExA(szDevInstName, ulHardwareProfile,
4748                                     pulValue, ulFlags, NULL);
4749 }
4750 
4751 
4752 /***********************************************************************
4753  * CM_Get_HW_Prof_FlagsW [SETUPAPI.@]
4754  */
4755 CONFIGRET
4756 WINAPI
4757 CM_Get_HW_Prof_FlagsW(
4758     _In_ DEVINSTID_W szDevInstName,
4759     _In_ ULONG ulHardwareProfile,
4760     _Out_ PULONG pulValue,
4761     _In_ ULONG ulFlags)
4762 {
4763     TRACE("CM_Get_HW_Prof_FlagsW(%s %lu %p %lx)\n",
4764           debugstr_w(szDevInstName), ulHardwareProfile, pulValue, ulFlags);
4765 
4766     return CM_Get_HW_Prof_Flags_ExW(szDevInstName, ulHardwareProfile,
4767                                     pulValue, ulFlags, NULL);
4768 }
4769 
4770 
4771 /***********************************************************************
4772  * CM_Get_HW_Prof_Flags_ExA [SETUPAPI.@]
4773  */
4774 CONFIGRET
4775 WINAPI
4776 CM_Get_HW_Prof_Flags_ExA(
4777     _In_ DEVINSTID_A szDevInstName,
4778     _In_ ULONG ulHardwareProfile,
4779     _Out_ PULONG pulValue,
4780     _In_ ULONG ulFlags,
4781     _In_opt_ HMACHINE hMachine)
4782 {
4783     DEVINSTID_W pszDevIdW = NULL;
4784     CONFIGRET ret = CR_SUCCESS;
4785 
4786     TRACE("CM_Get_HW_Prof_Flags_ExA(%s %lu %p %lx %p)\n",
4787           debugstr_a(szDevInstName), ulHardwareProfile, pulValue, ulFlags, hMachine);
4788 
4789     if (szDevInstName != NULL)
4790     {
4791        if (pSetupCaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
4792          return CR_INVALID_DEVICE_ID;
4793     }
4794 
4795     ret = CM_Get_HW_Prof_Flags_ExW(pszDevIdW, ulHardwareProfile,
4796                                    pulValue, ulFlags, hMachine);
4797 
4798     if (pszDevIdW != NULL)
4799         MyFree(pszDevIdW);
4800 
4801     return ret;
4802 }
4803 
4804 
4805 /***********************************************************************
4806  * CM_Get_HW_Prof_Flags_ExW [SETUPAPI.@]
4807  */
4808 CONFIGRET
4809 WINAPI
4810 CM_Get_HW_Prof_Flags_ExW(
4811     _In_ DEVINSTID_W szDevInstName,
4812     _In_ ULONG ulHardwareProfile,
4813     _Out_ PULONG pulValue,
4814     _In_ ULONG ulFlags,
4815     _In_opt_ HMACHINE hMachine)
4816 {
4817     RPC_BINDING_HANDLE BindingHandle = NULL;
4818     CONFIGRET ret;
4819 
4820     FIXME("CM_Get_HW_Prof_Flags_ExW(%s %lu %p %lx %p)\n",
4821           debugstr_w(szDevInstName), ulHardwareProfile, pulValue, ulFlags, hMachine);
4822 
4823     if ((szDevInstName == NULL) || (pulValue == NULL))
4824         return CR_INVALID_POINTER;
4825 
4826     if (ulFlags != 0)
4827         return CR_INVALID_FLAG;
4828 
4829     /* FIXME: Check whether szDevInstName is valid */
4830 
4831     if (hMachine != NULL)
4832     {
4833         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4834         if (BindingHandle == NULL)
4835             return CR_FAILURE;
4836     }
4837     else
4838     {
4839         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4840             return CR_FAILURE;
4841     }
4842 
4843     RpcTryExcept
4844     {
4845         ret = PNP_HwProfFlags(BindingHandle, PNP_GET_HWPROFFLAGS, szDevInstName,
4846                               ulHardwareProfile, pulValue, NULL, NULL, 0, 0);
4847     }
4848     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4849     {
4850         ret = RpcStatusToCmStatus(RpcExceptionCode());
4851     }
4852     RpcEndExcept;
4853 
4854     return ret;
4855 }
4856 
4857 
4858 /***********************************************************************
4859  * CM_Get_Hardware_Profile_InfoA [SETUPAPI.@]
4860  */
4861 CONFIGRET
4862 WINAPI
4863 CM_Get_Hardware_Profile_InfoA(
4864     _In_ ULONG ulIndex,
4865     _Out_ PHWPROFILEINFO_A pHWProfileInfo,
4866     _In_ ULONG ulFlags)
4867 {
4868     TRACE("CM_Get_Hardware_Profile_InfoA(%lu %p %lx)\n",
4869           ulIndex, pHWProfileInfo, ulFlags);
4870 
4871     return CM_Get_Hardware_Profile_Info_ExA(ulIndex, pHWProfileInfo,
4872                                             ulFlags, NULL);
4873 }
4874 
4875 
4876 /***********************************************************************
4877  * CM_Get_Hardware_Profile_InfoW [SETUPAPI.@]
4878  */
4879 CONFIGRET
4880 WINAPI
4881 CM_Get_Hardware_Profile_InfoW(
4882     _In_ ULONG ulIndex,
4883     _Out_ PHWPROFILEINFO_W pHWProfileInfo,
4884     _In_ ULONG ulFlags)
4885 {
4886     TRACE("CM_Get_Hardware_Profile_InfoW(%lu %p %lx)\n",
4887           ulIndex, pHWProfileInfo, ulFlags);
4888 
4889     return CM_Get_Hardware_Profile_Info_ExW(ulIndex, pHWProfileInfo,
4890                                             ulFlags, NULL);
4891 }
4892 
4893 
4894 /***********************************************************************
4895  * CM_Get_Hardware_Profile_Info_ExA [SETUPAPI.@]
4896  */
4897 CONFIGRET
4898 WINAPI
4899 CM_Get_Hardware_Profile_Info_ExA(
4900     _In_ ULONG ulIndex,
4901     _Out_ PHWPROFILEINFO_A pHWProfileInfo,
4902     _In_ ULONG ulFlags,
4903     _In_opt_ HMACHINE hMachine)
4904 {
4905     HWPROFILEINFO_W LocalProfileInfo;
4906     CONFIGRET ret;
4907 
4908     TRACE("CM_Get_Hardware_Profile_Info_ExA(%lu %p %lx %p)\n",
4909           ulIndex, pHWProfileInfo, ulFlags, hMachine);
4910 
4911     if (pHWProfileInfo == NULL)
4912         return CR_INVALID_POINTER;
4913 
4914     ret = CM_Get_Hardware_Profile_Info_ExW(ulIndex, &LocalProfileInfo,
4915                                            ulFlags, hMachine);
4916     if (ret == CR_SUCCESS)
4917     {
4918         pHWProfileInfo->HWPI_ulHWProfile = LocalProfileInfo.HWPI_ulHWProfile;
4919         pHWProfileInfo->HWPI_dwFlags = LocalProfileInfo.HWPI_dwFlags;
4920 
4921         if (WideCharToMultiByte(CP_ACP,
4922                                 0,
4923                                 LocalProfileInfo.HWPI_szFriendlyName,
4924                                 lstrlenW(LocalProfileInfo.HWPI_szFriendlyName) + 1,
4925                                 pHWProfileInfo->HWPI_szFriendlyName,
4926                                 MAX_PROFILE_LEN,
4927                                 NULL,
4928                                 NULL) == 0)
4929             ret = CR_FAILURE;
4930     }
4931 
4932     return ret;
4933 }
4934 
4935 
4936 /***********************************************************************
4937  * CM_Get_Hardware_Profile_Info_ExW [SETUPAPI.@]
4938  */
4939 CONFIGRET
4940 WINAPI
4941 CM_Get_Hardware_Profile_Info_ExW(
4942     _In_ ULONG ulIndex,
4943     _Out_ PHWPROFILEINFO_W pHWProfileInfo,
4944     _In_ ULONG ulFlags,
4945     _In_opt_ HMACHINE hMachine)
4946 {
4947     RPC_BINDING_HANDLE BindingHandle = NULL;
4948     CONFIGRET ret;
4949 
4950     TRACE("CM_Get_Hardware_Profile_Info_ExW(%lu %p %lx %p)\n",
4951           ulIndex, pHWProfileInfo, ulFlags, hMachine);
4952 
4953     if (pHWProfileInfo == NULL)
4954         return CR_INVALID_POINTER;
4955 
4956     if (ulFlags != 0)
4957         return CR_INVALID_FLAG;
4958 
4959     if (hMachine != NULL)
4960     {
4961         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4962         if (BindingHandle == NULL)
4963             return CR_FAILURE;
4964     }
4965     else
4966     {
4967         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4968             return CR_FAILURE;
4969     }
4970 
4971     RpcTryExcept
4972     {
4973         ret = PNP_GetHwProfInfo(BindingHandle, ulIndex, pHWProfileInfo,
4974                                 sizeof(HWPROFILEINFO_W), 0);
4975     }
4976     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4977     {
4978         ret = RpcStatusToCmStatus(RpcExceptionCode());
4979     }
4980     RpcEndExcept;
4981 
4982     return ret;
4983 }
4984 
4985 
4986 /***********************************************************************
4987  * CM_Get_Log_Conf_Priority [SETUPAPI.@]
4988  */
4989 CONFIGRET
4990 WINAPI
4991 CM_Get_Log_Conf_Priority(
4992     _In_ LOG_CONF lcLogConf,
4993     _Out_ PPRIORITY pPriority,
4994     _In_ ULONG ulFlags)
4995 {
4996     TRACE("CM_Get_Log_Conf_Priority(%p %p %lx)\n",
4997           lcLogConf, pPriority, ulFlags);
4998 
4999     return CM_Get_Log_Conf_Priority_Ex(lcLogConf, pPriority, ulFlags, NULL);
5000 }
5001 
5002 
5003 /***********************************************************************
5004  * CM_Get_Log_Conf_Priority_Ex [SETUPAPI.@]
5005  */
5006 CONFIGRET
5007 WINAPI
5008 CM_Get_Log_Conf_Priority_Ex(
5009     _In_ LOG_CONF lcLogConf,
5010     _Out_ PPRIORITY pPriority,
5011     _In_ ULONG ulFlags,
5012     _In_opt_ HMACHINE hMachine)
5013 {
5014     RPC_BINDING_HANDLE BindingHandle = NULL;
5015     HSTRING_TABLE StringTable = NULL;
5016     PLOG_CONF_INFO pLogConfInfo;
5017     LPWSTR lpDevInst;
5018     CONFIGRET ret;
5019 
5020     FIXME("CM_Get_Log_Conf_Priority_Ex(%p %p %lx %p)\n",
5021           lcLogConf, pPriority, ulFlags, hMachine);
5022 
5023     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
5024     if (!IsValidLogConf(pLogConfInfo))
5025         return CR_INVALID_LOG_CONF;
5026 
5027     if (pPriority == NULL)
5028         return CR_INVALID_POINTER;
5029 
5030     if (ulFlags != 0)
5031         return CR_INVALID_FLAG;
5032 
5033     if (hMachine != NULL)
5034     {
5035         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5036         if (BindingHandle == NULL)
5037             return CR_FAILURE;
5038 
5039         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5040         if (StringTable == 0)
5041             return CR_FAILURE;
5042     }
5043     else
5044     {
5045         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5046             return CR_FAILURE;
5047     }
5048 
5049     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
5050     if (lpDevInst == NULL)
5051         return CR_INVALID_DEVNODE;
5052 
5053     RpcTryExcept
5054     {
5055         ret = PNP_GetLogConfPriority(BindingHandle,
5056                                      lpDevInst,
5057                                      pLogConfInfo->ulType,
5058                                      pLogConfInfo->ulTag,
5059                                      pPriority,
5060                                      0);
5061     }
5062     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5063     {
5064         ret = RpcStatusToCmStatus(RpcExceptionCode());
5065     }
5066     RpcEndExcept;
5067 
5068     return ret;
5069 }
5070 
5071 
5072 /***********************************************************************
5073  * CM_Get_Next_Log_Conf [SETUPAPI.@]
5074  */
5075 CONFIGRET
5076 WINAPI
5077 CM_Get_Next_Log_Conf(
5078     _Out_opt_ PLOG_CONF plcLogConf,
5079     _In_ LOG_CONF lcLogConf,
5080     _In_ ULONG ulFlags)
5081 {
5082     TRACE("CM_Get_Next_Log_Conf(%p %p %lx)\n",
5083           plcLogConf, lcLogConf, ulFlags);
5084 
5085     return CM_Get_Next_Log_Conf_Ex(plcLogConf, lcLogConf, ulFlags, NULL);
5086 }
5087 
5088 
5089 /***********************************************************************
5090  * CM_Get_Next_Log_Conf_Ex [SETUPAPI.@]
5091  */
5092 CONFIGRET
5093 WINAPI
5094 CM_Get_Next_Log_Conf_Ex(
5095     _Out_opt_ PLOG_CONF plcLogConf,
5096     _In_ LOG_CONF lcLogConf,
5097     _In_ ULONG ulFlags,
5098     _In_opt_ HMACHINE hMachine)
5099 {
5100     RPC_BINDING_HANDLE BindingHandle = NULL;
5101     HSTRING_TABLE StringTable = NULL;
5102     PLOG_CONF_INFO pLogConfInfo;
5103     PLOG_CONF_INFO pNewLogConfInfo;
5104     ULONG ulNewTag;
5105     LPWSTR lpDevInst;
5106     CONFIGRET ret;
5107 
5108     FIXME("CM_Get_Next_Log_Conf_Ex(%p %p %lx %p)\n",
5109           plcLogConf, lcLogConf, ulFlags, hMachine);
5110 
5111     if (plcLogConf)
5112         *plcLogConf = 0;
5113 
5114     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
5115     if (!IsValidLogConf(pLogConfInfo))
5116         return CR_INVALID_LOG_CONF;
5117 
5118     if (ulFlags != 0)
5119         return CR_INVALID_FLAG;
5120 
5121     if (hMachine != NULL)
5122     {
5123         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5124         if (BindingHandle == NULL)
5125             return CR_FAILURE;
5126 
5127         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5128         if (StringTable == 0)
5129             return CR_FAILURE;
5130     }
5131     else
5132     {
5133         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5134             return CR_FAILURE;
5135     }
5136 
5137     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
5138     if (lpDevInst == NULL)
5139         return CR_INVALID_DEVNODE;
5140 
5141     RpcTryExcept
5142     {
5143         ret = PNP_GetNextLogConf(BindingHandle,
5144                                  lpDevInst,
5145                                  pLogConfInfo->ulType,
5146                                  pLogConfInfo->ulTag,
5147                                  &ulNewTag,
5148                                  0);
5149     }
5150     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5151     {
5152         ret = RpcStatusToCmStatus(RpcExceptionCode());
5153     }
5154     RpcEndExcept;
5155 
5156     if (ret != CR_SUCCESS)
5157         return ret;
5158 
5159     if (plcLogConf)
5160     {
5161         pNewLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
5162         if (pNewLogConfInfo == NULL)
5163             return CR_OUT_OF_MEMORY;
5164 
5165         pNewLogConfInfo->ulMagic = LOG_CONF_MAGIC;
5166         pNewLogConfInfo->dnDevInst = pLogConfInfo->dnDevInst;
5167         pNewLogConfInfo->ulType = pLogConfInfo->ulType;
5168         pNewLogConfInfo->ulTag = ulNewTag;
5169 
5170         *plcLogConf = (LOG_CONF)pNewLogConfInfo;
5171     }
5172 
5173     return CR_SUCCESS;
5174 }
5175 
5176 
5177 /***********************************************************************
5178  * CM_Get_Next_Re_Des [SETUPAPI.@]
5179  */
5180 CONFIGRET
5181 WINAPI
5182 CM_Get_Next_Res_Des(
5183     _Out_ PRES_DES prdResDes,
5184     _In_ RES_DES rdResDes,
5185     _In_ RESOURCEID ForResource,
5186     _Out_opt_ PRESOURCEID pResourceID,
5187     _In_ ULONG ulFlags)
5188 {
5189     TRACE("CM_Get_Next_Res_Des(%p %p %lu %p %lx)\n",
5190           prdResDes, rdResDes, ForResource, pResourceID, ulFlags);
5191 
5192     return CM_Get_Next_Res_Des_Ex(prdResDes, rdResDes, ForResource,
5193                                   pResourceID, ulFlags, NULL);
5194 }
5195 
5196 
5197 /***********************************************************************
5198  * CM_Get_Next_Re_Des_Ex [SETUPAPI.@]
5199  */
5200 CONFIGRET
5201 WINAPI
5202 CM_Get_Next_Res_Des_Ex(
5203     _Out_ PRES_DES prdResDes,
5204     _In_ RES_DES rdResDes,
5205     _In_ RESOURCEID ForResource,
5206     _Out_opt_ PRESOURCEID pResourceID,
5207     _In_ ULONG ulFlags,
5208     _In_opt_ HMACHINE hMachine)
5209 {
5210     RPC_BINDING_HANDLE BindingHandle = NULL;
5211     HSTRING_TABLE StringTable = NULL;
5212     ULONG ulInTag, ulOutTag = 0;
5213     ULONG ulInType, ulOutType = 0;
5214     LPWSTR lpDevInst;
5215     DEVINST dnDevInst;
5216     CONFIGRET ret;
5217 
5218     FIXME("CM_Get_Next_Res_Des_Ex(%p %p %lu %p %lx %p)\n",
5219           prdResDes, rdResDes, ForResource, pResourceID, ulFlags, hMachine);
5220 
5221     if (prdResDes == NULL)
5222         return CR_INVALID_POINTER;
5223 
5224     if (IsValidLogConf((PLOG_CONF_INFO)rdResDes))
5225     {
5226         FIXME("LogConf found!\n");
5227         dnDevInst = ((PLOG_CONF_INFO)rdResDes)->dnDevInst;
5228         ulInTag = ((PLOG_CONF_INFO)rdResDes)->ulTag;
5229         ulInType = ((PLOG_CONF_INFO)rdResDes)->ulType;
5230     }
5231 #if 0
5232     else if (IsValidResDes((PRES_DES_INFO)rdResDes))
5233     {
5234         FIXME("ResDes found!\n");
5235         dnDevInst = ((PRES_DES_INFO)rdResDes)->dnDevInst;
5236         ulInTag = ((PRES_DES_INFO)rdResDes)->ulTag;
5237         ulInType = ((PRES_DES_INFO)rdResDes)->ulType;
5238     }
5239 #endif
5240     else
5241     {
5242         return CR_INVALID_RES_DES;
5243     }
5244 
5245     if (hMachine != NULL)
5246     {
5247         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5248         if (BindingHandle == NULL)
5249             return CR_FAILURE;
5250 
5251         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5252         if (StringTable == 0)
5253             return CR_FAILURE;
5254     }
5255     else
5256     {
5257         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5258             return CR_FAILURE;
5259     }
5260 
5261     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
5262     if (lpDevInst == NULL)
5263         return CR_INVALID_DEVNODE;
5264 
5265     RpcTryExcept
5266     {
5267         ret = PNP_GetNextResDes(BindingHandle,
5268                                 lpDevInst,
5269                                 ulInTag,
5270                                 ulInType,
5271                                 ForResource,
5272                                 0, /* unsigned long ulResourceTag, */
5273                                 &ulOutTag,
5274                                 &ulOutType,
5275                                 0);
5276     }
5277     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5278     {
5279         ret = RpcStatusToCmStatus(RpcExceptionCode());
5280     }
5281     RpcEndExcept;
5282 
5283     if (ret != CR_SUCCESS)
5284         return ret;
5285 
5286     /* FIXME: Create the ResDes handle */
5287 
5288     return CR_SUCCESS;
5289 }
5290 
5291 
5292 /***********************************************************************
5293  * CM_Get_Parent [SETUPAPI.@]
5294  */
5295 CONFIGRET
5296 WINAPI
5297 CM_Get_Parent(
5298     _Out_ PDEVINST pdnDevInst,
5299     _In_ DEVINST dnDevInst,
5300     _In_ ULONG ulFlags)
5301 {
5302     TRACE("CM_Get_Parent(%p %p %lx)\n",
5303           pdnDevInst, dnDevInst, ulFlags);
5304 
5305     return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
5306 }
5307 
5308 
5309 /***********************************************************************
5310  * CM_Get_Parent_Ex [SETUPAPI.@]
5311  */
5312 CONFIGRET
5313 WINAPI
5314 CM_Get_Parent_Ex(
5315     _Out_ PDEVINST pdnDevInst,
5316     _In_ DEVINST dnDevInst,
5317     _In_ ULONG ulFlags,
5318     _In_opt_ HMACHINE hMachine)
5319 {
5320     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
5321     RPC_BINDING_HANDLE BindingHandle = NULL;
5322     HSTRING_TABLE StringTable = NULL;
5323     LPWSTR lpDevInst;
5324     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
5325     CONFIGRET ret;
5326 
5327     TRACE("CM_Get_Parent_Ex(%p %lx %lx %p)\n",
5328           pdnDevInst, dnDevInst, ulFlags, hMachine);
5329 
5330     if (pdnDevInst == NULL)
5331         return CR_INVALID_POINTER;
5332 
5333     if (dnDevInst == 0)
5334         return CR_INVALID_DEVINST;
5335 
5336     if (ulFlags != 0)
5337         return CR_INVALID_FLAG;
5338 
5339     *pdnDevInst = -1;
5340 
5341     if (hMachine != NULL)
5342     {
5343         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5344         if (BindingHandle == NULL)
5345             return CR_FAILURE;
5346 
5347         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5348         if (StringTable == 0)
5349             return CR_FAILURE;
5350     }
5351     else
5352     {
5353         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5354             return CR_FAILURE;
5355     }
5356 
5357     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
5358     if (lpDevInst == NULL)
5359         return CR_INVALID_DEVNODE;
5360 
5361     RpcTryExcept
5362     {
5363         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
5364                                            PNP_GET_PARENT_DEVICE_INSTANCE,
5365                                            lpDevInst,
5366                                            szRelatedDevInst,
5367                                            &dwLength,
5368                                            0);
5369     }
5370     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5371     {
5372         ret = RpcStatusToCmStatus(RpcExceptionCode());
5373     }
5374     RpcEndExcept;
5375 
5376     if (ret != CR_SUCCESS)
5377         return ret;
5378 
5379     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
5380 
5381     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
5382     if (dwIndex == -1)
5383         return CR_FAILURE;
5384 
5385     *pdnDevInst = dwIndex;
5386 
5387     return CR_SUCCESS;
5388 }
5389 
5390 
5391 /***********************************************************************
5392  * CM_Get_Res_Des_Data [SETUPAPI.@]
5393  */
5394 CONFIGRET
5395 WINAPI
5396 CM_Get_Res_Des_Data(
5397     _In_ RES_DES rdResDes,
5398     _Out_writes_bytes_(BufferLen) PVOID Buffer,
5399     _In_ ULONG BufferLen,
5400     _In_ ULONG ulFlags)
5401 {
5402     TRACE("CM_Get_Res_Des_Data(%p %p %lu %lx)\n",
5403           rdResDes, Buffer, BufferLen, ulFlags);
5404 
5405     return CM_Get_Res_Des_Data_Ex(rdResDes, Buffer, BufferLen, ulFlags, NULL);
5406 }
5407 
5408 
5409 /***********************************************************************
5410  * CM_Get_Res_Des_Data_Ex [SETUPAPI.@]
5411  */
5412 CONFIGRET
5413 WINAPI
5414 CM_Get_Res_Des_Data_Ex(
5415     _In_ RES_DES rdResDes,
5416     _Out_writes_bytes_(BufferLen) PVOID Buffer,
5417     _In_ ULONG BufferLen,
5418     _In_ ULONG ulFlags,
5419     _In_opt_ HMACHINE hMachine)
5420 {
5421     FIXME("CM_Get_Res_Des_Data_Ex(%p %p %lu %lx %p)\n",
5422           rdResDes, Buffer, BufferLen, ulFlags, hMachine);
5423 
5424     return CR_CALL_NOT_IMPLEMENTED;
5425 }
5426 
5427 
5428 /***********************************************************************
5429  * CM_Get_Res_Des_Size [SETUPAPI.@]
5430  */
5431 CONFIGRET
5432 WINAPI
5433 CM_Get_Res_Des_Data_Size(
5434     _Out_ PULONG pulSize,
5435     _In_ RES_DES rdResDes,
5436     _In_ ULONG ulFlags)
5437 {
5438     TRACE("CM_Get_Res_Des_Data_Size(%p %p %lx)\n",
5439           pulSize, rdResDes, ulFlags);
5440 
5441     return CM_Get_Res_Des_Data_Size_Ex(pulSize, rdResDes, ulFlags, NULL);
5442 }
5443 
5444 
5445 /***********************************************************************
5446  * CM_Get_Res_Des_Size_Ex [SETUPAPI.@]
5447  */
5448 CONFIGRET
5449 WINAPI
5450 CM_Get_Res_Des_Data_Size_Ex(
5451     _Out_ PULONG pulSize,
5452     _In_ RES_DES rdResDes,
5453     _In_ ULONG ulFlags,
5454     _In_opt_ HMACHINE hMachine)
5455 {
5456     TRACE("CM_Get_Res_Des_Data_Size_Ex(%p %p %lx %p)\n",
5457           pulSize, rdResDes, ulFlags, hMachine);
5458 
5459     return CR_CALL_NOT_IMPLEMENTED;
5460 }
5461 
5462 
5463 /***********************************************************************
5464  * CM_Get_Resource_Conflict_Count [SETUPAPI.@]
5465  */
5466 CONFIGRET
5467 WINAPI
5468 CM_Get_Resource_Conflict_Count(
5469     _In_ CONFLICT_LIST clConflictList,
5470     _Out_ PULONG pulCount)
5471 {
5472     PCONFLICT_DATA pConflictData;
5473 
5474     FIXME("CM_Get_Resource_Conflict_Count(%p %p)\n",
5475           clConflictList, pulCount);
5476 
5477     pConflictData = (PCONFLICT_DATA)clConflictList;
5478     if (!IsValidConflictData(pConflictData))
5479         return CR_INVALID_CONFLICT_LIST;
5480 
5481     if (pulCount == NULL)
5482         return CR_INVALID_POINTER;
5483 
5484     *pulCount = pConflictData->pConflictList->ConflictsListed;
5485 
5486     return CR_SUCCESS;
5487 }
5488 
5489 
5490 /***********************************************************************
5491  * CM_Get_Resource_Conflict_DetailsA [SETUPAPI.@]
5492  */
5493 CONFIGRET
5494 WINAPI
5495 CM_Get_Resource_Conflict_DetailsA(
5496     _In_ CONFLICT_LIST clConflictList,
5497     _In_ ULONG ulIndex,
5498     _Inout_ PCONFLICT_DETAILS_A pConflictDetails)
5499 {
5500     FIXME("CM_Get_Resource_Conflict_CountA(%p %lu %p)\n",
5501           clConflictList, ulIndex, pConflictDetails);
5502 
5503     return CR_CALL_NOT_IMPLEMENTED;
5504 }
5505 
5506 
5507 /***********************************************************************
5508  * CM_Get_Resource_Conflict_DetailsW [SETUPAPI.@]
5509  */
5510 CONFIGRET
5511 WINAPI
5512 CM_Get_Resource_Conflict_DetailsW(
5513     _In_ CONFLICT_LIST clConflictList,
5514     _In_ ULONG ulIndex,
5515     _Inout_ PCONFLICT_DETAILS_W pConflictDetails)
5516 {
5517     FIXME("CM_Get_Resource_Conflict_CountW(%p %lu %p)\n",
5518           clConflictList, ulIndex, pConflictDetails);
5519 
5520     return CR_CALL_NOT_IMPLEMENTED;
5521 }
5522 
5523 
5524 /***********************************************************************
5525  * CM_Get_Sibling [SETUPAPI.@]
5526  */
5527 CONFIGRET
5528 WINAPI
5529 CM_Get_Sibling(
5530     _Out_ PDEVINST pdnDevInst,
5531     _In_ DEVINST dnDevInst,
5532     _In_ ULONG ulFlags)
5533 {
5534     TRACE("CM_Get_Sibling(%p %p %lx)\n",
5535           pdnDevInst, dnDevInst, ulFlags);
5536 
5537     return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
5538 }
5539 
5540 
5541 /***********************************************************************
5542  * CM_Get_Sibling_Ex [SETUPAPI.@]
5543  */
5544 CONFIGRET
5545 WINAPI
5546 CM_Get_Sibling_Ex(
5547     _Out_ PDEVINST pdnDevInst,
5548     _In_ DEVINST dnDevInst,
5549     _In_ ULONG ulFlags,
5550     _In_opt_ HMACHINE hMachine)
5551 {
5552     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
5553     RPC_BINDING_HANDLE BindingHandle = NULL;
5554     HSTRING_TABLE StringTable = NULL;
5555     LPWSTR lpDevInst;
5556     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
5557     CONFIGRET ret;
5558 
5559     TRACE("CM_Get_Sibling_Ex(%p %lx %lx %p)\n",
5560           pdnDevInst, dnDevInst, ulFlags, hMachine);
5561 
5562     if (pdnDevInst == NULL)
5563         return CR_INVALID_POINTER;
5564 
5565     if (dnDevInst == 0)
5566         return CR_INVALID_DEVINST;
5567 
5568     if (ulFlags != 0)
5569         return CR_INVALID_FLAG;
5570 
5571     *pdnDevInst = -1;
5572 
5573     if (hMachine != NULL)
5574     {
5575         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5576         if (BindingHandle == NULL)
5577             return CR_FAILURE;
5578 
5579         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5580         if (StringTable == 0)
5581             return CR_FAILURE;
5582     }
5583     else
5584     {
5585         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5586             return CR_FAILURE;
5587     }
5588 
5589     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
5590     if (lpDevInst == NULL)
5591         return CR_INVALID_DEVNODE;
5592 
5593     RpcTryExcept
5594     {
5595         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
5596                                            PNP_GET_SIBLING_DEVICE_INSTANCE,
5597                                            lpDevInst,
5598                                            szRelatedDevInst,
5599                                            &dwLength,
5600                                            0);
5601     }
5602     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5603     {
5604         ret = RpcStatusToCmStatus(RpcExceptionCode());
5605     }
5606     RpcEndExcept;
5607 
5608     if (ret != CR_SUCCESS)
5609         return ret;
5610 
5611     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
5612 
5613     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
5614     if (dwIndex == -1)
5615         return CR_FAILURE;
5616 
5617     *pdnDevInst = dwIndex;
5618 
5619     return CR_SUCCESS;
5620 }
5621 
5622 
5623 /***********************************************************************
5624  * CM_Get_Version [SETUPAPI.@]
5625  */
5626 WORD
5627 WINAPI
5628 CM_Get_Version(VOID)
5629 {
5630     TRACE("CM_Get_Version()\n");
5631 
5632     return CM_Get_Version_Ex(NULL);
5633 }
5634 
5635 
5636 /***********************************************************************
5637  * CM_Get_Version_Ex [SETUPAPI.@]
5638  */
5639 WORD
5640 WINAPI
5641 CM_Get_Version_Ex(
5642     _In_opt_ HMACHINE hMachine)
5643 {
5644     RPC_BINDING_HANDLE BindingHandle = NULL;
5645     WORD Version = 0;
5646     CONFIGRET ret;
5647 
5648     TRACE("CM_Get_Version_Ex(%p)\n", hMachine);
5649 
5650     if (hMachine != NULL)
5651     {
5652         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5653         if (BindingHandle == NULL)
5654             return 0;
5655     }
5656     else
5657     {
5658         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5659             return CR_FAILURE;
5660     }
5661 
5662     RpcTryExcept
5663     {
5664         ret = PNP_GetVersion(BindingHandle, &Version);
5665     }
5666     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5667     {
5668         ret = RpcStatusToCmStatus(RpcExceptionCode());
5669     }
5670     RpcEndExcept;
5671 
5672     if (ret != CR_SUCCESS)
5673         return 0;
5674 
5675     return Version;
5676 }
5677 
5678 
5679 /***********************************************************************
5680  * CM_Intersect_Range_List [SETUPAPI.@]
5681  */
5682 CONFIGRET
5683 WINAPI
5684 CM_Intersect_Range_List(
5685     _In_ RANGE_LIST rlhOld1,
5686     _In_ RANGE_LIST rlhOld2,
5687     _In_ RANGE_LIST rlhNew,
5688     _In_ ULONG ulFlags)
5689 {
5690     FIXME("CM_Intersect_Range_List(%p %p %p %lx)\n",
5691           rlhOld1, rlhOld2, rlhNew, ulFlags);
5692 
5693     return CR_CALL_NOT_IMPLEMENTED;
5694 }
5695 
5696 
5697 /***********************************************************************
5698  * CM_Invert_Range_List [SETUPAPI.@]
5699  */
5700 CONFIGRET
5701 WINAPI
5702 CM_Invert_Range_List(
5703     _In_ RANGE_LIST rlhOld,
5704     _In_ RANGE_LIST rlhNew,
5705     _In_ DWORDLONG ullMaxValue,
5706     _In_ ULONG ulFlags)
5707 {
5708     FIXME("CM_Invert_Range_List(%p %p %I64u %lx)\n",
5709           rlhOld, rlhNew, ullMaxValue, ulFlags);
5710 
5711     return CR_CALL_NOT_IMPLEMENTED;
5712 }
5713 
5714 
5715 /***********************************************************************
5716  * CM_Is_Dock_Station_Present [SETUPAPI.@]
5717  */
5718 CONFIGRET
5719 WINAPI
5720 CM_Is_Dock_Station_Present(
5721     _Out_ PBOOL pbPresent)
5722 {
5723     TRACE("CM_Is_Dock_Station_Present(%p)\n",
5724           pbPresent);
5725 
5726     return CM_Is_Dock_Station_Present_Ex(pbPresent, NULL);
5727 }
5728 
5729 
5730 /***********************************************************************
5731  * CM_Is_Dock_Station_Present_Ex [SETUPAPI.@]
5732  */
5733 CONFIGRET
5734 WINAPI
5735 CM_Is_Dock_Station_Present_Ex(
5736     _Out_ PBOOL pbPresent,
5737     _In_opt_ HMACHINE hMachine)
5738 {
5739     RPC_BINDING_HANDLE BindingHandle = NULL;
5740     CONFIGRET ret;
5741 
5742     TRACE("CM_Is_Dock_Station_Present_Ex(%p %p)\n",
5743           pbPresent, hMachine);
5744 
5745     if (pbPresent == NULL)
5746         return CR_INVALID_POINTER;
5747 
5748     *pbPresent = FALSE;
5749 
5750     if (hMachine != NULL)
5751     {
5752         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5753         if (BindingHandle == NULL)
5754             return CR_FAILURE;
5755     }
5756     else
5757     {
5758         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5759             return CR_FAILURE;
5760     }
5761 
5762     RpcTryExcept
5763     {
5764         ret = PNP_IsDockStationPresent(BindingHandle,
5765                                        pbPresent);
5766     }
5767     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5768     {
5769         ret = RpcStatusToCmStatus(RpcExceptionCode());
5770     }
5771     RpcEndExcept;
5772 
5773     return ret;
5774 }
5775 
5776 
5777 /***********************************************************************
5778  * CM_Is_Version_Available_Ex [SETUPAPI.@]
5779  */
5780 BOOL
5781 WINAPI
5782 CM_Is_Version_Available(
5783      _In_ WORD wVersion)
5784 {
5785     TRACE("CM_Is_Version_Available(%hu)\n",
5786           wVersion);
5787 
5788     return CM_Is_Version_Available_Ex(wVersion, NULL);
5789 }
5790 
5791 
5792 /***********************************************************************
5793  * CM_Is_Version_Available_Ex [SETUPAPI.@]
5794  */
5795 BOOL
5796 WINAPI
5797 CM_Is_Version_Available_Ex(
5798     _In_ WORD wVersion,
5799     _In_opt_ HMACHINE hMachine)
5800 {
5801     RPC_BINDING_HANDLE BindingHandle = NULL;
5802     WORD wServerVersion;
5803     CONFIGRET ret;
5804 
5805     TRACE("CM_Is_Version_Available_Ex(%hu %p)\n",
5806           wVersion, hMachine);
5807 
5808     if (wVersion <= 0x400)
5809         return TRUE;
5810 
5811     if (hMachine != NULL)
5812     {
5813         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5814         if (BindingHandle == NULL)
5815             return FALSE;
5816     }
5817     else
5818     {
5819         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5820             return FALSE;
5821     }
5822 
5823     RpcTryExcept
5824     {
5825         ret = PNP_GetVersion(BindingHandle, &wServerVersion);
5826     }
5827     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5828     {
5829         ret = RpcStatusToCmStatus(RpcExceptionCode());
5830     }
5831     RpcEndExcept;
5832 
5833     if (ret != CR_SUCCESS)
5834         return FALSE;
5835 
5836     return (wServerVersion >= wVersion);
5837 }
5838 
5839 
5840 /***********************************************************************
5841  * CM_Locate_DevNodeA [SETUPAPI.@]
5842  */
5843 CONFIGRET
5844 WINAPI
5845 CM_Locate_DevNodeA(
5846     _Out_ PDEVINST pdnDevInst,
5847     _In_opt_ DEVINSTID_A pDeviceID,
5848     _In_ ULONG ulFlags)
5849 {
5850     TRACE("CM_Locate_DevNodeA(%p %s %lx)\n",
5851           pdnDevInst, debugstr_a(pDeviceID), ulFlags);
5852 
5853     return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
5854 }
5855 
5856 
5857 /***********************************************************************
5858  * CM_Locate_DevNodeW [SETUPAPI.@]
5859  */
5860 CONFIGRET
5861 WINAPI
5862 CM_Locate_DevNodeW(
5863     _Out_ PDEVINST pdnDevInst,
5864     _In_opt_ DEVINSTID_W pDeviceID,
5865     _In_ ULONG ulFlags)
5866 {
5867     TRACE("CM_Locate_DevNodeW(%p %s %lx)\n",
5868           pdnDevInst, debugstr_w(pDeviceID), ulFlags);
5869 
5870     return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
5871 }
5872 
5873 
5874 /***********************************************************************
5875  * CM_Locate_DevNode_ExA [SETUPAPI.@]
5876  */
5877 CONFIGRET
5878 WINAPI
5879 CM_Locate_DevNode_ExA(
5880     _Out_ PDEVINST pdnDevInst,
5881     _In_opt_ DEVINSTID_A pDeviceID,
5882     _In_ ULONG ulFlags,
5883     _In_opt_ HMACHINE hMachine)
5884 {
5885     DEVINSTID_W pDevIdW = NULL;
5886     CONFIGRET ret = CR_SUCCESS;
5887 
5888     TRACE("CM_Locate_DevNode_ExA(%p %s %lx %p)\n",
5889           pdnDevInst, debugstr_a(pDeviceID), ulFlags, hMachine);
5890 
5891     if (pDeviceID != NULL)
5892     {
5893        if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDevIdW))
5894          return CR_INVALID_DEVICE_ID;
5895     }
5896 
5897     ret = CM_Locate_DevNode_ExW(pdnDevInst, pDevIdW, ulFlags, hMachine);
5898 
5899     if (pDevIdW != NULL)
5900         MyFree(pDevIdW);
5901 
5902     return ret;
5903 }
5904 
5905 
5906 /***********************************************************************
5907  * CM_Locate_DevNode_ExW [SETUPAPI.@]
5908  */
5909 CONFIGRET
5910 WINAPI
5911 CM_Locate_DevNode_ExW(
5912     _Out_ PDEVINST pdnDevInst,
5913     _In_opt_ DEVINSTID_W pDeviceID,
5914     _In_ ULONG ulFlags,
5915     _In_opt_ HMACHINE hMachine)
5916 {
5917     WCHAR DeviceIdBuffer[MAX_DEVICE_ID_LEN];
5918     RPC_BINDING_HANDLE BindingHandle = NULL;
5919     HSTRING_TABLE StringTable = NULL;
5920     CONFIGRET ret = CR_SUCCESS;
5921 
5922     TRACE("CM_Locate_DevNode_ExW(%p %s %lx %p)\n",
5923           pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
5924 
5925     if (pdnDevInst == NULL)
5926         return CR_INVALID_POINTER;
5927 
5928     if (ulFlags & ~CM_LOCATE_DEVNODE_BITS)
5929         return CR_INVALID_FLAG;
5930 
5931     if (hMachine != NULL)
5932     {
5933         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5934         if (BindingHandle == NULL)
5935             return CR_FAILURE;
5936 
5937         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5938         if (StringTable == 0)
5939             return CR_FAILURE;
5940     }
5941     else
5942     {
5943         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5944             return CR_FAILURE;
5945     }
5946 
5947     if (pDeviceID != NULL && lstrlenW(pDeviceID) != 0)
5948     {
5949         lstrcpyW(DeviceIdBuffer, pDeviceID);
5950 
5951         RpcTryExcept
5952         {
5953             /* Validate the device ID */
5954             ret = PNP_ValidateDeviceInstance(BindingHandle,
5955                                              DeviceIdBuffer,
5956                                              ulFlags);
5957         }
5958         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5959         {
5960             ret = RpcStatusToCmStatus(RpcExceptionCode());
5961         }
5962         RpcEndExcept;
5963     }
5964     else
5965     {
5966         RpcTryExcept
5967         {
5968             /* Get the root device ID */
5969             ret = PNP_GetRootDeviceInstance(BindingHandle,
5970                                             DeviceIdBuffer,
5971                                             MAX_DEVICE_ID_LEN);
5972         }
5973         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5974         {
5975             ret = RpcStatusToCmStatus(RpcExceptionCode());
5976         }
5977         RpcEndExcept;
5978     }
5979 
5980     TRACE("DeviceIdBuffer: %s\n", debugstr_w(DeviceIdBuffer));
5981 
5982     if (ret == CR_SUCCESS)
5983     {
5984         *pdnDevInst = pSetupStringTableAddString(StringTable, DeviceIdBuffer, 1);
5985         if (*pdnDevInst == -1)
5986             ret = CR_FAILURE;
5987     }
5988 
5989     return ret;
5990 }
5991 
5992 
5993 /***********************************************************************
5994  * CM_Merge_Range_List [SETUPAPI.@]
5995  */
5996 CONFIGRET
5997 WINAPI
5998 CM_Merge_Range_List(
5999     _In_ RANGE_LIST rlhOld1,
6000     _In_ RANGE_LIST rlhOld2,
6001     _In_ RANGE_LIST rlhNew,
6002     _In_ ULONG ulFlags)
6003 {
6004     FIXME("CM_Merge_Range_List(%p %p %p %lx)\n",
6005           rlhOld1, rlhOld2, rlhNew, ulFlags);
6006 
6007     return CR_CALL_NOT_IMPLEMENTED;
6008 }
6009 
6010 
6011 /***********************************************************************
6012  * CM_Modify_Res_Des [SETUPAPI.@]
6013  */
6014 CONFIGRET
6015 WINAPI
6016 CM_Modify_Res_Des(
6017     _Out_ PRES_DES prdResDes,
6018     _In_ RES_DES rdResDes,
6019     _In_ RESOURCEID ResourceID,
6020     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
6021     _In_ ULONG ResourceLen,
6022     _In_ ULONG ulFlags)
6023 {
6024     TRACE("CM_Modify_Res_Des(%p %p %lx %p %lu %lx)\n",
6025           prdResDes, rdResDes, ResourceID, ResourceData,
6026           ResourceLen, ulFlags);
6027 
6028     return CM_Modify_Res_Des_Ex(prdResDes, rdResDes, ResourceID, ResourceData,
6029                                 ResourceLen, ulFlags, NULL);
6030 }
6031 
6032 
6033 /***********************************************************************
6034  * CM_Modify_Res_Des_Ex [SETUPAPI.@]
6035  */
6036 CONFIGRET
6037 WINAPI
6038 CM_Modify_Res_Des_Ex(
6039     _Out_ PRES_DES prdResDes,
6040     _In_ RES_DES rdResDes,
6041     _In_ RESOURCEID ResourceID,
6042     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
6043     _In_ ULONG ResourceLen,
6044     _In_ ULONG ulFlags,
6045     _In_opt_ HMACHINE hMachine)
6046 {
6047     FIXME("CM_Modify_Res_Des_Ex(%p %p %lx %p %lu %lx %p)\n",
6048           prdResDes, rdResDes, ResourceID, ResourceData,
6049           ResourceLen, ulFlags, hMachine);
6050 
6051     return CR_CALL_NOT_IMPLEMENTED;
6052 }
6053 
6054 
6055 /***********************************************************************
6056  * CM_Move_DevNode [SETUPAPI.@]
6057  */
6058 CONFIGRET
6059 WINAPI
6060 CM_Move_DevNode(
6061     _In_ DEVINST dnFromDevInst,
6062     _In_ DEVINST dnToDevInst,
6063     _In_ ULONG ulFlags)
6064 {
6065     TRACE("CM_Move_DevNode(%lx %lx %lx)\n",
6066           dnFromDevInst, dnToDevInst, ulFlags);
6067 
6068     return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
6069 }
6070 
6071 
6072 /***********************************************************************
6073  * CM_Move_DevNode_Ex [SETUPAPI.@]
6074  */
6075 CONFIGRET
6076 WINAPI
6077 CM_Move_DevNode_Ex(
6078     _In_ DEVINST dnFromDevInst,
6079     _In_ DEVINST dnToDevInst,
6080     _In_ ULONG ulFlags,
6081     _In_opt_ HMACHINE hMachine)
6082 {
6083     RPC_BINDING_HANDLE BindingHandle = NULL;
6084     HSTRING_TABLE StringTable = NULL;
6085     LPWSTR lpFromDevInst;
6086     LPWSTR lpToDevInst;
6087     CONFIGRET ret;
6088 
6089     FIXME("CM_Move_DevNode_Ex(%lx %lx %lx %p)\n",
6090           dnFromDevInst, dnToDevInst, ulFlags, hMachine);
6091 
6092     if (!pSetupIsUserAdmin())
6093         return CR_ACCESS_DENIED;
6094 
6095     if (dnFromDevInst == 0 || dnToDevInst == 0)
6096         return CR_INVALID_DEVNODE;
6097 
6098     if (ulFlags != 0)
6099         return CR_INVALID_FLAG;
6100 
6101     if (hMachine != NULL)
6102     {
6103         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6104         if (BindingHandle == NULL)
6105             return CR_FAILURE;
6106 
6107         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6108         if (StringTable == 0)
6109             return CR_FAILURE;
6110     }
6111     else
6112     {
6113         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6114             return CR_FAILURE;
6115     }
6116 
6117     lpFromDevInst = pSetupStringTableStringFromId(StringTable, dnFromDevInst);
6118     if (lpFromDevInst == NULL)
6119         return CR_INVALID_DEVNODE;
6120 
6121     lpToDevInst = pSetupStringTableStringFromId(StringTable, dnToDevInst);
6122     if (lpToDevInst == NULL)
6123         return CR_INVALID_DEVNODE;
6124 
6125     RpcTryExcept
6126     {
6127         ret = PNP_DeviceInstanceAction(BindingHandle,
6128                                        PNP_DEVINST_MOVE,
6129                                        ulFlags,
6130                                        lpFromDevInst,
6131                                        lpToDevInst);
6132     }
6133     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6134     {
6135         ret = RpcStatusToCmStatus(RpcExceptionCode());
6136     }
6137     RpcEndExcept;
6138 
6139     return ret;
6140 }
6141 
6142 
6143 /***********************************************************************
6144  * CM_Next_Range [SETUPAPI.@]
6145  */
6146 CONFIGRET
6147 WINAPI
6148 CM_Next_Range(
6149     _Inout_ PRANGE_ELEMENT preElement,
6150     _Out_ PDWORDLONG pullStart,
6151     _Out_ PDWORDLONG pullEnd,
6152     _In_ ULONG ulFlags)
6153 {
6154     PINTERNAL_RANGE_LIST pRangeList;
6155     PINTERNAL_RANGE pRange;
6156     PLIST_ENTRY ListEntry;
6157     CONFIGRET ret = CR_SUCCESS;
6158 
6159     FIXME("CM_Next_Range(%p %p %p %lx)\n",
6160           preElement, pullStart, pullEnd, ulFlags);
6161 
6162     pRange = (PINTERNAL_RANGE)preElement;
6163 
6164     if (pRange == NULL || pRange->pRangeList == NULL)
6165         return CR_FAILURE;
6166 
6167     if (pullStart == NULL || pullEnd == NULL)
6168         return CR_INVALID_POINTER;
6169 
6170     if (ulFlags != 0)
6171         return CR_INVALID_FLAG;
6172 
6173     pRangeList = pRange->pRangeList;
6174 
6175     /* Lock the range list */
6176     WaitForSingleObject(pRangeList->hMutex, INFINITE);
6177 
6178     /* Fail, if we reached the end of the list */
6179     if (pRange->ListEntry.Flink == &pRangeList->ListHead)
6180     {
6181         ret = CR_FAILURE;
6182         goto done;
6183     }
6184 
6185     /* Get the next range */
6186     ListEntry = pRangeList->ListHead.Flink;
6187     pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
6188 
6189     /* Return the range data */
6190     *pullStart = pRange->ullStart;
6191     *pullEnd = pRange->ullEnd;
6192     *preElement = (RANGE_ELEMENT)pRange;
6193 
6194 done:
6195     /* Unlock the range list */
6196     ReleaseMutex(pRangeList->hMutex);
6197 
6198     return ret;
6199 }
6200 
6201 
6202 /***********************************************************************
6203  * CM_Open_Class_KeyA [SETUPAPI.@]
6204  */
6205 CONFIGRET
6206 WINAPI
6207 CM_Open_Class_KeyA(
6208     _In_opt_ LPGUID pClassGuid,
6209     _In_opt_ LPCSTR pszClassName,
6210     _In_ REGSAM samDesired,
6211     _In_ REGDISPOSITION Disposition,
6212     _Out_ PHKEY phkClass,
6213     _In_ ULONG ulFlags)
6214 {
6215     TRACE("CM_Open_Class_KeyA(%p %s %lx %lx %p %lx)\n",
6216           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
6217           samDesired, Disposition, phkClass, ulFlags);
6218 
6219     return CM_Open_Class_Key_ExA(pClassGuid, pszClassName, samDesired,
6220                                  Disposition, phkClass, ulFlags, NULL);
6221 }
6222 
6223 
6224 /***********************************************************************
6225  * CM_Open_Class_KeyW [SETUPAPI.@]
6226  */
6227 CONFIGRET
6228 WINAPI
6229 CM_Open_Class_KeyW(
6230     _In_opt_ LPGUID pClassGuid,
6231     _In_opt_ LPCWSTR pszClassName,
6232     _In_ REGSAM samDesired,
6233     _In_ REGDISPOSITION Disposition,
6234     _Out_ PHKEY phkClass,
6235     _In_ ULONG ulFlags)
6236 {
6237     TRACE("CM_Open_Class_KeyW(%p %s %lx %lx %p %lx)\n",
6238           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
6239           samDesired, Disposition, phkClass, ulFlags);
6240 
6241     return CM_Open_Class_Key_ExW(pClassGuid, pszClassName, samDesired,
6242                                  Disposition, phkClass, ulFlags, NULL);
6243 }
6244 
6245 
6246 /***********************************************************************
6247  * CM_Open_Class_Key_ExA [SETUPAPI.@]
6248  */
6249 CONFIGRET
6250 WINAPI
6251 CM_Open_Class_Key_ExA(
6252     _In_opt_ LPGUID pClassGuid,
6253     _In_opt_ LPCSTR pszClassName,
6254     _In_ REGSAM samDesired,
6255     _In_ REGDISPOSITION Disposition,
6256     _Out_ PHKEY phkClass,
6257     _In_ ULONG ulFlags,
6258     _In_opt_ HMACHINE hMachine)
6259 {
6260     LPWSTR pszClassNameW = NULL;
6261     CONFIGRET ret;
6262 
6263     TRACE("CM_Open_Class_Key_ExA(%p %s %lx %lx %p %lx %p)\n",
6264           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
6265           samDesired, Disposition, phkClass, ulFlags, hMachine);
6266 
6267     if (pszClassName != NULL)
6268     {
6269        if (pSetupCaptureAndConvertAnsiArg(pszClassName, &pszClassNameW))
6270          return CR_INVALID_DATA;
6271     }
6272 
6273     ret = CM_Open_Class_Key_ExW(pClassGuid, pszClassNameW, samDesired,
6274                                 Disposition, phkClass, ulFlags, hMachine);
6275 
6276     if (pszClassNameW != NULL)
6277         MyFree(pszClassNameW);
6278 
6279     return ret;
6280 }
6281 
6282 
6283 /***********************************************************************
6284  * CM_Open_Class_Key_ExW [SETUPAPI.@]
6285  */
6286 CONFIGRET
6287 WINAPI
6288 CM_Open_Class_Key_ExW(
6289     _In_opt_ LPGUID pClassGuid,
6290     _In_opt_ LPCWSTR pszClassName,
6291     _In_ REGSAM samDesired,
6292     _In_ REGDISPOSITION Disposition,
6293     _Out_ PHKEY phkClass,
6294     _In_ ULONG ulFlags,
6295     _In_opt_ HMACHINE hMachine)
6296 {
6297     WCHAR szKeyName[MAX_PATH];
6298     LPWSTR lpGuidString;
6299     DWORD dwDisposition;
6300     DWORD dwError;
6301     HKEY hKey;
6302 
6303     TRACE("CM_Open_Class_Key_ExW(%p %s %lx %lx %p %lx %p)\n",
6304           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
6305           samDesired, Disposition, phkClass, ulFlags, hMachine);
6306 
6307     /* Check Disposition and ulFlags */
6308     if ((Disposition & ~RegDisposition_Bits) ||
6309         (ulFlags & ~CM_OPEN_CLASS_KEY_BITS))
6310         return CR_INVALID_FLAG;
6311 
6312     /* Check phkClass */
6313     if (phkClass == NULL)
6314         return CR_INVALID_POINTER;
6315 
6316     *phkClass = NULL;
6317 
6318     if (ulFlags == CM_OPEN_CLASS_KEY_INTERFACE &&
6319         pszClassName != NULL)
6320         return CR_INVALID_DATA;
6321 
6322     if (hMachine == NULL)
6323     {
6324         hKey = HKEY_LOCAL_MACHINE;
6325     }
6326     else
6327     {
6328         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6329                                 HKEY_LOCAL_MACHINE,
6330                                 &hKey))
6331             return CR_REGISTRY_ERROR;
6332     }
6333 
6334     if (ulFlags & CM_OPEN_CLASS_KEY_INTERFACE)
6335     {
6336         lstrcpyW(szKeyName, DeviceClasses);
6337     }
6338     else
6339     {
6340         lstrcpyW(szKeyName, ControlClass);
6341     }
6342 
6343     if (pClassGuid != NULL)
6344     {
6345         if (UuidToStringW((UUID*)pClassGuid, &lpGuidString) != RPC_S_OK)
6346         {
6347             RegCloseKey(hKey);
6348             return CR_INVALID_DATA;
6349         }
6350 
6351         lstrcatW(szKeyName, BackslashOpenBrace);
6352         lstrcatW(szKeyName, lpGuidString);
6353         lstrcatW(szKeyName, CloseBrace);
6354     }
6355 
6356     if (Disposition == RegDisposition_OpenAlways)
6357     {
6358         dwError = RegCreateKeyExW(hKey, szKeyName, 0, NULL, 0, samDesired,
6359                                   NULL, phkClass, &dwDisposition);
6360     }
6361     else
6362     {
6363         dwError = RegOpenKeyExW(hKey, szKeyName, 0, samDesired, phkClass);
6364     }
6365 
6366     RegCloseKey(hKey);
6367 
6368     if (pClassGuid != NULL)
6369         RpcStringFreeW(&lpGuidString);
6370 
6371     if (dwError != ERROR_SUCCESS)
6372     {
6373         *phkClass = NULL;
6374         return CR_NO_SUCH_REGISTRY_KEY;
6375     }
6376 
6377     if (pszClassName != NULL)
6378     {
6379         RegSetValueExW(*phkClass, Class, 0, REG_SZ, (LPBYTE)pszClassName,
6380                        (lstrlenW(pszClassName) + 1) * sizeof(WCHAR));
6381     }
6382 
6383     return CR_SUCCESS;
6384 }
6385 
6386 
6387 /***********************************************************************
6388  * CM_Open_DevNode_Key [SETUPAPI.@]
6389  */
6390 CONFIGRET
6391 WINAPI
6392 CM_Open_DevNode_Key(
6393     _In_ DEVINST dnDevNode,
6394     _In_ REGSAM samDesired,
6395     _In_ ULONG ulHardwareProfile,
6396     _In_ REGDISPOSITION Disposition,
6397     _Out_ PHKEY phkDevice,
6398     _In_ ULONG ulFlags)
6399 {
6400     TRACE("CM_Open_DevNode_Key(%lx %lx %lu %lx %p %lx)\n",
6401           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags);
6402 
6403     return CM_Open_DevNode_Key_Ex(dnDevNode, samDesired, ulHardwareProfile,
6404                                   Disposition, phkDevice, ulFlags, NULL);
6405 }
6406 
6407 
6408 /***********************************************************************
6409  * CM_Open_DevNode_Key_Ex [SETUPAPI.@]
6410  */
6411 CONFIGRET
6412 WINAPI
6413 CM_Open_DevNode_Key_Ex(
6414     _In_ DEVINST dnDevNode,
6415     _In_ REGSAM samDesired,
6416     _In_ ULONG ulHardwareProfile,
6417     _In_ REGDISPOSITION Disposition,
6418     _Out_ PHKEY phkDevice,
6419     _In_ ULONG ulFlags,
6420     _In_opt_ HMACHINE hMachine)
6421 {
6422     RPC_BINDING_HANDLE BindingHandle = NULL;
6423     HSTRING_TABLE StringTable = NULL;
6424     LPWSTR pszDevInst, pszKeyPath = NULL, pszInstancePath = NULL;
6425     LONG lError;
6426     DWORD dwDisposition;
6427     HKEY hRootKey = NULL;
6428     CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
6429 
6430     TRACE("CM_Open_DevNode_Key_Ex(%lx %lx %lu %lx %p %lx %p)\n",
6431           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags, hMachine);
6432 
6433     if (phkDevice == NULL)
6434         return CR_INVALID_POINTER;
6435 
6436     *phkDevice = NULL;
6437 
6438     if (dnDevNode == 0)
6439         return CR_INVALID_DEVNODE;
6440 
6441     if (ulFlags & ~CM_REGISTRY_BITS)
6442         return CR_INVALID_FLAG;
6443 
6444     if (Disposition & ~RegDisposition_Bits)
6445         return CR_INVALID_DATA;
6446 
6447     if (hMachine != NULL)
6448     {
6449         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6450         if (BindingHandle == NULL)
6451             return CR_FAILURE;
6452 
6453         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6454         if (StringTable == 0)
6455             return CR_FAILURE;
6456     }
6457     else
6458     {
6459         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6460             return CR_FAILURE;
6461     }
6462 
6463     pszDevInst = pSetupStringTableStringFromId(StringTable, dnDevNode);
6464     if (pszDevInst == NULL)
6465         return CR_INVALID_DEVNODE;
6466 
6467     TRACE("pszDevInst: %S\n", pszDevInst);
6468 
6469     pszKeyPath = MyMalloc(512 * sizeof(WCHAR));
6470     if (pszKeyPath == NULL)
6471     {
6472         ret = CR_OUT_OF_MEMORY;
6473         goto done;
6474     }
6475 
6476     pszInstancePath = MyMalloc(512 * sizeof(WCHAR));
6477     if (pszInstancePath == NULL)
6478     {
6479         ret = CR_OUT_OF_MEMORY;
6480         goto done;
6481     }
6482 
6483     ret = GetDeviceInstanceKeyPath(BindingHandle,
6484                                    pszDevInst,
6485                                    pszKeyPath,
6486                                    pszInstancePath,
6487                                    ulHardwareProfile,
6488                                    ulFlags);
6489     if (ret != CR_SUCCESS)
6490         goto done;
6491 
6492     TRACE("pszKeyPath: %S\n", pszKeyPath);
6493     TRACE("pszInstancePath: %S\n", pszInstancePath);
6494 
6495     wcscat(pszKeyPath, L"\\");
6496     wcscat(pszKeyPath, pszInstancePath);
6497 
6498     TRACE("pszKeyPath: %S\n", pszKeyPath);
6499 
6500     if (hMachine == NULL)
6501     {
6502         hRootKey = HKEY_LOCAL_MACHINE;
6503     }
6504     else
6505     {
6506         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6507                                 HKEY_LOCAL_MACHINE,
6508                                 &hRootKey))
6509         {
6510             ret = CR_REGISTRY_ERROR;
6511             goto done;
6512         }
6513     }
6514 
6515     if (Disposition == RegDisposition_OpenAlways)
6516     {
6517         lError = RegCreateKeyExW(hRootKey,
6518                                  pszKeyPath,
6519                                  0,
6520                                  NULL,
6521                                  0,
6522                                  samDesired,
6523                                  NULL,
6524                                  phkDevice,
6525                                  &dwDisposition);
6526     }
6527     else
6528     {
6529         lError = RegOpenKeyExW(hRootKey,
6530                                pszKeyPath,
6531                                0,
6532                                samDesired,
6533                                phkDevice);
6534     }
6535 
6536     if (lError != ERROR_SUCCESS)
6537     {
6538         *phkDevice = NULL;
6539         ret = CR_NO_SUCH_REGISTRY_KEY;
6540     }
6541 
6542 done:
6543     if ((hRootKey != NULL) && (hRootKey != HKEY_LOCAL_MACHINE))
6544         RegCloseKey(hRootKey);
6545 
6546     if (pszInstancePath != NULL)
6547         MyFree(pszInstancePath);
6548 
6549     if (pszKeyPath != NULL)
6550         MyFree(pszKeyPath);
6551 
6552     return ret;
6553 }
6554 
6555 
6556 /***********************************************************************
6557  * CM_Query_And_Remove_SubTreeA [SETUPAPI.@]
6558  */
6559 CONFIGRET
6560 WINAPI
6561 CM_Query_And_Remove_SubTreeA(
6562     _In_ DEVINST dnAncestor,
6563     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6564     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6565     _In_ ULONG ulNameLength,
6566     _In_ ULONG ulFlags)
6567 {
6568     TRACE("CM_Query_And_Remove_SubTreeA(%lx %p %p %lu %lx)\n",
6569           dnAncestor, pVetoType, pszVetoName, ulNameLength, ulFlags);
6570 
6571     return CM_Query_And_Remove_SubTree_ExA(dnAncestor, pVetoType, pszVetoName,
6572                                            ulNameLength, ulFlags, NULL);
6573 }
6574 
6575 
6576 /***********************************************************************
6577  * CM_Query_And_Remove_SubTreeW [SETUPAPI.@]
6578  */
6579 CONFIGRET
6580 WINAPI
6581 CM_Query_And_Remove_SubTreeW(
6582     _In_ DEVINST dnAncestor,
6583     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6584     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6585     _In_ ULONG ulNameLength,
6586     _In_ ULONG ulFlags)
6587 {
6588     TRACE("CM_Query_And_Remove_SubTreeW(%lx %p %p %lu %lx)\n",
6589           dnAncestor, pVetoType, pszVetoName, ulNameLength, ulFlags);
6590 
6591     return CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, pszVetoName,
6592                                            ulNameLength, ulFlags, NULL);
6593 }
6594 
6595 
6596 /***********************************************************************
6597  * CM_Query_And_Remove_SubTree_ExA [SETUPAPI.@]
6598  */
6599 CONFIGRET
6600 WINAPI
6601 CM_Query_And_Remove_SubTree_ExA(
6602     _In_ DEVINST dnAncestor,
6603     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6604     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6605     _In_ ULONG ulNameLength,
6606     _In_ ULONG ulFlags,
6607     _In_opt_ HMACHINE hMachine)
6608 {
6609     LPWSTR lpLocalVetoName;
6610     CONFIGRET ret;
6611 
6612     TRACE("CM_Query_And_Remove_SubTree_ExA(%lx %p %p %lu %lx %p)\n",
6613           dnAncestor, pVetoType, pszVetoName, ulNameLength,
6614           ulFlags, hMachine);
6615 
6616     if (pszVetoName == NULL && ulNameLength == 0)
6617         return CR_INVALID_POINTER;
6618 
6619     lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
6620     if (lpLocalVetoName == NULL)
6621         return CR_OUT_OF_MEMORY;
6622 
6623     ret = CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, lpLocalVetoName,
6624                                           ulNameLength, ulFlags, hMachine);
6625     if (ret == CR_REMOVE_VETOED)
6626     {
6627         if (WideCharToMultiByte(CP_ACP,
6628                                 0,
6629                                 lpLocalVetoName,
6630                                 ulNameLength,
6631                                 pszVetoName,
6632                                 ulNameLength,
6633                                 NULL,
6634                                 NULL) == 0)
6635             ret = CR_FAILURE;
6636     }
6637 
6638     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
6639 
6640     return ret;
6641 }
6642 
6643 
6644 /***********************************************************************
6645  * CM_Query_And_Remove_SubTree_ExW [SETUPAPI.@]
6646  */
6647 CONFIGRET
6648 WINAPI
6649 CM_Query_And_Remove_SubTree_ExW(
6650     _In_ DEVINST dnAncestor,
6651     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6652     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6653     _In_ ULONG ulNameLength,
6654     _In_ ULONG ulFlags,
6655     _In_opt_ HMACHINE hMachine)
6656 {
6657     RPC_BINDING_HANDLE BindingHandle = NULL;
6658     HSTRING_TABLE StringTable = NULL;
6659     LPWSTR lpDevInst;
6660     CONFIGRET ret;
6661 
6662     TRACE("CM_Query_And_Remove_SubTree_ExW(%lx %p %p %lu %lx %p)\n",
6663           dnAncestor, pVetoType, pszVetoName, ulNameLength,
6664           ulFlags, hMachine);
6665 
6666     if (dnAncestor == 0)
6667         return CR_INVALID_DEVNODE;
6668 
6669     if (ulFlags & ~CM_REMOVE_BITS)
6670         return CR_INVALID_FLAG;
6671 
6672     if (pszVetoName == NULL && ulNameLength == 0)
6673         return CR_INVALID_POINTER;
6674 
6675     if (hMachine != NULL)
6676     {
6677         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6678         if (BindingHandle == NULL)
6679             return CR_FAILURE;
6680 
6681         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6682         if (StringTable == 0)
6683             return CR_FAILURE;
6684     }
6685     else
6686     {
6687         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6688             return CR_FAILURE;
6689     }
6690 
6691     lpDevInst = pSetupStringTableStringFromId(StringTable, dnAncestor);
6692     if (lpDevInst == NULL)
6693         return CR_INVALID_DEVNODE;
6694 
6695     RpcTryExcept
6696     {
6697         ret = PNP_QueryRemove(BindingHandle,
6698                               lpDevInst,
6699                               pVetoType,
6700                               pszVetoName,
6701                               ulNameLength,
6702                               ulFlags);
6703     }
6704     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6705     {
6706         ret = RpcStatusToCmStatus(RpcExceptionCode());
6707     }
6708     RpcEndExcept;
6709 
6710     return ret;
6711 }
6712 
6713 
6714 /***********************************************************************
6715  * CM_Query_Arbitrator_Free_Data [SETUPAPI.@]
6716  */
6717 CONFIGRET
6718 WINAPI
6719 CM_Query_Arbitrator_Free_Data(
6720     _Out_writes_bytes_(DataLen) PVOID pData,
6721     _In_ ULONG DataLen,
6722     _In_ DEVINST dnDevInst,
6723     _In_ RESOURCEID ResourceID,
6724     _In_ ULONG ulFlags)
6725 {
6726     TRACE("CM_Query_Arbitrator_Free_Data(%p %lu %lx %lu 0x%08lx)\n",
6727           pData, DataLen, dnDevInst, ResourceID, ulFlags);
6728 
6729     return CM_Query_Arbitrator_Free_Data_Ex(pData, DataLen, dnDevInst,
6730                                             ResourceID, ulFlags, NULL);
6731 }
6732 
6733 
6734 /***********************************************************************
6735  * CM_Query_Arbitrator_Free_Data_Ex [SETUPAPI.@]
6736  */
6737 CONFIGRET
6738 WINAPI
6739 CM_Query_Arbitrator_Free_Data_Ex(
6740     _Out_writes_bytes_(DataLen) PVOID pData,
6741     _In_ ULONG DataLen,
6742     _In_ DEVINST dnDevInst,
6743     _In_ RESOURCEID ResourceID,
6744     _In_ ULONG ulFlags,
6745     _In_opt_ HMACHINE hMachine)
6746 {
6747     RPC_BINDING_HANDLE BindingHandle = NULL;
6748     HSTRING_TABLE StringTable = NULL;
6749     LPWSTR lpDevInst;
6750     CONFIGRET ret;
6751 
6752     TRACE("CM_Query_Arbitrator_Free_Data_Ex(%p %lu %lx %lu 0x%08lx %p)\n",
6753           pData, DataLen, dnDevInst, ResourceID, ulFlags, hMachine);
6754 
6755     if (pData == NULL || DataLen == 0)
6756         return CR_INVALID_POINTER;
6757 
6758     if (dnDevInst == 0)
6759         return CR_INVALID_DEVINST;
6760 
6761     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6762         return CR_INVALID_FLAG;
6763 
6764     if (hMachine != NULL)
6765     {
6766         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6767         if (BindingHandle == NULL)
6768             return CR_FAILURE;
6769 
6770         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6771         if (StringTable == 0)
6772             return CR_FAILURE;
6773     }
6774     else
6775     {
6776         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6777             return CR_FAILURE;
6778     }
6779 
6780     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6781     if (lpDevInst == NULL)
6782         return CR_INVALID_DEVNODE;
6783 
6784     RpcTryExcept
6785     {
6786         ret = PNP_QueryArbitratorFreeData(BindingHandle,
6787                                           pData,
6788                                           DataLen,
6789                                           lpDevInst,
6790                                           ResourceID,
6791                                           ulFlags);
6792     }
6793     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6794     {
6795         ret = RpcStatusToCmStatus(RpcExceptionCode());
6796     }
6797     RpcEndExcept;
6798 
6799     return ret;
6800 }
6801 
6802 
6803 /***********************************************************************
6804  * CM_Query_Arbitrator_Free_Size [SETUPAPI.@]
6805  */
6806 CONFIGRET
6807 WINAPI
6808 CM_Query_Arbitrator_Free_Size(
6809     _Out_ PULONG pulSize,
6810     _In_ DEVINST dnDevInst,
6811     _In_ RESOURCEID ResourceID,
6812     _In_ ULONG ulFlags)
6813 {
6814     TRACE("CM_Query_Arbitrator_Free_Size(%p %lu %lx 0x%08lx)\n",
6815           pulSize, dnDevInst,ResourceID, ulFlags);
6816 
6817     return CM_Query_Arbitrator_Free_Size_Ex(pulSize, dnDevInst, ResourceID,
6818                                             ulFlags, NULL);
6819 }
6820 
6821 
6822 /***********************************************************************
6823  * CM_Query_Arbitrator_Free_Size_Ex [SETUPAPI.@]
6824  */
6825 CONFIGRET
6826 WINAPI
6827 CM_Query_Arbitrator_Free_Size_Ex(
6828     _Out_ PULONG pulSize,
6829     _In_ DEVINST dnDevInst,
6830     _In_ RESOURCEID ResourceID,
6831     _In_ ULONG ulFlags,
6832     _In_opt_ HMACHINE hMachine)
6833 {
6834     RPC_BINDING_HANDLE BindingHandle = NULL;
6835     HSTRING_TABLE StringTable = NULL;
6836     LPWSTR lpDevInst;
6837     CONFIGRET ret;
6838 
6839     TRACE("CM_Query_Arbitrator_Free_Size_Ex(%p %lu %lx 0x%08lx %p)\n",
6840           pulSize, dnDevInst,ResourceID, ulFlags, hMachine);
6841 
6842     if (pulSize == NULL)
6843         return CR_INVALID_POINTER;
6844 
6845     if (dnDevInst == 0)
6846         return CR_INVALID_DEVINST;
6847 
6848     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6849         return CR_INVALID_FLAG;
6850 
6851     if (hMachine != NULL)
6852     {
6853         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6854         if (BindingHandle == NULL)
6855             return CR_FAILURE;
6856 
6857         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6858         if (StringTable == 0)
6859             return CR_FAILURE;
6860     }
6861     else
6862     {
6863         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6864             return CR_FAILURE;
6865     }
6866 
6867     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6868     if (lpDevInst == NULL)
6869         return CR_INVALID_DEVNODE;
6870 
6871     RpcTryExcept
6872     {
6873         ret = PNP_QueryArbitratorFreeSize(BindingHandle,
6874                                           pulSize,
6875                                           lpDevInst,
6876                                           ResourceID,
6877                                           ulFlags);
6878     }
6879     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6880     {
6881         ret = RpcStatusToCmStatus(RpcExceptionCode());
6882     }
6883     RpcEndExcept;
6884 
6885     return ret;
6886 }
6887 
6888 
6889 /***********************************************************************
6890  * CM_Query_Remove_SubTree [SETUPAPI.@]
6891  *
6892  * This function is obsolete in Windows XP and above.
6893  */
6894 CONFIGRET
6895 WINAPI
6896 CM_Query_Remove_SubTree(
6897     _In_ DEVINST dnAncestor,
6898     _In_ ULONG ulFlags)
6899 {
6900     TRACE("CM_Query_Remove_SubTree(%lx %lx)\n",
6901           dnAncestor, ulFlags);
6902 
6903     return CR_CALL_NOT_IMPLEMENTED;
6904 }
6905 
6906 
6907 /***********************************************************************
6908  * CM_Query_Remove_SubTree_Ex [SETUPAPI.@]
6909  *
6910  * This function is obsolete in Windows XP and above.
6911  */
6912 CONFIGRET
6913 WINAPI
6914 CM_Query_Remove_SubTree_Ex(
6915     _In_ DEVINST dnAncestor,
6916     _In_ ULONG ulFlags,
6917     _In_opt_ HMACHINE hMachine)
6918 {
6919     TRACE("CM_Query_Remove_SubTree_Ex(%lx %lx %p)\n",
6920           dnAncestor, ulFlags, hMachine);
6921 
6922     return CR_CALL_NOT_IMPLEMENTED;
6923 }
6924 
6925 
6926 /***********************************************************************
6927  * CM_Query_Resource_Conflict_List [SETUPAPI.@]
6928  */
6929 CONFIGRET
6930 WINAPI
6931 CM_Query_Resource_Conflict_List(
6932     _Out_ PCONFLICT_LIST pclConflictList,
6933     _In_ DEVINST dnDevInst,
6934     _In_ RESOURCEID ResourceID,
6935     _In_ PCVOID ResourceData,
6936     _In_ ULONG ResourceLen,
6937     _In_ ULONG ulFlags,
6938     _In_opt_ HMACHINE hMachine)
6939 {
6940     RPC_BINDING_HANDLE BindingHandle = NULL;
6941     HSTRING_TABLE StringTable = NULL;
6942     PPNP_CONFLICT_LIST pConflictBuffer = NULL;
6943     PCONFLICT_DATA pConflictData = NULL;
6944     ULONG ulBufferLength;
6945     LPWSTR lpDevInst;
6946     CONFIGRET ret;
6947 
6948     FIXME("CM_Query_Resource_Conflict_List(%p %lx %lu %p %lu %lx %p)\n",
6949           pclConflictList, dnDevInst, ResourceID, ResourceData,
6950           ResourceLen, ulFlags, hMachine);
6951 
6952     if (dnDevInst == 0)
6953         return CR_INVALID_DEVNODE;
6954 
6955     if (ulFlags & ~CM_RESDES_WIDTH_BITS)
6956         return CR_INVALID_FLAG;
6957 
6958     if (pclConflictList == NULL ||
6959         ResourceData == NULL ||
6960         ResourceLen == 0)
6961         return CR_INVALID_POINTER;
6962 
6963     if (ResourceID == 0)
6964         return CR_INVALID_RESOURCEID;
6965 
6966     *pclConflictList = 0;
6967 
6968     if (hMachine != NULL)
6969     {
6970         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6971         if (BindingHandle == NULL)
6972             return CR_FAILURE;
6973 
6974         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6975         if (StringTable == 0)
6976             return CR_FAILURE;
6977     }
6978     else
6979     {
6980         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6981             return CR_FAILURE;
6982     }
6983 
6984     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6985     if (lpDevInst == NULL)
6986         return CR_INVALID_DEVNODE;
6987 
6988     pConflictData = MyMalloc(sizeof(CONFLICT_DATA));
6989     if (pConflictData == NULL)
6990     {
6991         ret = CR_OUT_OF_MEMORY;
6992         goto done;
6993     }
6994 
6995     ulBufferLength = sizeof(PNP_CONFLICT_LIST) +
6996                      sizeof(PNP_CONFLICT_STRINGS) +
6997                      (sizeof(wchar_t) * 200);
6998     pConflictBuffer = MyMalloc(ulBufferLength);
6999     if (pConflictBuffer == NULL)
7000     {
7001         ret = CR_OUT_OF_MEMORY;
7002         goto done;
7003     }
7004 
7005     RpcTryExcept
7006     {
7007         ret = PNP_QueryResConfList(BindingHandle,
7008                                    lpDevInst,
7009                                    ResourceID,
7010                                    (PBYTE)ResourceData,
7011                                    ResourceLen,
7012                                    (PBYTE)pConflictBuffer,
7013                                    ulBufferLength,
7014                                    ulFlags);
7015     }
7016     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7017     {
7018         ret = RpcStatusToCmStatus(RpcExceptionCode());
7019     }
7020     RpcEndExcept;
7021 
7022     if (ret != CR_SUCCESS)
7023         goto done;
7024 
7025     pConflictData->ulMagic = CONFLICT_MAGIC;
7026     pConflictData->pConflictList = pConflictBuffer;
7027 
7028     *pclConflictList = (CONFLICT_LIST)pConflictData;
7029 
7030 done:
7031     if (ret != CR_SUCCESS)
7032     {
7033         if (pConflictBuffer != NULL)
7034             MyFree(pConflictBuffer);
7035 
7036         if (pConflictData != NULL)
7037             MyFree(pConflictData);
7038     }
7039 
7040     return ret;
7041 }
7042 
7043 
7044 /***********************************************************************
7045  * CM_Reenumerate_DevNode [SETUPAPI.@]
7046  */
7047 CONFIGRET
7048 WINAPI
7049 CM_Reenumerate_DevNode(
7050     _In_ DEVINST dnDevInst,
7051     _In_ ULONG ulFlags)
7052 {
7053     TRACE("CM_Reenumerate_DevNode(%lx %lx)\n",
7054           dnDevInst, ulFlags);
7055 
7056     return CM_Reenumerate_DevNode_Ex(dnDevInst, ulFlags, NULL);
7057 }
7058 
7059 
7060 /***********************************************************************
7061  * CM_Reenumerate_DevNode_Ex [SETUPAPI.@]
7062  */
7063 CONFIGRET WINAPI
7064 CM_Reenumerate_DevNode_Ex(
7065     _In_ DEVINST dnDevInst,
7066     _In_ ULONG ulFlags,
7067     _In_opt_ HMACHINE hMachine)
7068 {
7069     RPC_BINDING_HANDLE BindingHandle = NULL;
7070     HSTRING_TABLE StringTable = NULL;
7071     LPWSTR lpDevInst;
7072     CONFIGRET ret;
7073 
7074     FIXME("CM_Reenumerate_DevNode_Ex(%lx %lx %p)\n",
7075           dnDevInst, ulFlags, hMachine);
7076 
7077     if (dnDevInst == 0)
7078         return CR_INVALID_DEVNODE;
7079 
7080     if (ulFlags & ~CM_REENUMERATE_BITS)
7081         return CR_INVALID_FLAG;
7082 
7083     if (hMachine != NULL)
7084     {
7085         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7086         if (BindingHandle == NULL)
7087             return CR_FAILURE;
7088 
7089         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7090         if (StringTable == 0)
7091             return CR_FAILURE;
7092     }
7093     else
7094     {
7095         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7096             return CR_FAILURE;
7097     }
7098 
7099     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7100     if (lpDevInst == NULL)
7101         return CR_INVALID_DEVNODE;
7102 
7103     RpcTryExcept
7104     {
7105         ret = PNP_DeviceInstanceAction(BindingHandle,
7106                                        PNP_DEVINST_REENUMERATE,
7107                                        ulFlags,
7108                                        lpDevInst,
7109                                        NULL);
7110     }
7111     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7112     {
7113         ret = RpcStatusToCmStatus(RpcExceptionCode());
7114     }
7115     RpcEndExcept;
7116 
7117     return ret;
7118 }
7119 
7120 
7121 /***********************************************************************
7122  * CM_Register_Device_Driver [SETUPAPI.@]
7123  */
7124 CONFIGRET
7125 WINAPI
7126 CM_Register_Device_Driver(
7127     _In_ DEVINST dnDevInst,
7128     _In_ ULONG ulFlags)
7129 {
7130     TRACE("CM_Register_Device_Driver(%lx 0x%08lx)\n",
7131           dnDevInst, ulFlags);
7132 
7133     return CM_Register_Device_Driver_Ex(dnDevInst, ulFlags, NULL);
7134 }
7135 
7136 
7137 /***********************************************************************
7138  * CM_Register_Device_Driver_Ex [SETUPAPI.@]
7139  */
7140 CONFIGRET
7141 WINAPI
7142 CM_Register_Device_Driver_Ex(
7143     _In_ DEVINST dnDevInst,
7144     _In_ ULONG ulFlags,
7145     _In_opt_ HMACHINE hMachine)
7146 {
7147     RPC_BINDING_HANDLE BindingHandle = NULL;
7148     HSTRING_TABLE StringTable = NULL;
7149     LPWSTR lpDevInst;
7150     CONFIGRET ret;
7151 
7152     TRACE("CM_Register_Device_Driver_Ex(%lx 0x%08lx %p)\n",
7153           dnDevInst, ulFlags, hMachine);
7154 
7155     if (dnDevInst == 0)
7156         return CR_INVALID_DEVNODE;
7157 
7158     if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
7159         return CR_INVALID_FLAG;
7160 
7161     if (hMachine != NULL)
7162     {
7163         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7164         if (BindingHandle == NULL)
7165             return CR_FAILURE;
7166 
7167         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7168         if (StringTable == 0)
7169             return CR_FAILURE;
7170     }
7171     else
7172     {
7173         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7174             return CR_FAILURE;
7175     }
7176 
7177     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7178     if (lpDevInst == NULL)
7179         return CR_INVALID_DEVNODE;
7180 
7181     RpcTryExcept
7182     {
7183         ret = PNP_RegisterDriver(BindingHandle,
7184                                  lpDevInst,
7185                                  ulFlags);
7186     }
7187     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7188     {
7189         ret = RpcStatusToCmStatus(RpcExceptionCode());
7190     }
7191     RpcEndExcept;
7192 
7193     return ret;
7194 }
7195 
7196 
7197 /***********************************************************************
7198  * CM_Register_Device_InterfaceA [SETUPAPI.@]
7199  */
7200 CONFIGRET
7201 WINAPI
7202 CM_Register_Device_InterfaceA(
7203     _In_ DEVINST dnDevInst,
7204     _In_ LPGUID InterfaceClassGuid,
7205     _In_opt_ LPCSTR pszReference,
7206     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
7207     _Inout_ PULONG pulLength,
7208     _In_ ULONG ulFlags)
7209 {
7210     TRACE("CM_Register_Device_InterfaceA(%lx %s %s %p %p %lx)\n",
7211           dnDevInst, debugstr_guid(InterfaceClassGuid),
7212           pszReference, pszDeviceInterface, pulLength, ulFlags);
7213 
7214     return CM_Register_Device_Interface_ExA(dnDevInst, InterfaceClassGuid,
7215                                             pszReference, pszDeviceInterface,
7216                                             pulLength, ulFlags, NULL);
7217 }
7218 
7219 
7220 /***********************************************************************
7221  * CM_Register_Device_InterfaceW [SETUPAPI.@]
7222  */
7223 CONFIGRET
7224 WINAPI
7225 CM_Register_Device_InterfaceW(
7226     _In_ DEVINST dnDevInst,
7227     _In_ LPGUID InterfaceClassGuid,
7228     _In_opt_ LPCWSTR pszReference,
7229     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
7230     _Inout_ PULONG pulLength,
7231     _In_ ULONG ulFlags)
7232 {
7233     TRACE("CM_Register_Device_InterfaceW(%lx %s %s %p %p %lx)\n",
7234           dnDevInst, debugstr_guid(InterfaceClassGuid),
7235           debugstr_w(pszReference), pszDeviceInterface, pulLength, ulFlags);
7236 
7237     return CM_Register_Device_Interface_ExW(dnDevInst, InterfaceClassGuid,
7238                                             pszReference, pszDeviceInterface,
7239                                             pulLength, ulFlags, NULL);
7240 }
7241 
7242 
7243 /***********************************************************************
7244  * CM_Register_Device_Interface_ExA [SETUPAPI.@]
7245  */
7246 CONFIGRET
7247 WINAPI
7248 CM_Register_Device_Interface_ExA(
7249     _In_ DEVINST dnDevInst,
7250     _In_ LPGUID InterfaceClassGuid,
7251     _In_opt_ LPCSTR pszReference,
7252     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
7253     _Inout_ PULONG pulLength,
7254     _In_ ULONG ulFlags,
7255     _In_opt_ HMACHINE hMachine)
7256 {
7257     LPWSTR pszReferenceW = NULL;
7258     LPWSTR pszDeviceInterfaceW;
7259     ULONG ulLength;
7260     CONFIGRET ret;
7261 
7262     TRACE("CM_Register_Device_Interface_ExA(%lx %s %s %p %p %lx %p)\n",
7263           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_a(pszReference),
7264           pszDeviceInterface, pulLength, ulFlags, hMachine);
7265 
7266     if (pulLength == NULL || pszDeviceInterface == NULL)
7267         return CR_INVALID_POINTER;
7268 
7269     if (pszReference != NULL)
7270     {
7271         if (pSetupCaptureAndConvertAnsiArg(pszReference, &pszReferenceW))
7272             return CR_INVALID_DATA;
7273     }
7274 
7275     ulLength = *pulLength;
7276 
7277     pszDeviceInterfaceW = HeapAlloc(GetProcessHeap(), 0, ulLength * sizeof(WCHAR));
7278     if (pszDeviceInterfaceW == NULL)
7279     {
7280         ret = CR_OUT_OF_MEMORY;
7281         goto Done;
7282     }
7283 
7284     ret = CM_Register_Device_Interface_ExW(dnDevInst,
7285                                            InterfaceClassGuid,
7286                                            pszReferenceW,
7287                                            pszDeviceInterfaceW,
7288                                            &ulLength,
7289                                            ulFlags,
7290                                            hMachine);
7291     if (ret == CR_SUCCESS)
7292     {
7293         if (WideCharToMultiByte(CP_ACP,
7294                                 0,
7295                                 pszDeviceInterfaceW,
7296                                 ulLength,
7297                                 pszDeviceInterface,
7298                                 *pulLength,
7299                                 NULL,
7300                                 NULL) == 0)
7301             ret = CR_FAILURE;
7302     }
7303 
7304     *pulLength = ulLength;
7305 
7306 Done:
7307     if (pszDeviceInterfaceW != NULL)
7308         HeapFree(GetProcessHeap(), 0, pszDeviceInterfaceW);
7309 
7310     if (pszReferenceW != NULL)
7311         MyFree(pszReferenceW);
7312 
7313     return ret;
7314 }
7315 
7316 
7317 /***********************************************************************
7318  * CM_Register_Device_Interface_ExW [SETUPAPI.@]
7319  */
7320 CONFIGRET
7321 WINAPI
7322 CM_Register_Device_Interface_ExW(
7323     _In_ DEVINST dnDevInst,
7324     _In_ LPGUID InterfaceClassGuid,
7325     _In_opt_ LPCWSTR pszReference,
7326     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
7327     _Inout_ PULONG pulLength,
7328     _In_ ULONG ulFlags,
7329     _In_opt_ HMACHINE hMachine)
7330 {
7331     RPC_BINDING_HANDLE BindingHandle = NULL;
7332     HSTRING_TABLE StringTable = NULL;
7333     LPWSTR lpDevInst;
7334     ULONG ulTransferLength;
7335     CONFIGRET ret;
7336 
7337     TRACE("CM_Register_Device_Interface_ExW(%lx %s %s %p %p %lx %p)\n",
7338           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_w(pszReference),
7339           pszDeviceInterface, pulLength, ulFlags, hMachine);
7340 
7341     if (dnDevInst == 0)
7342         return CR_INVALID_DEVNODE;
7343 
7344     if (InterfaceClassGuid == NULL ||
7345         pszDeviceInterface == NULL ||
7346         pulLength == NULL)
7347         return CR_INVALID_POINTER;
7348 
7349     if (ulFlags != 0)
7350         return CR_INVALID_FLAG;
7351 
7352     if (hMachine != NULL)
7353     {
7354         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7355         if (BindingHandle == NULL)
7356             return CR_FAILURE;
7357 
7358         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7359         if (StringTable == 0)
7360             return CR_FAILURE;
7361     }
7362     else
7363     {
7364         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7365             return CR_FAILURE;
7366     }
7367 
7368     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7369     if (lpDevInst == NULL)
7370         return CR_INVALID_DEVNODE;
7371 
7372     ulTransferLength = *pulLength;
7373 
7374     RpcTryExcept
7375     {
7376         ret = PNP_RegisterDeviceClassAssociation(BindingHandle,
7377                                                  lpDevInst,
7378                                                  InterfaceClassGuid,
7379                                                  (LPWSTR)pszReference,
7380                                                  pszDeviceInterface,
7381                                                  pulLength,
7382                                                  &ulTransferLength,
7383                                                  0);
7384     }
7385     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7386     {
7387         ret = RpcStatusToCmStatus(RpcExceptionCode());
7388     }
7389     RpcEndExcept;
7390 
7391     return ret;
7392 }
7393 
7394 
7395 /***********************************************************************
7396  * CM_Remove_SubTree [SETUPAPI.@]
7397  *
7398  * This function is obsolete in Windows XP and above.
7399  */
7400 CONFIGRET
7401 WINAPI
7402 CM_Remove_SubTree(
7403     _In_ DEVINST dnAncestor,
7404     _In_ ULONG ulFlags)
7405 {
7406     TRACE("CM_Remove_SubTree(%lx %lx)\n",
7407           dnAncestor, ulFlags);
7408 
7409     return CR_CALL_NOT_IMPLEMENTED;
7410 }
7411 
7412 
7413 /***********************************************************************
7414  * CM_Remove_SubTree_Ex [SETUPAPI.@]
7415  *
7416  * This function is obsolete in Windows XP and above.
7417  */
7418 CONFIGRET
7419 WINAPI
7420 CM_Remove_SubTree_Ex(
7421     _In_ DEVINST dnAncestor,
7422     _In_ ULONG ulFlags,
7423     _In_opt_ HMACHINE hMachine)
7424 {
7425     TRACE("CM_Remove_SubTree_Ex(%lx %lx %p)\n",
7426           dnAncestor, ulFlags, hMachine);
7427 
7428     return CR_CALL_NOT_IMPLEMENTED;
7429 }
7430 
7431 
7432 /***********************************************************************
7433  * CM_Request_Device_EjectA [SETUPAPI.@]
7434  */
7435 CONFIGRET
7436 WINAPI
7437 CM_Request_Device_EjectA(
7438     _In_ DEVINST dnDevInst,
7439     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7440     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7441     _In_ ULONG ulNameLength,
7442     _In_ ULONG ulFlags)
7443 {
7444     TRACE("CM_Request_Device_EjectA(%lx %p %p %lu %lx)\n",
7445           dnDevInst, pVetoType, pszVetoName, ulNameLength, ulFlags);
7446 
7447     return CM_Request_Device_Eject_ExA(dnDevInst, pVetoType, pszVetoName,
7448                                        ulNameLength, ulFlags, NULL);
7449 }
7450 
7451 
7452 /***********************************************************************
7453  * CM_Request_Device_EjectW [SETUPAPI.@]
7454  */
7455 CONFIGRET
7456 WINAPI
7457 CM_Request_Device_EjectW(
7458     _In_ DEVINST dnDevInst,
7459     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7460     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7461     _In_ ULONG ulNameLength,
7462     _In_ ULONG ulFlags)
7463 {
7464     TRACE("CM_Request_Device_EjectW(%lx %p %p %lu %lx)\n",
7465           dnDevInst, pVetoType, pszVetoName, ulNameLength, ulFlags);
7466 
7467     return CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, pszVetoName,
7468                                        ulNameLength, ulFlags, NULL);
7469 }
7470 
7471 
7472 /***********************************************************************
7473  * CM_Request_Device_Eject_ExA [SETUPAPI.@]
7474  */
7475 CONFIGRET
7476 WINAPI
7477 CM_Request_Device_Eject_ExA(
7478     _In_ DEVINST dnDevInst,
7479     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7480     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7481     _In_ ULONG ulNameLength,
7482     _In_ ULONG ulFlags,
7483     _In_opt_ HMACHINE hMachine)
7484 {
7485     LPWSTR lpLocalVetoName = NULL;
7486     CONFIGRET ret;
7487 
7488     TRACE("CM_Request_Device_Eject_ExA(%lx %p %p %lu %lx %p)\n",
7489           dnDevInst, pVetoType, pszVetoName, ulNameLength, ulFlags, hMachine);
7490 
7491     if (ulNameLength != 0)
7492     {
7493         if (pszVetoName == NULL)
7494             return CR_INVALID_POINTER;
7495 
7496         lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
7497         if (lpLocalVetoName == NULL)
7498             return CR_OUT_OF_MEMORY;
7499     }
7500 
7501     ret = CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, lpLocalVetoName,
7502                                       ulNameLength, ulFlags, hMachine);
7503     if (ret == CR_REMOVE_VETOED && ulNameLength != 0)
7504     {
7505         if (WideCharToMultiByte(CP_ACP,
7506                                 0,
7507                                 lpLocalVetoName,
7508                                 ulNameLength,
7509                                 pszVetoName,
7510                                 ulNameLength,
7511                                 NULL,
7512                                 NULL) == 0)
7513             ret = CR_FAILURE;
7514     }
7515 
7516     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
7517 
7518     return ret;
7519 }
7520 
7521 
7522 /***********************************************************************
7523  * CM_Request_Device_Eject_ExW [SETUPAPI.@]
7524  */
7525 CONFIGRET
7526 WINAPI
7527 CM_Request_Device_Eject_ExW(
7528     _In_ DEVINST dnDevInst,
7529     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7530     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7531     _In_ ULONG ulNameLength,
7532     _In_ ULONG ulFlags,
7533     _In_opt_ HMACHINE hMachine)
7534 {
7535     RPC_BINDING_HANDLE BindingHandle = NULL;
7536     HSTRING_TABLE StringTable = NULL;
7537     LPWSTR lpDevInst;
7538     CONFIGRET ret;
7539 
7540     TRACE("CM_Request_Device_Eject_ExW(%lx %p %p %lu %lx %p)\n",
7541           dnDevInst, pVetoType, pszVetoName, ulNameLength, ulFlags, hMachine);
7542 
7543     if (dnDevInst == 0)
7544         return CR_INVALID_DEVNODE;
7545 
7546     if (ulFlags != 0)
7547         return CR_INVALID_FLAG;
7548 
7549     if (pszVetoName == NULL && ulNameLength != 0)
7550         return CR_INVALID_POINTER;
7551 
7552     /* Windows 2003 SP2 ignores pszVetoName when ulNameLength is zero
7553      * and behaves like when pszVetoName is NULL */
7554     if (ulNameLength == 0)
7555         pszVetoName = NULL;
7556 
7557     if (hMachine != NULL)
7558     {
7559         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7560         if (BindingHandle == NULL)
7561             return CR_FAILURE;
7562 
7563         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7564         if (StringTable == 0)
7565             return CR_FAILURE;
7566     }
7567     else
7568     {
7569         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7570             return CR_FAILURE;
7571     }
7572 
7573     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7574     if (lpDevInst == NULL)
7575         return CR_INVALID_DEVNODE;
7576 
7577     RpcTryExcept
7578     {
7579         ret = PNP_RequestDeviceEject(BindingHandle,
7580                                      lpDevInst,
7581                                      pVetoType,
7582                                      pszVetoName,
7583                                      ulNameLength,
7584                                      ulFlags);
7585     }
7586     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7587     {
7588         ret = RpcStatusToCmStatus(RpcExceptionCode());
7589     }
7590     RpcEndExcept;
7591 
7592     return ret;
7593 }
7594 
7595 
7596 /***********************************************************************
7597  * CM_Request_Eject_PC [SETUPAPI.@]
7598  */
7599 CONFIGRET
7600 WINAPI
7601 CM_Request_Eject_PC(VOID)
7602 {
7603     TRACE("CM_Request_Eject_PC()\n");
7604 
7605     return CM_Request_Eject_PC_Ex(NULL);
7606 }
7607 
7608 
7609 /***********************************************************************
7610  * CM_Request_Eject_PC_Ex [SETUPAPI.@]
7611  */
7612 CONFIGRET
7613 WINAPI
7614 CM_Request_Eject_PC_Ex(
7615     _In_opt_ HMACHINE hMachine)
7616 {
7617     RPC_BINDING_HANDLE BindingHandle = NULL;
7618     CONFIGRET ret;
7619 
7620     TRACE("CM_Request_Eject_PC_Ex(%p)\n", hMachine);
7621 
7622     if (hMachine != NULL)
7623     {
7624         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7625         if (BindingHandle == NULL)
7626             return CR_FAILURE;
7627     }
7628     else
7629     {
7630         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7631             return CR_FAILURE;
7632     }
7633 
7634     RpcTryExcept
7635     {
7636         ret = PNP_RequestEjectPC(BindingHandle);
7637     }
7638     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7639     {
7640         ret = RpcStatusToCmStatus(RpcExceptionCode());
7641     }
7642     RpcEndExcept;
7643 
7644     return ret;
7645 }
7646 
7647 
7648 /***********************************************************************
7649  * CM_Run_Detection [SETUPAPI.@]
7650  */
7651 CONFIGRET
7652 WINAPI
7653 CM_Run_Detection(
7654     _In_ ULONG ulFlags)
7655 {
7656     TRACE("CM_Run_Detection(%lx)\n", ulFlags);
7657 
7658     return CM_Run_Detection_Ex(ulFlags, NULL);
7659 }
7660 
7661 
7662 /***********************************************************************
7663  * CM_Run_Detection_Ex [SETUPAPI.@]
7664  */
7665 CONFIGRET
7666 WINAPI
7667 CM_Run_Detection_Ex(
7668     _In_ ULONG ulFlags,
7669     _In_opt_ HMACHINE hMachine)
7670 {
7671     RPC_BINDING_HANDLE BindingHandle = NULL;
7672     CONFIGRET ret;
7673 
7674     TRACE("CM_Run_Detection_Ex(%lx %p)\n",
7675           ulFlags, hMachine);
7676 
7677     if (!pSetupIsUserAdmin())
7678         return CR_ACCESS_DENIED;
7679 
7680     if (ulFlags & ~CM_DETECT_BITS)
7681         return CR_INVALID_FLAG;
7682 
7683     if (hMachine != NULL)
7684     {
7685         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7686         if (BindingHandle == NULL)
7687             return CR_FAILURE;
7688     }
7689     else
7690     {
7691         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7692             return CR_FAILURE;
7693     }
7694 
7695     RpcTryExcept
7696     {
7697         ret = PNP_RunDetection(BindingHandle,
7698                                ulFlags);
7699     }
7700     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7701     {
7702         ret = RpcStatusToCmStatus(RpcExceptionCode());
7703     }
7704     RpcEndExcept;
7705 
7706     return ret;
7707 }
7708 
7709 
7710 /***********************************************************************
7711  * CM_Set_Class_Registry_PropertyA [SETUPAPI.@]
7712  */
7713 CONFIGRET
7714 WINAPI
7715 CM_Set_Class_Registry_PropertyA(
7716     _In_ LPGUID ClassGuid,
7717     _In_ ULONG ulProperty,
7718     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7719     _In_ ULONG ulLength,
7720     _In_ ULONG ulFlags,
7721     _In_opt_ HMACHINE hMachine)
7722 {
7723     FIXME("CM_Set_Class_Registry_PropertyA(%p %lx %p %lu %lx %p)\n",
7724           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7725 
7726     return CR_CALL_NOT_IMPLEMENTED;
7727 }
7728 
7729 
7730 /***********************************************************************
7731  * CM_Set_Class_Registry_PropertyW [SETUPAPI.@]
7732  */
7733 CONFIGRET
7734 WINAPI
7735 CM_Set_Class_Registry_PropertyW(
7736     _In_ LPGUID ClassGuid,
7737     _In_ ULONG ulProperty,
7738     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7739     _In_ ULONG ulLength,
7740     _In_ ULONG ulFlags,
7741     _In_opt_ HMACHINE hMachine)
7742 {
7743     FIXME("CM_Set_Class_Registry_PropertyW(%p %lx %p %lu %lx %p)\n",
7744           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7745 
7746     return CR_CALL_NOT_IMPLEMENTED;
7747 }
7748 
7749 
7750 /***********************************************************************
7751  * CM_Set_DevNode_Problem [SETUPAPI.@]
7752  */
7753 CONFIGRET
7754 WINAPI
7755 CM_Set_DevNode_Problem(
7756     _In_ DEVINST dnDevInst,
7757     _In_ ULONG ulProblem,
7758     _In_ ULONG ulFlags)
7759 {
7760     TRACE("CM_Set_DevNode_Problem(%lx %lx %lx)\n",
7761           dnDevInst, ulProblem, ulFlags);
7762 
7763     return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
7764 }
7765 
7766 
7767 /***********************************************************************
7768  * CM_Set_DevNode_Problem_Ex [SETUPAPI.@]
7769  */
7770 CONFIGRET
7771 WINAPI
7772 CM_Set_DevNode_Problem_Ex(
7773     _In_ DEVINST dnDevInst,
7774     _In_ ULONG ulProblem,
7775     _In_ ULONG ulFlags,
7776     _In_opt_ HMACHINE hMachine)
7777 {
7778     RPC_BINDING_HANDLE BindingHandle = NULL;
7779     HSTRING_TABLE StringTable = NULL;
7780     LPWSTR lpDevInst;
7781     CONFIGRET ret;
7782 
7783     TRACE("CM_Set_DevNode_Problem_Ex(%lx %lx %lx %p)\n",
7784           dnDevInst, ulProblem, ulFlags, hMachine);
7785 
7786     if (dnDevInst == 0)
7787         return CR_INVALID_DEVNODE;
7788 
7789     if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
7790         return CR_INVALID_FLAG;
7791 
7792     if (hMachine != NULL)
7793     {
7794         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7795         if (BindingHandle == NULL)
7796             return CR_FAILURE;
7797 
7798         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7799         if (StringTable == 0)
7800             return CR_FAILURE;
7801     }
7802     else
7803     {
7804         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7805             return CR_FAILURE;
7806     }
7807 
7808     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7809     if (lpDevInst == NULL)
7810         return CR_INVALID_DEVNODE;
7811 
7812     RpcTryExcept
7813     {
7814         ret = PNP_SetDeviceProblem(BindingHandle,
7815                                    lpDevInst,
7816                                    ulProblem,
7817                                    ulFlags);
7818     }
7819     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7820     {
7821         ret = RpcStatusToCmStatus(RpcExceptionCode());
7822     }
7823     RpcEndExcept;
7824 
7825     return ret;
7826 }
7827 
7828 
7829 /***********************************************************************
7830  * CM_Set_DevNode_Registry_PropertyA [SETUPAPI.@]
7831  */
7832 CONFIGRET
7833 WINAPI
7834 CM_Set_DevNode_Registry_PropertyA(
7835   _In_ DEVINST dnDevInst,
7836   _In_ ULONG ulProperty,
7837   _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7838   _In_ ULONG ulLength,
7839   _In_ ULONG ulFlags)
7840 {
7841     TRACE("CM_Set_DevNode_Registry_PropertyA(%lx %lu %p %lx %lx)\n",
7842           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7843 
7844     return CM_Set_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
7845                                                 Buffer, ulLength,
7846                                                 ulFlags, NULL);
7847 }
7848 
7849 
7850 /***********************************************************************
7851  * CM_Set_DevNode_Registry_PropertyW [SETUPAPI.@]
7852  */
7853 CONFIGRET
7854 WINAPI
7855 CM_Set_DevNode_Registry_PropertyW(
7856     _In_ DEVINST dnDevInst,
7857     _In_ ULONG ulProperty,
7858     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7859     _In_ ULONG ulLength,
7860     _In_ ULONG ulFlags)
7861 {
7862     TRACE("CM_Set_DevNode_Registry_PropertyW(%lx %lu %p %lx %lx)\n",
7863           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7864 
7865     return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
7866                                                 Buffer, ulLength,
7867                                                 ulFlags, NULL);
7868 }
7869 
7870 
7871 /***********************************************************************
7872  * CM_Set_DevNode_Registry_Property_ExA [SETUPAPI.@]
7873  */
7874 CONFIGRET
7875 WINAPI
7876 CM_Set_DevNode_Registry_Property_ExA(
7877     _In_ DEVINST dnDevInst,
7878     _In_ ULONG ulProperty,
7879     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7880     _In_ ULONG ulLength,
7881     _In_ ULONG ulFlags,
7882     _In_opt_ HMACHINE hMachine)
7883 {
7884     CONFIGRET ret = CR_SUCCESS;
7885     LPWSTR lpBuffer;
7886     ULONG ulType;
7887 
7888     FIXME("CM_Set_DevNode_Registry_Property_ExA(%lx %lu %p %lx %lx %p)\n",
7889           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7890 
7891     if (Buffer == NULL && ulLength != 0)
7892         return CR_INVALID_POINTER;
7893 
7894     if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7895         return CR_INVALID_PROPERTY;
7896 
7897     if (Buffer == NULL)
7898     {
7899         ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7900                                                    ulProperty,
7901                                                    NULL,
7902                                                    0,
7903                                                    ulFlags,
7904                                                    hMachine);
7905     }
7906     else
7907     {
7908         /* Get property type */
7909         ulType = GetRegistryPropertyType(ulProperty);
7910 
7911         /* Allocate buffer if needed */
7912         if (ulType == REG_SZ ||
7913             ulType == REG_MULTI_SZ)
7914         {
7915             lpBuffer = MyMalloc(ulLength * sizeof(WCHAR));
7916             if (lpBuffer == NULL)
7917             {
7918                 ret = CR_OUT_OF_MEMORY;
7919             }
7920             else
7921             {
7922                 if (!MultiByteToWideChar(CP_ACP, 0, Buffer,
7923                                          ulLength, lpBuffer, ulLength))
7924                 {
7925                     MyFree(lpBuffer);
7926                     ret = CR_FAILURE;
7927                 }
7928                 else
7929                 {
7930                     ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7931                                                                ulProperty,
7932                                                                lpBuffer,
7933                                                                ulLength * sizeof(WCHAR),
7934                                                                ulFlags,
7935                                                                hMachine);
7936                     MyFree(lpBuffer);
7937                 }
7938             }
7939         }
7940         else
7941         {
7942             ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7943                                                        ulProperty,
7944                                                        Buffer,
7945                                                        ulLength,
7946                                                        ulFlags,
7947                                                        hMachine);
7948         }
7949 
7950         ret = CR_CALL_NOT_IMPLEMENTED;
7951     }
7952 
7953     return ret;
7954 }
7955 
7956 
7957 /***********************************************************************
7958  * CM_Set_DevNode_Registry_Property_ExW [SETUPAPI.@]
7959  */
7960 CONFIGRET
7961 WINAPI
7962 CM_Set_DevNode_Registry_Property_ExW(
7963     _In_ DEVINST dnDevInst,
7964     _In_ ULONG ulProperty,
7965     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7966     _In_ ULONG ulLength,
7967     _In_ ULONG ulFlags,
7968     _In_opt_ HMACHINE hMachine)
7969 {
7970     RPC_BINDING_HANDLE BindingHandle = NULL;
7971     HSTRING_TABLE StringTable = NULL;
7972     LPWSTR lpDevInst;
7973     ULONG ulType;
7974     CONFIGRET ret;
7975 
7976     TRACE("CM_Set_DevNode_Registry_Property_ExW(%lx %lu %p %lx %lx %p)\n",
7977           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7978 
7979     if (dnDevInst == 0)
7980         return CR_INVALID_DEVNODE;
7981 
7982     if (ulProperty <  CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7983         return CR_INVALID_PROPERTY;
7984 
7985     if (Buffer != NULL && ulLength == 0)
7986         return CR_INVALID_POINTER;
7987 
7988     if (ulFlags != 0)
7989         return CR_INVALID_FLAG;
7990 
7991     if (hMachine != NULL)
7992     {
7993         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7994         if (BindingHandle == NULL)
7995             return CR_FAILURE;
7996 
7997         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7998         if (StringTable == 0)
7999             return CR_FAILURE;
8000     }
8001     else
8002     {
8003         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8004             return CR_FAILURE;
8005     }
8006 
8007     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
8008     if (lpDevInst == NULL)
8009         return CR_INVALID_DEVNODE;
8010 
8011     /* Get property type */
8012     ulType = GetRegistryPropertyType(ulProperty);
8013 
8014     RpcTryExcept
8015     {
8016         ret = PNP_SetDeviceRegProp(BindingHandle,
8017                                    lpDevInst,
8018                                    ulProperty,
8019                                    ulType,
8020                                    (BYTE *)Buffer,
8021                                    ulLength,
8022                                    ulFlags);
8023     }
8024     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8025     {
8026         ret = RpcStatusToCmStatus(RpcExceptionCode());
8027     }
8028     RpcEndExcept;
8029 
8030     return ret;
8031 }
8032 
8033 
8034 /***********************************************************************
8035  * CM_Set_HW_Prof [SETUPAPI.@]
8036  */
8037 CONFIGRET
8038 WINAPI
8039 CM_Set_HW_Prof(
8040     _In_ ULONG ulHardwareProfile,
8041     _In_ ULONG ulFlags)
8042 {
8043     TRACE("CM_Set_HW_Prof(%lu %lx)\n",
8044           ulHardwareProfile, ulFlags);
8045 
8046     return CM_Set_HW_Prof_Ex(ulHardwareProfile, ulFlags, NULL);
8047 }
8048 
8049 
8050 /***********************************************************************
8051  * CM_Set_HW_Prof_Ex [SETUPAPI.@]
8052  */
8053 CONFIGRET
8054 WINAPI
8055 CM_Set_HW_Prof_Ex(
8056     _In_ ULONG ulHardwareProfile,
8057     _In_ ULONG ulFlags,
8058     _In_opt_ HMACHINE hMachine)
8059 {
8060     RPC_BINDING_HANDLE BindingHandle = NULL;
8061     CONFIGRET ret;
8062 
8063     TRACE("CM_Set_HW_Prof_Ex(%lu %lx %p)\n",
8064           ulHardwareProfile, ulFlags, hMachine);
8065 
8066     if (!pSetupIsUserAdmin())
8067         return CR_ACCESS_DENIED;
8068 
8069     if (ulFlags != 0)
8070         return CR_INVALID_FLAG;
8071 
8072     if (hMachine != NULL)
8073     {
8074         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8075         if (BindingHandle == NULL)
8076             return CR_FAILURE;
8077     }
8078     else
8079     {
8080         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8081             return CR_FAILURE;
8082     }
8083 
8084     RpcTryExcept
8085     {
8086         ret = PNP_SetHwProf(BindingHandle, ulHardwareProfile, ulFlags);
8087     }
8088     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8089     {
8090         ret = RpcStatusToCmStatus(RpcExceptionCode());
8091     }
8092     RpcEndExcept;
8093 
8094     return ret;
8095 }
8096 
8097 
8098 /***********************************************************************
8099  * CM_Set_HW_Prof_FlagsA [SETUPAPI.@]
8100  */
8101 CONFIGRET
8102 WINAPI
8103 CM_Set_HW_Prof_FlagsA(
8104     _In_ DEVINSTID_A szDevInstName,
8105     _In_ ULONG ulConfig,
8106     _In_ ULONG ulValue,
8107     _In_ ULONG ulFlags)
8108 {
8109     TRACE("CM_Set_HW_Prof_FlagsA(%s %lu %lu %lx)\n",
8110           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags);
8111 
8112     return CM_Set_HW_Prof_Flags_ExA(szDevInstName, ulConfig, ulValue,
8113                                     ulFlags, NULL);
8114 }
8115 
8116 
8117 /***********************************************************************
8118  * CM_Set_HW_Prof_FlagsW [SETUPAPI.@]
8119  */
8120 CONFIGRET
8121 WINAPI
8122 CM_Set_HW_Prof_FlagsW(
8123     _In_ DEVINSTID_W szDevInstName,
8124     _In_ ULONG ulConfig,
8125     _In_ ULONG ulValue,
8126     _In_ ULONG ulFlags)
8127 {
8128     TRACE("CM_Set_HW_Prof_FlagsW(%s %lu %lu %lx)\n",
8129           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags);
8130 
8131     return CM_Set_HW_Prof_Flags_ExW(szDevInstName, ulConfig, ulValue,
8132                                     ulFlags, NULL);
8133 }
8134 
8135 
8136 /***********************************************************************
8137  * CM_Set_HW_Prof_Flags_ExA [SETUPAPI.@]
8138  */
8139 CONFIGRET
8140 WINAPI
8141 CM_Set_HW_Prof_Flags_ExA(
8142     _In_ DEVINSTID_A szDevInstName,
8143     _In_ ULONG ulConfig,
8144     _In_ ULONG ulValue,
8145     _In_ ULONG ulFlags,
8146     _In_opt_ HMACHINE hMachine)
8147 {
8148     DEVINSTID_W pszDevIdW = NULL;
8149     CONFIGRET ret = CR_SUCCESS;
8150 
8151     TRACE("CM_Set_HW_Prof_Flags_ExA(%s %lu %lu %lx %p)\n",
8152           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
8153 
8154     if (szDevInstName != NULL)
8155     {
8156        if (pSetupCaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
8157          return CR_INVALID_DEVICE_ID;
8158     }
8159 
8160     ret = CM_Set_HW_Prof_Flags_ExW(pszDevIdW, ulConfig, ulValue,
8161                                    ulFlags, hMachine);
8162 
8163     if (pszDevIdW != NULL)
8164         MyFree(pszDevIdW);
8165 
8166     return ret;
8167 }
8168 
8169 
8170 /***********************************************************************
8171  * CM_Set_HW_Prof_Flags_ExW [SETUPAPI.@]
8172  */
8173 CONFIGRET
8174 WINAPI
8175 CM_Set_HW_Prof_Flags_ExW(
8176     _In_ DEVINSTID_W szDevInstName,
8177     _In_ ULONG ulConfig,
8178     _In_ ULONG ulValue,
8179     _In_ ULONG ulFlags,
8180     _In_opt_ HMACHINE hMachine)
8181 {
8182     RPC_BINDING_HANDLE BindingHandle = NULL;
8183     CONFIGRET ret;
8184 
8185     FIXME("CM_Set_HW_Prof_Flags_ExW(%s %lu %lu %lx %p)\n",
8186           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
8187 
8188     if (szDevInstName == NULL)
8189         return CR_INVALID_POINTER;
8190 
8191     if (ulFlags & ~ CM_SET_HW_PROF_FLAGS_BITS)
8192         return CR_INVALID_FLAG;
8193 
8194     /* FIXME: Check whether szDevInstName is valid */
8195 
8196     if (hMachine != NULL)
8197     {
8198         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8199         if (BindingHandle == NULL)
8200             return CR_FAILURE;
8201     }
8202     else
8203     {
8204         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8205             return CR_FAILURE;
8206     }
8207 
8208     RpcTryExcept
8209     {
8210         ret = PNP_HwProfFlags(BindingHandle, PNP_SET_HWPROFFLAGS, szDevInstName,
8211                               ulConfig, &ulValue, NULL, NULL, 0, 0);
8212     }
8213     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8214     {
8215         ret = RpcStatusToCmStatus(RpcExceptionCode());
8216     }
8217     RpcEndExcept;
8218 
8219     return ret;
8220 }
8221 
8222 
8223 /***********************************************************************
8224  * CM_Setup_DevNode [SETUPAPI.@]
8225  */
8226 CONFIGRET
8227 WINAPI
8228 CM_Setup_DevNode(
8229     _In_ DEVINST dnDevInst,
8230     _In_ ULONG ulFlags)
8231 {
8232     TRACE("CM_Setup_DevNode(%lx %lx)\n",
8233           dnDevInst, ulFlags);
8234 
8235     return CM_Setup_DevNode_Ex(dnDevInst, ulFlags, NULL);
8236 }
8237 
8238 
8239 /***********************************************************************
8240  * CM_Setup_DevNode_Ex [SETUPAPI.@]
8241  */
8242 CONFIGRET
8243 WINAPI
8244 CM_Setup_DevNode_Ex(
8245     _In_ DEVINST dnDevInst,
8246     _In_ ULONG ulFlags,
8247     _In_opt_ HMACHINE hMachine)
8248 {
8249     RPC_BINDING_HANDLE BindingHandle = NULL;
8250     HSTRING_TABLE StringTable = NULL;
8251     LPWSTR lpDevInst;
8252     CONFIGRET ret;
8253 
8254     FIXME("CM_Setup_DevNode_Ex(%lx %lx %p)\n",
8255           dnDevInst, ulFlags, hMachine);
8256 
8257     if (!pSetupIsUserAdmin())
8258         return CR_ACCESS_DENIED;
8259 
8260     if (dnDevInst == 0)
8261         return CR_INVALID_DEVNODE;
8262 
8263     if (ulFlags & ~CM_SETUP_BITS)
8264         return CR_INVALID_FLAG;
8265 
8266     if (hMachine != NULL)
8267     {
8268         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8269         if (BindingHandle == NULL)
8270             return CR_FAILURE;
8271 
8272         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
8273         if (StringTable == 0)
8274             return CR_FAILURE;
8275     }
8276     else
8277     {
8278         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8279             return CR_FAILURE;
8280     }
8281 
8282     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
8283     if (lpDevInst == NULL)
8284         return CR_INVALID_DEVNODE;
8285 
8286     RpcTryExcept
8287     {
8288         ret = PNP_DeviceInstanceAction(BindingHandle,
8289                                        PNP_DEVINST_SETUP,
8290                                        ulFlags,
8291                                        lpDevInst,
8292                                        NULL);
8293     }
8294     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8295     {
8296         ret = RpcStatusToCmStatus(RpcExceptionCode());
8297     }
8298     RpcEndExcept;
8299 
8300     return ret;
8301 }
8302 
8303 
8304 /***********************************************************************
8305  * CM_Test_Range_Available [SETUPAPI.@]
8306  */
8307 CONFIGRET
8308 WINAPI
8309 CM_Test_Range_Available(
8310     _In_ DWORDLONG ullStartValue,
8311     _In_ DWORDLONG ullEndValue,
8312     _In_ RANGE_LIST rlh,
8313     _In_ ULONG ulFlags)
8314 {
8315     FIXME("CM_Test_Range_Available(%I64u %I64u %p %lx)\n",
8316           ullStartValue, ullEndValue, rlh, ulFlags);
8317     return CR_CALL_NOT_IMPLEMENTED;
8318 }
8319 
8320 
8321 /***********************************************************************
8322  * CM_Uninstall_DevNode [SETUPAPI.@]
8323  */
8324 CONFIGRET
8325 WINAPI
8326 CM_Uninstall_DevNode(
8327     _In_ DEVINST dnPhantom,
8328     _In_ ULONG ulFlags)
8329 {
8330     TRACE("CM_Uninstall_DevNode(%lx %lx)\n",
8331           dnPhantom, ulFlags);
8332 
8333     return CM_Uninstall_DevNode_Ex(dnPhantom, ulFlags, NULL);
8334 }
8335 
8336 
8337 /***********************************************************************
8338  * CM_Uninstall_DevNode_Ex [SETUPAPI.@]
8339  */
8340 CONFIGRET
8341 WINAPI
8342 CM_Uninstall_DevNode_Ex(
8343     _In_ DEVINST dnPhantom,
8344     _In_ ULONG ulFlags,
8345     _In_opt_ HMACHINE hMachine)
8346 {
8347     RPC_BINDING_HANDLE BindingHandle = NULL;
8348     HSTRING_TABLE StringTable = NULL;
8349     LPWSTR lpDevInst;
8350     CONFIGRET ret;
8351 
8352     TRACE("CM_Uninstall_DevNode_Ex(%lx %lx %p)\n",
8353           dnPhantom, ulFlags, hMachine);
8354 
8355     if (dnPhantom == 0)
8356         return CR_INVALID_DEVNODE;
8357 
8358     if (ulFlags != 0)
8359         return CR_INVALID_FLAG;
8360 
8361     if (hMachine != NULL)
8362     {
8363         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8364         if (BindingHandle == NULL)
8365             return CR_FAILURE;
8366 
8367         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
8368         if (StringTable == 0)
8369             return CR_FAILURE;
8370     }
8371     else
8372     {
8373         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8374             return CR_FAILURE;
8375     }
8376 
8377     lpDevInst = pSetupStringTableStringFromId(StringTable, dnPhantom);
8378     if (lpDevInst == NULL)
8379         return CR_INVALID_DEVNODE;
8380 
8381     RpcTryExcept
8382     {
8383         ret = PNP_UninstallDevInst(BindingHandle,
8384                                    lpDevInst,
8385                                    ulFlags);
8386     }
8387     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8388     {
8389         ret = RpcStatusToCmStatus(RpcExceptionCode());
8390     }
8391     RpcEndExcept;
8392 
8393     return ret;
8394 }
8395 
8396 
8397 /***********************************************************************
8398  * CM_Unregister_Device_InterfaceA [SETUPAPI.@]
8399  */
8400 CONFIGRET
8401 WINAPI
8402 CM_Unregister_Device_InterfaceA(
8403     _In_ LPCSTR pszDeviceInterface,
8404     _In_ ULONG ulFlags)
8405 {
8406     TRACE("CM_Unregister_Device_InterfaceA(%s %lx)\n",
8407           debugstr_a(pszDeviceInterface), ulFlags);
8408 
8409     return CM_Unregister_Device_Interface_ExA(pszDeviceInterface,
8410                                               ulFlags, NULL);
8411 }
8412 
8413 
8414 /***********************************************************************
8415  * CM_Unregister_Device_InterfaceW [SETUPAPI.@]
8416  */
8417 CONFIGRET
8418 WINAPI
8419 CM_Unregister_Device_InterfaceW(
8420     _In_ LPCWSTR pszDeviceInterface,
8421     _In_ ULONG ulFlags)
8422 {
8423     TRACE("CM_Unregister_Device_InterfaceW(%s %lx)\n",
8424           debugstr_w(pszDeviceInterface), ulFlags);
8425 
8426     return CM_Unregister_Device_Interface_ExW(pszDeviceInterface,
8427                                               ulFlags, NULL);
8428 }
8429 
8430 
8431 /***********************************************************************
8432  * CM_Unregister_Device_Interface_ExA [SETUPAPI.@]
8433  */
8434 CONFIGRET
8435 WINAPI
8436 CM_Unregister_Device_Interface_ExA(
8437     _In_ LPCSTR pszDeviceInterface,
8438     _In_ ULONG ulFlags,
8439     _In_opt_ HMACHINE hMachine)
8440 {
8441     LPWSTR pszDeviceInterfaceW = NULL;
8442     CONFIGRET ret;
8443 
8444     TRACE("CM_Unregister_Device_Interface_ExA(%s %lx %p)\n",
8445           debugstr_a(pszDeviceInterface), ulFlags, hMachine);
8446 
8447     if (pszDeviceInterface == NULL)
8448         return CR_INVALID_POINTER;
8449 
8450     if (pSetupCaptureAndConvertAnsiArg(pszDeviceInterface, &pszDeviceInterfaceW))
8451         return CR_INVALID_DATA;
8452 
8453     ret = CM_Unregister_Device_Interface_ExW(pszDeviceInterfaceW,
8454                                              ulFlags, hMachine);
8455 
8456     if (pszDeviceInterfaceW != NULL)
8457         MyFree(pszDeviceInterfaceW);
8458 
8459     return ret;
8460 }
8461 
8462 
8463 /***********************************************************************
8464  * CM_Unregister_Device_Interface_ExW [SETUPAPI.@]
8465  */
8466 CONFIGRET
8467 WINAPI
8468 CM_Unregister_Device_Interface_ExW(
8469     _In_ LPCWSTR pszDeviceInterface,
8470     _In_ ULONG ulFlags,
8471     _In_opt_ HMACHINE hMachine)
8472 {
8473     RPC_BINDING_HANDLE BindingHandle = NULL;
8474     CONFIGRET ret;
8475 
8476     TRACE("CM_Unregister_Device_Interface_ExW(%s %lx %p)\n",
8477           debugstr_w(pszDeviceInterface), ulFlags, hMachine);
8478 
8479     if (pszDeviceInterface == NULL)
8480         return CR_INVALID_POINTER;
8481 
8482     if (ulFlags != 0)
8483         return CR_INVALID_FLAG;
8484 
8485     if (hMachine != NULL)
8486     {
8487         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8488         if (BindingHandle == NULL)
8489             return CR_FAILURE;
8490     }
8491     else
8492     {
8493         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8494             return CR_FAILURE;
8495     }
8496 
8497     RpcTryExcept
8498     {
8499         ret = PNP_UnregisterDeviceClassAssociation(BindingHandle,
8500                                                    (LPWSTR)pszDeviceInterface,
8501                                                    ulFlags);
8502     }
8503     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8504     {
8505         ret = RpcStatusToCmStatus(RpcExceptionCode());
8506     }
8507     RpcEndExcept;
8508 
8509     return ret;
8510 }
8511