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