xref: /reactos/dll/win32/setupapi/cfgmgr.c (revision 57d7f6f6)
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         RpcTryExcept
5953         {
5954             /* Validate the device ID */
5955             ret = PNP_ValidateDeviceInstance(BindingHandle,
5956                                              DeviceIdBuffer,
5957                                              ulFlags);
5958         }
5959         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5960         {
5961             ret = RpcStatusToCmStatus(RpcExceptionCode());
5962         }
5963         RpcEndExcept;
5964     }
5965     else
5966     {
5967         RpcTryExcept
5968         {
5969             /* Get the root device ID */
5970             ret = PNP_GetRootDeviceInstance(BindingHandle,
5971                                             DeviceIdBuffer,
5972                                             MAX_DEVICE_ID_LEN);
5973         }
5974         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5975         {
5976             ret = RpcStatusToCmStatus(RpcExceptionCode());
5977         }
5978         RpcEndExcept;
5979     }
5980 
5981     TRACE("DeviceIdBuffer: %s\n", debugstr_w(DeviceIdBuffer));
5982 
5983     if (ret == CR_SUCCESS)
5984     {
5985         *pdnDevInst = pSetupStringTableAddString(StringTable, DeviceIdBuffer, 1);
5986         if (*pdnDevInst == -1)
5987             ret = CR_FAILURE;
5988     }
5989 
5990     return ret;
5991 }
5992 
5993 
5994 /***********************************************************************
5995  * CM_Merge_Range_List [SETUPAPI.@]
5996  */
5997 CONFIGRET
5998 WINAPI
5999 CM_Merge_Range_List(
6000     _In_ RANGE_LIST rlhOld1,
6001     _In_ RANGE_LIST rlhOld2,
6002     _In_ RANGE_LIST rlhNew,
6003     _In_ ULONG ulFlags)
6004 {
6005     FIXME("CM_Merge_Range_List(%p %p %p %lx)\n",
6006           rlhOld1, rlhOld2, rlhNew, ulFlags);
6007 
6008     return CR_CALL_NOT_IMPLEMENTED;
6009 }
6010 
6011 
6012 /***********************************************************************
6013  * CM_Modify_Res_Des [SETUPAPI.@]
6014  */
6015 CONFIGRET
6016 WINAPI
6017 CM_Modify_Res_Des(
6018     _Out_ PRES_DES prdResDes,
6019     _In_ RES_DES rdResDes,
6020     _In_ RESOURCEID ResourceID,
6021     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
6022     _In_ ULONG ResourceLen,
6023     _In_ ULONG ulFlags)
6024 {
6025     TRACE("CM_Modify_Res_Des(%p %p %lx %p %lu %lx)\n",
6026           prdResDes, rdResDes, ResourceID, ResourceData,
6027           ResourceLen, ulFlags);
6028 
6029     return CM_Modify_Res_Des_Ex(prdResDes, rdResDes, ResourceID, ResourceData,
6030                                 ResourceLen, ulFlags, NULL);
6031 }
6032 
6033 
6034 /***********************************************************************
6035  * CM_Modify_Res_Des_Ex [SETUPAPI.@]
6036  */
6037 CONFIGRET
6038 WINAPI
6039 CM_Modify_Res_Des_Ex(
6040     _Out_ PRES_DES prdResDes,
6041     _In_ RES_DES rdResDes,
6042     _In_ RESOURCEID ResourceID,
6043     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
6044     _In_ ULONG ResourceLen,
6045     _In_ ULONG ulFlags,
6046     _In_opt_ HMACHINE hMachine)
6047 {
6048     FIXME("CM_Modify_Res_Des_Ex(%p %p %lx %p %lu %lx %p)\n",
6049           prdResDes, rdResDes, ResourceID, ResourceData,
6050           ResourceLen, ulFlags, hMachine);
6051 
6052     return CR_CALL_NOT_IMPLEMENTED;
6053 }
6054 
6055 
6056 /***********************************************************************
6057  * CM_Move_DevNode [SETUPAPI.@]
6058  */
6059 CONFIGRET
6060 WINAPI
6061 CM_Move_DevNode(
6062     _In_ DEVINST dnFromDevInst,
6063     _In_ DEVINST dnToDevInst,
6064     _In_ ULONG ulFlags)
6065 {
6066     TRACE("CM_Move_DevNode(%lx %lx %lx)\n",
6067           dnFromDevInst, dnToDevInst, ulFlags);
6068 
6069     return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
6070 }
6071 
6072 
6073 /***********************************************************************
6074  * CM_Move_DevNode_Ex [SETUPAPI.@]
6075  */
6076 CONFIGRET
6077 WINAPI
6078 CM_Move_DevNode_Ex(
6079     _In_ DEVINST dnFromDevInst,
6080     _In_ DEVINST dnToDevInst,
6081     _In_ ULONG ulFlags,
6082     _In_opt_ HMACHINE hMachine)
6083 {
6084     RPC_BINDING_HANDLE BindingHandle = NULL;
6085     HSTRING_TABLE StringTable = NULL;
6086     LPWSTR lpFromDevInst;
6087     LPWSTR lpToDevInst;
6088     CONFIGRET ret;
6089 
6090     FIXME("CM_Move_DevNode_Ex(%lx %lx %lx %p)\n",
6091           dnFromDevInst, dnToDevInst, ulFlags, hMachine);
6092 
6093     if (!pSetupIsUserAdmin())
6094         return CR_ACCESS_DENIED;
6095 
6096     if (dnFromDevInst == 0 || dnToDevInst == 0)
6097         return CR_INVALID_DEVNODE;
6098 
6099     if (ulFlags != 0)
6100         return CR_INVALID_FLAG;
6101 
6102     if (hMachine != NULL)
6103     {
6104         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6105         if (BindingHandle == NULL)
6106             return CR_FAILURE;
6107 
6108         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6109         if (StringTable == 0)
6110             return CR_FAILURE;
6111     }
6112     else
6113     {
6114         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6115             return CR_FAILURE;
6116     }
6117 
6118     lpFromDevInst = pSetupStringTableStringFromId(StringTable, dnFromDevInst);
6119     if (lpFromDevInst == NULL)
6120         return CR_INVALID_DEVNODE;
6121 
6122     lpToDevInst = pSetupStringTableStringFromId(StringTable, dnToDevInst);
6123     if (lpToDevInst == NULL)
6124         return CR_INVALID_DEVNODE;
6125 
6126     RpcTryExcept
6127     {
6128         ret = PNP_DeviceInstanceAction(BindingHandle,
6129                                        PNP_DEVINST_MOVE,
6130                                        ulFlags,
6131                                        lpFromDevInst,
6132                                        lpToDevInst);
6133     }
6134     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6135     {
6136         ret = RpcStatusToCmStatus(RpcExceptionCode());
6137     }
6138     RpcEndExcept;
6139 
6140     return ret;
6141 }
6142 
6143 
6144 /***********************************************************************
6145  * CM_Next_Range [SETUPAPI.@]
6146  */
6147 CONFIGRET
6148 WINAPI
6149 CM_Next_Range(
6150     _Inout_ PRANGE_ELEMENT preElement,
6151     _Out_ PDWORDLONG pullStart,
6152     _Out_ PDWORDLONG pullEnd,
6153     _In_ ULONG ulFlags)
6154 {
6155     PINTERNAL_RANGE_LIST pRangeList;
6156     PINTERNAL_RANGE pRange;
6157     PLIST_ENTRY ListEntry;
6158     CONFIGRET ret = CR_SUCCESS;
6159 
6160     FIXME("CM_Next_Range(%p %p %p %lx)\n",
6161           preElement, pullStart, pullEnd, ulFlags);
6162 
6163     pRange = (PINTERNAL_RANGE)preElement;
6164 
6165     if (pRange == NULL || pRange->pRangeList == NULL)
6166         return CR_FAILURE;
6167 
6168     if (pullStart == NULL || pullEnd == NULL)
6169         return CR_INVALID_POINTER;
6170 
6171     if (ulFlags != 0)
6172         return CR_INVALID_FLAG;
6173 
6174     pRangeList = pRange->pRangeList;
6175 
6176     /* Lock the range list */
6177     WaitForSingleObject(pRangeList->hMutex, INFINITE);
6178 
6179     /* Fail, if we reached the end of the list */
6180     if (pRange->ListEntry.Flink == &pRangeList->ListHead)
6181     {
6182         ret = CR_FAILURE;
6183         goto done;
6184     }
6185 
6186     /* Get the next range */
6187     ListEntry = pRangeList->ListHead.Flink;
6188     pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
6189 
6190     /* Return the range data */
6191     *pullStart = pRange->ullStart;
6192     *pullEnd = pRange->ullEnd;
6193     *preElement = (RANGE_ELEMENT)pRange;
6194 
6195 done:
6196     /* Unlock the range list */
6197     ReleaseMutex(pRangeList->hMutex);
6198 
6199     return ret;
6200 }
6201 
6202 
6203 /***********************************************************************
6204  * CM_Open_Class_KeyA [SETUPAPI.@]
6205  */
6206 CONFIGRET
6207 WINAPI
6208 CM_Open_Class_KeyA(
6209     _In_opt_ LPGUID pClassGuid,
6210     _In_opt_ LPCSTR pszClassName,
6211     _In_ REGSAM samDesired,
6212     _In_ REGDISPOSITION Disposition,
6213     _Out_ PHKEY phkClass,
6214     _In_ ULONG ulFlags)
6215 {
6216     TRACE("CM_Open_Class_KeyA(%p %s %lx %lx %p %lx)\n",
6217           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
6218           samDesired, Disposition, phkClass, ulFlags);
6219 
6220     return CM_Open_Class_Key_ExA(pClassGuid, pszClassName, samDesired,
6221                                  Disposition, phkClass, ulFlags, NULL);
6222 }
6223 
6224 
6225 /***********************************************************************
6226  * CM_Open_Class_KeyW [SETUPAPI.@]
6227  */
6228 CONFIGRET
6229 WINAPI
6230 CM_Open_Class_KeyW(
6231     _In_opt_ LPGUID pClassGuid,
6232     _In_opt_ LPCWSTR pszClassName,
6233     _In_ REGSAM samDesired,
6234     _In_ REGDISPOSITION Disposition,
6235     _Out_ PHKEY phkClass,
6236     _In_ ULONG ulFlags)
6237 {
6238     TRACE("CM_Open_Class_KeyW%p %s %lx %lx %p %lx)\n",
6239           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
6240           samDesired, Disposition, phkClass, ulFlags);
6241 
6242     return CM_Open_Class_Key_ExW(pClassGuid, pszClassName, samDesired,
6243                                  Disposition, phkClass, ulFlags, NULL);
6244 }
6245 
6246 
6247 /***********************************************************************
6248  * CM_Open_Class_Key_ExA [SETUPAPI.@]
6249  */
6250 CONFIGRET
6251 WINAPI
6252 CM_Open_Class_Key_ExA(
6253     _In_opt_ LPGUID pClassGuid,
6254     _In_opt_ LPCSTR pszClassName,
6255     _In_ REGSAM samDesired,
6256     _In_ REGDISPOSITION Disposition,
6257     _Out_ PHKEY phkClass,
6258     _In_ ULONG ulFlags,
6259     _In_opt_ HMACHINE hMachine)
6260 {
6261     LPWSTR pszClassNameW = NULL;
6262     CONFIGRET ret;
6263 
6264     TRACE("CM_Open_Class_Key_ExA(%p %s %lx %lx %p %lx %p)\n",
6265           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
6266           samDesired, Disposition, phkClass, ulFlags, hMachine);
6267 
6268     if (pszClassName != NULL)
6269     {
6270        if (pSetupCaptureAndConvertAnsiArg(pszClassName, &pszClassNameW))
6271          return CR_INVALID_DATA;
6272     }
6273 
6274     ret = CM_Open_Class_Key_ExW(pClassGuid, pszClassNameW, samDesired,
6275                                 Disposition, phkClass, ulFlags, hMachine);
6276 
6277     if (pszClassNameW != NULL)
6278         MyFree(pszClassNameW);
6279 
6280     return ret;
6281 }
6282 
6283 
6284 /***********************************************************************
6285  * CM_Open_Class_Key_ExW [SETUPAPI.@]
6286  */
6287 CONFIGRET
6288 WINAPI
6289 CM_Open_Class_Key_ExW(
6290     _In_opt_ LPGUID pClassGuid,
6291     _In_opt_ LPCWSTR pszClassName,
6292     _In_ REGSAM samDesired,
6293     _In_ REGDISPOSITION Disposition,
6294     _Out_ PHKEY phkClass,
6295     _In_ ULONG ulFlags,
6296     _In_opt_ HMACHINE hMachine)
6297 {
6298     WCHAR szKeyName[MAX_PATH];
6299     LPWSTR lpGuidString;
6300     DWORD dwDisposition;
6301     DWORD dwError;
6302     HKEY hKey;
6303 
6304     TRACE("CM_Open_Class_Key_ExW(%p %s %lx %lx %p %lx %p)\n",
6305           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
6306           samDesired, Disposition, phkClass, ulFlags, hMachine);
6307 
6308     /* Check Disposition and ulFlags */
6309     if ((Disposition & ~RegDisposition_Bits) ||
6310         (ulFlags & ~CM_OPEN_CLASS_KEY_BITS))
6311         return CR_INVALID_FLAG;
6312 
6313     /* Check phkClass */
6314     if (phkClass == NULL)
6315         return CR_INVALID_POINTER;
6316 
6317     *phkClass = NULL;
6318 
6319     if (ulFlags == CM_OPEN_CLASS_KEY_INTERFACE &&
6320         pszClassName != NULL)
6321         return CR_INVALID_DATA;
6322 
6323     if (hMachine == NULL)
6324     {
6325         hKey = HKEY_LOCAL_MACHINE;
6326     }
6327     else
6328     {
6329         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6330                                 HKEY_LOCAL_MACHINE,
6331                                 &hKey))
6332             return CR_REGISTRY_ERROR;
6333     }
6334 
6335     if (ulFlags & CM_OPEN_CLASS_KEY_INTERFACE)
6336     {
6337         lstrcpyW(szKeyName, DeviceClasses);
6338     }
6339     else
6340     {
6341         lstrcpyW(szKeyName, ControlClass);
6342     }
6343 
6344     if (pClassGuid != NULL)
6345     {
6346         if (UuidToStringW((UUID*)pClassGuid, &lpGuidString) != RPC_S_OK)
6347         {
6348             RegCloseKey(hKey);
6349             return CR_INVALID_DATA;
6350         }
6351 
6352         lstrcatW(szKeyName, BackslashOpenBrace);
6353         lstrcatW(szKeyName, lpGuidString);
6354         lstrcatW(szKeyName, CloseBrace);
6355     }
6356 
6357     if (Disposition == RegDisposition_OpenAlways)
6358     {
6359         dwError = RegCreateKeyExW(hKey, szKeyName, 0, NULL, 0, samDesired,
6360                                   NULL, phkClass, &dwDisposition);
6361     }
6362     else
6363     {
6364         dwError = RegOpenKeyExW(hKey, szKeyName, 0, samDesired, phkClass);
6365     }
6366 
6367     RegCloseKey(hKey);
6368 
6369     if (pClassGuid != NULL)
6370         RpcStringFreeW(&lpGuidString);
6371 
6372     if (dwError != ERROR_SUCCESS)
6373     {
6374         *phkClass = NULL;
6375         return CR_NO_SUCH_REGISTRY_KEY;
6376     }
6377 
6378     if (pszClassName != NULL)
6379     {
6380         RegSetValueExW(*phkClass, Class, 0, REG_SZ, (LPBYTE)pszClassName,
6381                        (lstrlenW(pszClassName) + 1) * sizeof(WCHAR));
6382     }
6383 
6384     return CR_SUCCESS;
6385 }
6386 
6387 
6388 /***********************************************************************
6389  * CM_Open_DevNode_Key [SETUPAPI.@]
6390  */
6391 CONFIGRET
6392 WINAPI
6393 CM_Open_DevNode_Key(
6394     _In_ DEVINST dnDevNode,
6395     _In_ REGSAM samDesired,
6396     _In_ ULONG ulHardwareProfile,
6397     _In_ REGDISPOSITION Disposition,
6398     _Out_ PHKEY phkDevice,
6399     _In_ ULONG ulFlags)
6400 {
6401     TRACE("CM_Open_DevNode_Key(%lx %lx %lu %lx %p %lx)\n",
6402           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags);
6403 
6404     return CM_Open_DevNode_Key_Ex(dnDevNode, samDesired, ulHardwareProfile,
6405                                   Disposition, phkDevice, ulFlags, NULL);
6406 }
6407 
6408 
6409 /***********************************************************************
6410  * CM_Open_DevNode_Key_Ex [SETUPAPI.@]
6411  */
6412 CONFIGRET
6413 WINAPI
6414 CM_Open_DevNode_Key_Ex(
6415     _In_ DEVINST dnDevNode,
6416     _In_ REGSAM samDesired,
6417     _In_ ULONG ulHardwareProfile,
6418     _In_ REGDISPOSITION Disposition,
6419     _Out_ PHKEY phkDevice,
6420     _In_ ULONG ulFlags,
6421     _In_opt_ HMACHINE hMachine)
6422 {
6423     RPC_BINDING_HANDLE BindingHandle = NULL;
6424     HSTRING_TABLE StringTable = NULL;
6425     LPWSTR pszDevInst, pszKeyPath = NULL, pszInstancePath = NULL;
6426     LONG lError;
6427     DWORD dwDisposition;
6428     HKEY hRootKey = NULL;
6429     CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
6430 
6431     TRACE("CM_Open_DevNode_Key_Ex(%lx %lx %lu %lx %p %lx %p)\n",
6432           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags, hMachine);
6433 
6434     if (phkDevice == NULL)
6435         return CR_INVALID_POINTER;
6436 
6437     *phkDevice = NULL;
6438 
6439     if (dnDevNode == 0)
6440         return CR_INVALID_DEVNODE;
6441 
6442     if (ulFlags & ~CM_REGISTRY_BITS)
6443         return CR_INVALID_FLAG;
6444 
6445     if (Disposition & ~RegDisposition_Bits)
6446         return CR_INVALID_DATA;
6447 
6448     if (hMachine != NULL)
6449     {
6450         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6451         if (BindingHandle == NULL)
6452             return CR_FAILURE;
6453 
6454         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6455         if (StringTable == 0)
6456             return CR_FAILURE;
6457     }
6458     else
6459     {
6460         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6461             return CR_FAILURE;
6462     }
6463 
6464     pszDevInst = pSetupStringTableStringFromId(StringTable, dnDevNode);
6465     if (pszDevInst == NULL)
6466         return CR_INVALID_DEVNODE;
6467 
6468     TRACE("pszDevInst: %S\n", pszDevInst);
6469 
6470     pszKeyPath = MyMalloc(512 * sizeof(WCHAR));
6471     if (pszKeyPath == NULL)
6472     {
6473         ret = CR_OUT_OF_MEMORY;
6474         goto done;
6475     }
6476 
6477     pszInstancePath = MyMalloc(512 * sizeof(WCHAR));
6478     if (pszInstancePath == NULL)
6479     {
6480         ret = CR_OUT_OF_MEMORY;
6481         goto done;
6482     }
6483 
6484     ret = GetDeviceInstanceKeyPath(BindingHandle,
6485                                    pszDevInst,
6486                                    pszKeyPath,
6487                                    pszInstancePath,
6488                                    ulHardwareProfile,
6489                                    ulFlags);
6490     if (ret != CR_SUCCESS)
6491         goto done;
6492 
6493     TRACE("pszKeyPath: %S\n", pszKeyPath);
6494     TRACE("pszInstancePath: %S\n", pszInstancePath);
6495 
6496     wcscat(pszKeyPath, L"\\");
6497     wcscat(pszKeyPath, pszInstancePath);
6498 
6499     TRACE("pszKeyPath: %S\n", pszKeyPath);
6500 
6501     if (hMachine == NULL)
6502     {
6503         hRootKey = HKEY_LOCAL_MACHINE;
6504     }
6505     else
6506     {
6507         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6508                                 HKEY_LOCAL_MACHINE,
6509                                 &hRootKey))
6510         {
6511             ret = CR_REGISTRY_ERROR;
6512             goto done;
6513         }
6514     }
6515 
6516     if (Disposition == RegDisposition_OpenAlways)
6517     {
6518         lError = RegCreateKeyExW(hRootKey,
6519                                  pszKeyPath,
6520                                  0,
6521                                  NULL,
6522                                  0,
6523                                  samDesired,
6524                                  NULL,
6525                                  phkDevice,
6526                                  &dwDisposition);
6527     }
6528     else
6529     {
6530         lError = RegOpenKeyExW(hRootKey,
6531                                pszKeyPath,
6532                                0,
6533                                samDesired,
6534                                phkDevice);
6535     }
6536 
6537     if (lError != ERROR_SUCCESS)
6538     {
6539         *phkDevice = NULL;
6540         ret = CR_NO_SUCH_REGISTRY_KEY;
6541     }
6542 
6543 done:
6544     if ((hRootKey != NULL) && (hRootKey != HKEY_LOCAL_MACHINE))
6545         RegCloseKey(hRootKey);
6546 
6547     if (pszInstancePath != NULL)
6548         MyFree(pszInstancePath);
6549 
6550     if (pszKeyPath != NULL)
6551         MyFree(pszKeyPath);
6552 
6553     return ret;
6554 }
6555 
6556 
6557 /***********************************************************************
6558  * CM_Query_And_Remove_SubTreeA [SETUPAPI.@]
6559  */
6560 CONFIGRET
6561 WINAPI
6562 CM_Query_And_Remove_SubTreeA(
6563     _In_ DEVINST dnAncestor,
6564     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6565     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6566     _In_ ULONG ulNameLength,
6567     _In_ ULONG ulFlags)
6568 {
6569     TRACE("CM_Query_And_Remove_SubTreeA(%lx %p %s %lu %lx)\n",
6570           dnAncestor, pVetoType, pszVetoName, ulNameLength, ulFlags);
6571 
6572     return CM_Query_And_Remove_SubTree_ExA(dnAncestor, pVetoType, pszVetoName,
6573                                            ulNameLength, ulFlags, NULL);
6574 }
6575 
6576 
6577 /***********************************************************************
6578  * CM_Query_And_Remove_SubTreeW [SETUPAPI.@]
6579  */
6580 CONFIGRET
6581 WINAPI
6582 CM_Query_And_Remove_SubTreeW(
6583     _In_ DEVINST dnAncestor,
6584     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6585     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6586     _In_ ULONG ulNameLength,
6587     _In_ ULONG ulFlags)
6588 {
6589     TRACE("CM_Query_And_Remove_SubTreeW(%lx %p %s %lu %lx)\n",
6590           dnAncestor, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags);
6591 
6592     return CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, pszVetoName,
6593                                            ulNameLength, ulFlags, NULL);
6594 }
6595 
6596 
6597 /***********************************************************************
6598  * CM_Query_And_Remove_SubTree_ExA [SETUPAPI.@]
6599  */
6600 CONFIGRET
6601 WINAPI
6602 CM_Query_And_Remove_SubTree_ExA(
6603     _In_ DEVINST dnAncestor,
6604     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6605     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6606     _In_ ULONG ulNameLength,
6607     _In_ ULONG ulFlags,
6608     _In_opt_ HMACHINE hMachine)
6609 {
6610     LPWSTR lpLocalVetoName;
6611     CONFIGRET ret;
6612 
6613     TRACE("CM_Query_And_Remove_SubTree_ExA(%lx %p %s %lu %lx %p)\n",
6614           dnAncestor, pVetoType, debugstr_a(pszVetoName), ulNameLength,
6615           ulFlags, hMachine);
6616 
6617     if (pszVetoName == NULL && ulNameLength == 0)
6618         return CR_INVALID_POINTER;
6619 
6620     lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
6621     if (lpLocalVetoName == NULL)
6622         return CR_OUT_OF_MEMORY;
6623 
6624     ret = CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, lpLocalVetoName,
6625                                           ulNameLength, ulFlags, hMachine);
6626     if (ret == CR_REMOVE_VETOED)
6627     {
6628         if (WideCharToMultiByte(CP_ACP,
6629                                 0,
6630                                 lpLocalVetoName,
6631                                 ulNameLength,
6632                                 pszVetoName,
6633                                 ulNameLength,
6634                                 NULL,
6635                                 NULL) == 0)
6636             ret = CR_FAILURE;
6637     }
6638 
6639     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
6640 
6641     return ret;
6642 }
6643 
6644 
6645 /***********************************************************************
6646  * CM_Query_And_Remove_SubTree_ExW [SETUPAPI.@]
6647  */
6648 CONFIGRET
6649 WINAPI
6650 CM_Query_And_Remove_SubTree_ExW(
6651     _In_ DEVINST dnAncestor,
6652     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6653     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6654     _In_ ULONG ulNameLength,
6655     _In_ ULONG ulFlags,
6656     _In_opt_ HMACHINE hMachine)
6657 {
6658     RPC_BINDING_HANDLE BindingHandle = NULL;
6659     HSTRING_TABLE StringTable = NULL;
6660     LPWSTR lpDevInst;
6661     CONFIGRET ret;
6662 
6663     TRACE("CM_Query_And_Remove_SubTree_ExW(%lx %p %s %lu %lx %p)\n",
6664           dnAncestor, pVetoType, debugstr_w(pszVetoName), ulNameLength,
6665           ulFlags, hMachine);
6666 
6667     if (dnAncestor == 0)
6668         return CR_INVALID_DEVNODE;
6669 
6670     if (ulFlags & ~CM_REMOVE_BITS)
6671         return CR_INVALID_FLAG;
6672 
6673     if (pszVetoName == NULL && ulNameLength == 0)
6674         return CR_INVALID_POINTER;
6675 
6676     if (hMachine != NULL)
6677     {
6678         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6679         if (BindingHandle == NULL)
6680             return CR_FAILURE;
6681 
6682         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6683         if (StringTable == 0)
6684             return CR_FAILURE;
6685     }
6686     else
6687     {
6688         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6689             return CR_FAILURE;
6690     }
6691 
6692     lpDevInst = pSetupStringTableStringFromId(StringTable, dnAncestor);
6693     if (lpDevInst == NULL)
6694         return CR_INVALID_DEVNODE;
6695 
6696     RpcTryExcept
6697     {
6698         ret = PNP_QueryRemove(BindingHandle,
6699                               lpDevInst,
6700                               pVetoType,
6701                               pszVetoName,
6702                               ulNameLength,
6703                               ulFlags);
6704     }
6705     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6706     {
6707         ret = RpcStatusToCmStatus(RpcExceptionCode());
6708     }
6709     RpcEndExcept;
6710 
6711     return ret;
6712 }
6713 
6714 
6715 /***********************************************************************
6716  * CM_Query_Arbitrator_Free_Data [SETUPAPI.@]
6717  */
6718 CONFIGRET
6719 WINAPI
6720 CM_Query_Arbitrator_Free_Data(
6721     _Out_writes_bytes_(DataLen) PVOID pData,
6722     _In_ ULONG DataLen,
6723     _In_ DEVINST dnDevInst,
6724     _In_ RESOURCEID ResourceID,
6725     _In_ ULONG ulFlags)
6726 {
6727     TRACE("CM_Query_Arbitrator_Free_Data(%p %lu %lx %lu 0x%08lx)\n",
6728           pData, DataLen, dnDevInst, ResourceID, ulFlags);
6729 
6730     return CM_Query_Arbitrator_Free_Data_Ex(pData, DataLen, dnDevInst,
6731                                             ResourceID, ulFlags, NULL);
6732 }
6733 
6734 
6735 /***********************************************************************
6736  * CM_Query_Arbitrator_Free_Data_Ex [SETUPAPI.@]
6737  */
6738 CONFIGRET
6739 WINAPI
6740 CM_Query_Arbitrator_Free_Data_Ex(
6741     _Out_writes_bytes_(DataLen) PVOID pData,
6742     _In_ ULONG DataLen,
6743     _In_ DEVINST dnDevInst,
6744     _In_ RESOURCEID ResourceID,
6745     _In_ ULONG ulFlags,
6746     _In_opt_ HMACHINE hMachine)
6747 {
6748     RPC_BINDING_HANDLE BindingHandle = NULL;
6749     HSTRING_TABLE StringTable = NULL;
6750     LPWSTR lpDevInst;
6751     CONFIGRET ret;
6752 
6753     TRACE("CM_Query_Arbitrator_Free_Data_Ex(%p %lu %lx %lu 0x%08lx %p)\n",
6754           pData, DataLen, dnDevInst, ResourceID, ulFlags, hMachine);
6755 
6756     if (pData == NULL || DataLen == 0)
6757         return CR_INVALID_POINTER;
6758 
6759     if (dnDevInst == 0)
6760         return CR_INVALID_DEVINST;
6761 
6762     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6763         return CR_INVALID_FLAG;
6764 
6765     if (hMachine != NULL)
6766     {
6767         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6768         if (BindingHandle == NULL)
6769             return CR_FAILURE;
6770 
6771         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6772         if (StringTable == 0)
6773             return CR_FAILURE;
6774     }
6775     else
6776     {
6777         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6778             return CR_FAILURE;
6779     }
6780 
6781     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6782     if (lpDevInst == NULL)
6783         return CR_INVALID_DEVNODE;
6784 
6785     RpcTryExcept
6786     {
6787         ret = PNP_QueryArbitratorFreeData(BindingHandle,
6788                                           pData,
6789                                           DataLen,
6790                                           lpDevInst,
6791                                           ResourceID,
6792                                           ulFlags);
6793     }
6794     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6795     {
6796         ret = RpcStatusToCmStatus(RpcExceptionCode());
6797     }
6798     RpcEndExcept;
6799 
6800     return ret;
6801 }
6802 
6803 
6804 /***********************************************************************
6805  * CM_Query_Arbitrator_Free_Size [SETUPAPI.@]
6806  */
6807 CONFIGRET
6808 WINAPI
6809 CM_Query_Arbitrator_Free_Size(
6810     _Out_ PULONG pulSize,
6811     _In_ DEVINST dnDevInst,
6812     _In_ RESOURCEID ResourceID,
6813     _In_ ULONG ulFlags)
6814 {
6815     TRACE("CM_Query_Arbitrator_Free_Size(%p %lu %lx 0x%08lx)\n",
6816           pulSize, dnDevInst,ResourceID, ulFlags);
6817 
6818     return CM_Query_Arbitrator_Free_Size_Ex(pulSize, dnDevInst, ResourceID,
6819                                             ulFlags, NULL);
6820 }
6821 
6822 
6823 /***********************************************************************
6824  * CM_Query_Arbitrator_Free_Size_Ex [SETUPAPI.@]
6825  */
6826 CONFIGRET
6827 WINAPI
6828 CM_Query_Arbitrator_Free_Size_Ex(
6829     _Out_ PULONG pulSize,
6830     _In_ DEVINST dnDevInst,
6831     _In_ RESOURCEID ResourceID,
6832     _In_ ULONG ulFlags,
6833     _In_opt_ HMACHINE hMachine)
6834 {
6835     RPC_BINDING_HANDLE BindingHandle = NULL;
6836     HSTRING_TABLE StringTable = NULL;
6837     LPWSTR lpDevInst;
6838     CONFIGRET ret;
6839 
6840     TRACE("CM_Query_Arbitrator_Free_Size_Ex(%p %lu %lx 0x%08lx %p)\n",
6841           pulSize, dnDevInst,ResourceID, ulFlags, hMachine);
6842 
6843     if (pulSize == NULL)
6844         return CR_INVALID_POINTER;
6845 
6846     if (dnDevInst == 0)
6847         return CR_INVALID_DEVINST;
6848 
6849     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6850         return CR_INVALID_FLAG;
6851 
6852     if (hMachine != NULL)
6853     {
6854         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6855         if (BindingHandle == NULL)
6856             return CR_FAILURE;
6857 
6858         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6859         if (StringTable == 0)
6860             return CR_FAILURE;
6861     }
6862     else
6863     {
6864         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6865             return CR_FAILURE;
6866     }
6867 
6868     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6869     if (lpDevInst == NULL)
6870         return CR_INVALID_DEVNODE;
6871 
6872     RpcTryExcept
6873     {
6874         ret = PNP_QueryArbitratorFreeSize(BindingHandle,
6875                                           pulSize,
6876                                           lpDevInst,
6877                                           ResourceID,
6878                                           ulFlags);
6879     }
6880     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6881     {
6882         ret = RpcStatusToCmStatus(RpcExceptionCode());
6883     }
6884     RpcEndExcept;
6885 
6886     return ret;
6887 }
6888 
6889 
6890 /***********************************************************************
6891  * CM_Query_Remove_SubTree [SETUPAPI.@]
6892  *
6893  * This function is obsolete in Windows XP and above.
6894  */
6895 CONFIGRET
6896 WINAPI
6897 CM_Query_Remove_SubTree(
6898     _In_ DEVINST dnAncestor,
6899     _In_ ULONG ulFlags)
6900 {
6901     TRACE("CM_Query_Remove_SubTree(%lx %lx)\n",
6902           dnAncestor, ulFlags);
6903 
6904     return CR_CALL_NOT_IMPLEMENTED;
6905 }
6906 
6907 
6908 /***********************************************************************
6909  * CM_Query_Remove_SubTree_Ex [SETUPAPI.@]
6910  *
6911  * This function is obsolete in Windows XP and above.
6912  */
6913 CONFIGRET
6914 WINAPI
6915 CM_Query_Remove_SubTree_Ex(
6916     _In_ DEVINST dnAncestor,
6917     _In_ ULONG ulFlags,
6918     _In_opt_ HMACHINE hMachine)
6919 {
6920     TRACE("CM_Query_Remove_SubTree_Ex(%lx %lx %p)\n",
6921           dnAncestor, ulFlags, hMachine);
6922 
6923     return CR_CALL_NOT_IMPLEMENTED;
6924 }
6925 
6926 
6927 /***********************************************************************
6928  * CM_Query_Resource_Conflict_List [SETUPAPI.@]
6929  */
6930 CONFIGRET
6931 WINAPI
6932 CM_Query_Resource_Conflict_List(
6933     _Out_ PCONFLICT_LIST pclConflictList,
6934     _In_ DEVINST dnDevInst,
6935     _In_ RESOURCEID ResourceID,
6936     _In_ PCVOID ResourceData,
6937     _In_ ULONG ResourceLen,
6938     _In_ ULONG ulFlags,
6939     _In_opt_ HMACHINE hMachine)
6940 {
6941     RPC_BINDING_HANDLE BindingHandle = NULL;
6942     HSTRING_TABLE StringTable = NULL;
6943     PPNP_CONFLICT_LIST pConflictBuffer = NULL;
6944     PCONFLICT_DATA pConflictData = NULL;
6945     ULONG ulBufferLength;
6946     LPWSTR lpDevInst;
6947     CONFIGRET ret;
6948 
6949     FIXME("CM_Query_Resource_Conflict_List(%p %lx %lu %p %lu %lx %p)\n",
6950           pclConflictList, dnDevInst, ResourceID, ResourceData,
6951           ResourceLen, ulFlags, hMachine);
6952 
6953     if (dnDevInst == 0)
6954         return CR_INVALID_DEVNODE;
6955 
6956     if (ulFlags & ~CM_RESDES_WIDTH_BITS)
6957         return CR_INVALID_FLAG;
6958 
6959     if (pclConflictList == NULL ||
6960         ResourceData == NULL ||
6961         ResourceLen == 0)
6962         return CR_INVALID_POINTER;
6963 
6964     if (ResourceID == 0)
6965         return CR_INVALID_RESOURCEID;
6966 
6967     *pclConflictList = 0;
6968 
6969     if (hMachine != NULL)
6970     {
6971         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6972         if (BindingHandle == NULL)
6973             return CR_FAILURE;
6974 
6975         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6976         if (StringTable == 0)
6977             return CR_FAILURE;
6978     }
6979     else
6980     {
6981         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6982             return CR_FAILURE;
6983     }
6984 
6985     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6986     if (lpDevInst == NULL)
6987         return CR_INVALID_DEVNODE;
6988 
6989     pConflictData = MyMalloc(sizeof(CONFLICT_DATA));
6990     if (pConflictData == NULL)
6991     {
6992         ret = CR_OUT_OF_MEMORY;
6993         goto done;
6994     }
6995 
6996     ulBufferLength = sizeof(PNP_CONFLICT_LIST) +
6997                      sizeof(PNP_CONFLICT_STRINGS) +
6998                      (sizeof(wchar_t) * 200);
6999     pConflictBuffer = MyMalloc(ulBufferLength);
7000     if (pConflictBuffer == NULL)
7001     {
7002         ret = CR_OUT_OF_MEMORY;
7003         goto done;
7004     }
7005 
7006     RpcTryExcept
7007     {
7008         ret = PNP_QueryResConfList(BindingHandle,
7009                                    lpDevInst,
7010                                    ResourceID,
7011                                    (PBYTE)ResourceData,
7012                                    ResourceLen,
7013                                    (PBYTE)pConflictBuffer,
7014                                    ulBufferLength,
7015                                    ulFlags);
7016     }
7017     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7018     {
7019         ret = RpcStatusToCmStatus(RpcExceptionCode());
7020     }
7021     RpcEndExcept;
7022 
7023     if (ret != CR_SUCCESS)
7024         goto done;
7025 
7026     pConflictData->ulMagic = CONFLICT_MAGIC;
7027     pConflictData->pConflictList = pConflictBuffer;
7028 
7029     *pclConflictList = (CONFLICT_LIST)pConflictData;
7030 
7031 done:
7032     if (ret != CR_SUCCESS)
7033     {
7034         if (pConflictBuffer != NULL)
7035             MyFree(pConflictBuffer);
7036 
7037         if (pConflictData != NULL)
7038             MyFree(pConflictData);
7039     }
7040 
7041     return ret;
7042 }
7043 
7044 
7045 /***********************************************************************
7046  * CM_Reenumerate_DevNode [SETUPAPI.@]
7047  */
7048 CONFIGRET
7049 WINAPI
7050 CM_Reenumerate_DevNode(
7051     _In_ DEVINST dnDevInst,
7052     _In_ ULONG ulFlags)
7053 {
7054     TRACE("CM_Reenumerate_DevNode(%lx %lx)\n",
7055           dnDevInst, ulFlags);
7056 
7057     return CM_Reenumerate_DevNode_Ex(dnDevInst, ulFlags, NULL);
7058 }
7059 
7060 
7061 /***********************************************************************
7062  * CM_Reenumerate_DevNode_Ex [SETUPAPI.@]
7063  */
7064 CONFIGRET WINAPI
7065 CM_Reenumerate_DevNode_Ex(
7066     _In_ DEVINST dnDevInst,
7067     _In_ ULONG ulFlags,
7068     _In_opt_ HMACHINE hMachine)
7069 {
7070     RPC_BINDING_HANDLE BindingHandle = NULL;
7071     HSTRING_TABLE StringTable = NULL;
7072     LPWSTR lpDevInst;
7073     CONFIGRET ret;
7074 
7075     FIXME("CM_Reenumerate_DevNode_Ex(%lx %lx %p)\n",
7076           dnDevInst, ulFlags, hMachine);
7077 
7078     if (dnDevInst == 0)
7079         return CR_INVALID_DEVNODE;
7080 
7081     if (ulFlags & ~CM_REENUMERATE_BITS)
7082         return CR_INVALID_FLAG;
7083 
7084     if (hMachine != NULL)
7085     {
7086         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7087         if (BindingHandle == NULL)
7088             return CR_FAILURE;
7089 
7090         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7091         if (StringTable == 0)
7092             return CR_FAILURE;
7093     }
7094     else
7095     {
7096         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7097             return CR_FAILURE;
7098     }
7099 
7100     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7101     if (lpDevInst == NULL)
7102         return CR_INVALID_DEVNODE;
7103 
7104     RpcTryExcept
7105     {
7106         ret = PNP_DeviceInstanceAction(BindingHandle,
7107                                        PNP_DEVINST_REENUMERATE,
7108                                        ulFlags,
7109                                        lpDevInst,
7110                                        NULL);
7111     }
7112     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7113     {
7114         ret = RpcStatusToCmStatus(RpcExceptionCode());
7115     }
7116     RpcEndExcept;
7117 
7118     return ret;
7119 }
7120 
7121 
7122 /***********************************************************************
7123  * CM_Register_Device_Driver [SETUPAPI.@]
7124  */
7125 CONFIGRET
7126 WINAPI
7127 CM_Register_Device_Driver(
7128     _In_ DEVINST dnDevInst,
7129     _In_ ULONG ulFlags)
7130 {
7131     TRACE("CM_Register_Device_Driver(%lx 0x%08lx)\n",
7132           dnDevInst, ulFlags);
7133 
7134     return CM_Register_Device_Driver_Ex(dnDevInst, ulFlags, NULL);
7135 }
7136 
7137 
7138 /***********************************************************************
7139  * CM_Register_Device_Driver_Ex [SETUPAPI.@]
7140  */
7141 CONFIGRET
7142 WINAPI
7143 CM_Register_Device_Driver_Ex(
7144     _In_ DEVINST dnDevInst,
7145     _In_ ULONG ulFlags,
7146     _In_opt_ HMACHINE hMachine)
7147 {
7148     RPC_BINDING_HANDLE BindingHandle = NULL;
7149     HSTRING_TABLE StringTable = NULL;
7150     LPWSTR lpDevInst;
7151     CONFIGRET ret;
7152 
7153     TRACE("CM_Register_Device_Driver_Ex(%lx 0x%08lx %p)\n",
7154           dnDevInst, ulFlags, hMachine);
7155 
7156     if (dnDevInst == 0)
7157         return CR_INVALID_DEVNODE;
7158 
7159     if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
7160         return CR_INVALID_FLAG;
7161 
7162     if (hMachine != NULL)
7163     {
7164         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7165         if (BindingHandle == NULL)
7166             return CR_FAILURE;
7167 
7168         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7169         if (StringTable == 0)
7170             return CR_FAILURE;
7171     }
7172     else
7173     {
7174         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7175             return CR_FAILURE;
7176     }
7177 
7178     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7179     if (lpDevInst == NULL)
7180         return CR_INVALID_DEVNODE;
7181 
7182     RpcTryExcept
7183     {
7184         ret = PNP_RegisterDriver(BindingHandle,
7185                                  lpDevInst,
7186                                  ulFlags);
7187     }
7188     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7189     {
7190         ret = RpcStatusToCmStatus(RpcExceptionCode());
7191     }
7192     RpcEndExcept;
7193 
7194     return ret;
7195 }
7196 
7197 
7198 /***********************************************************************
7199  * CM_Register_Device_InterfaceA [SETUPAPI.@]
7200  */
7201 CONFIGRET
7202 WINAPI
7203 CM_Register_Device_InterfaceA(
7204     _In_ DEVINST dnDevInst,
7205     _In_ LPGUID InterfaceClassGuid,
7206     _In_opt_ LPCSTR pszReference,
7207     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
7208     _Inout_ PULONG pulLength,
7209     _In_ ULONG ulFlags)
7210 {
7211     TRACE("CM_Register_Device_InterfaceA(%lx %s %s %p %p %lx)\n",
7212           dnDevInst, debugstr_guid(InterfaceClassGuid),
7213           pszReference, pszDeviceInterface, pulLength, ulFlags);
7214 
7215     return CM_Register_Device_Interface_ExA(dnDevInst, InterfaceClassGuid,
7216                                             pszReference, pszDeviceInterface,
7217                                             pulLength, ulFlags, NULL);
7218 }
7219 
7220 
7221 /***********************************************************************
7222  * CM_Register_Device_InterfaceW [SETUPAPI.@]
7223  */
7224 CONFIGRET
7225 WINAPI
7226 CM_Register_Device_InterfaceW(
7227     _In_ DEVINST dnDevInst,
7228     _In_ LPGUID InterfaceClassGuid,
7229     _In_opt_ LPCWSTR pszReference,
7230     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
7231     _Inout_ PULONG pulLength,
7232     _In_ ULONG ulFlags)
7233 {
7234     TRACE("CM_Register_Device_InterfaceW(%lx %s %s %p %p %lx)\n",
7235           dnDevInst, debugstr_guid(InterfaceClassGuid),
7236           debugstr_w(pszReference), pszDeviceInterface, pulLength, ulFlags);
7237 
7238     return CM_Register_Device_Interface_ExW(dnDevInst, InterfaceClassGuid,
7239                                             pszReference, pszDeviceInterface,
7240                                             pulLength, ulFlags, NULL);
7241 }
7242 
7243 
7244 /***********************************************************************
7245  * CM_Register_Device_Interface_ExA [SETUPAPI.@]
7246  */
7247 CONFIGRET
7248 WINAPI
7249 CM_Register_Device_Interface_ExA(
7250     _In_ DEVINST dnDevInst,
7251     _In_ LPGUID InterfaceClassGuid,
7252     _In_opt_ LPCSTR pszReference,
7253     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
7254     _Inout_ PULONG pulLength,
7255     _In_ ULONG ulFlags,
7256     _In_opt_ HMACHINE hMachine)
7257 {
7258     LPWSTR pszReferenceW = NULL;
7259     LPWSTR pszDeviceInterfaceW = NULL;
7260     ULONG ulLength;
7261     CONFIGRET ret;
7262 
7263     TRACE("CM_Register_Device_Interface_ExA(%lx %s %s %p %p %lx %p)\n",
7264           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_a(pszReference),
7265           pszDeviceInterface, pulLength, ulFlags, hMachine);
7266 
7267     if (pulLength == NULL || pszDeviceInterface == NULL)
7268         return CR_INVALID_POINTER;
7269 
7270     if (pszReference != NULL)
7271     {
7272         if (pSetupCaptureAndConvertAnsiArg(pszReference, &pszReferenceW))
7273             return CR_INVALID_DATA;
7274     }
7275 
7276     ulLength = *pulLength;
7277 
7278     pszDeviceInterfaceW = HeapAlloc(GetProcessHeap(), 0, ulLength * sizeof(WCHAR));
7279     if (pszDeviceInterfaceW == NULL)
7280     {
7281         ret = CR_OUT_OF_MEMORY;
7282         goto Done;
7283     }
7284 
7285     ret = CM_Register_Device_Interface_ExW(dnDevInst,
7286                                            InterfaceClassGuid,
7287                                            pszReferenceW,
7288                                            pszDeviceInterfaceW,
7289                                            &ulLength,
7290                                            ulFlags,
7291                                            hMachine);
7292     if (ret == CR_SUCCESS)
7293     {
7294         if (WideCharToMultiByte(CP_ACP,
7295                                 0,
7296                                 pszDeviceInterfaceW,
7297                                 ulLength,
7298                                 pszDeviceInterface,
7299                                 *pulLength,
7300                                 NULL,
7301                                 NULL) == 0)
7302             ret = CR_FAILURE;
7303     }
7304 
7305     *pulLength = ulLength;
7306 
7307 Done:
7308     if (pszDeviceInterfaceW != NULL)
7309         HeapFree(GetProcessHeap(), 0, pszDeviceInterfaceW);
7310 
7311     if (pszReferenceW != NULL)
7312         MyFree(pszReferenceW);
7313 
7314     return ret;
7315 }
7316 
7317 
7318 /***********************************************************************
7319  * CM_Register_Device_Interface_ExW [SETUPAPI.@]
7320  */
7321 CONFIGRET
7322 WINAPI
7323 CM_Register_Device_Interface_ExW(
7324     _In_ DEVINST dnDevInst,
7325     _In_ LPGUID InterfaceClassGuid,
7326     _In_opt_ LPCWSTR pszReference,
7327     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
7328     _Inout_ PULONG pulLength,
7329     _In_ ULONG ulFlags,
7330     _In_opt_ HMACHINE hMachine)
7331 {
7332     RPC_BINDING_HANDLE BindingHandle = NULL;
7333     HSTRING_TABLE StringTable = NULL;
7334     LPWSTR lpDevInst;
7335     ULONG ulTransferLength;
7336     CONFIGRET ret;
7337 
7338     TRACE("CM_Register_Device_Interface_ExW(%lx %s %s %p %p %lx %p)\n",
7339           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_w(pszReference),
7340           pszDeviceInterface, pulLength, ulFlags, hMachine);
7341 
7342     if (dnDevInst == 0)
7343         return CR_INVALID_DEVNODE;
7344 
7345     if (InterfaceClassGuid == NULL ||
7346         pszDeviceInterface == NULL ||
7347         pulLength == NULL)
7348         return CR_INVALID_POINTER;
7349 
7350     if (ulFlags != 0)
7351         return CR_INVALID_FLAG;
7352 
7353     if (hMachine != NULL)
7354     {
7355         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7356         if (BindingHandle == NULL)
7357             return CR_FAILURE;
7358 
7359         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7360         if (StringTable == 0)
7361             return CR_FAILURE;
7362     }
7363     else
7364     {
7365         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7366             return CR_FAILURE;
7367     }
7368 
7369     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7370     if (lpDevInst == NULL)
7371         return CR_INVALID_DEVNODE;
7372 
7373     ulTransferLength = *pulLength;
7374 
7375     RpcTryExcept
7376     {
7377         ret = PNP_RegisterDeviceClassAssociation(BindingHandle,
7378                                                  lpDevInst,
7379                                                  InterfaceClassGuid,
7380                                                  (LPWSTR)pszReference,
7381                                                  pszDeviceInterface,
7382                                                  pulLength,
7383                                                  &ulTransferLength,
7384                                                  0);
7385     }
7386     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7387     {
7388         ret = RpcStatusToCmStatus(RpcExceptionCode());
7389     }
7390     RpcEndExcept;
7391 
7392     return ret;
7393 }
7394 
7395 
7396 /***********************************************************************
7397  * CM_Remove_SubTree [SETUPAPI.@]
7398  *
7399  * This function is obsolete in Windows XP and above.
7400  */
7401 CONFIGRET
7402 WINAPI
7403 CM_Remove_SubTree(
7404     _In_ DEVINST dnAncestor,
7405     _In_ ULONG ulFlags)
7406 {
7407     TRACE("CM_Remove_SubTree(%lx %lx)\n",
7408           dnAncestor, ulFlags);
7409 
7410     return CR_CALL_NOT_IMPLEMENTED;
7411 }
7412 
7413 
7414 /***********************************************************************
7415  * CM_Remove_SubTree_Ex [SETUPAPI.@]
7416  *
7417  * This function is obsolete in Windows XP and above.
7418  */
7419 CONFIGRET
7420 WINAPI
7421 CM_Remove_SubTree_Ex(
7422     _In_ DEVINST dnAncestor,
7423     _In_ ULONG ulFlags,
7424     _In_opt_ HMACHINE hMachine)
7425 {
7426     TRACE("CM_Remove_SubTree_Ex(%lx %lx %p)\n",
7427           dnAncestor, ulFlags, hMachine);
7428 
7429     return CR_CALL_NOT_IMPLEMENTED;
7430 }
7431 
7432 
7433 /***********************************************************************
7434  * CM_Request_Device_EjectA [SETUPAPI.@]
7435  */
7436 CONFIGRET
7437 WINAPI
7438 CM_Request_Device_EjectA(
7439     _In_ DEVINST dnDevInst,
7440     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7441     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7442     _In_ ULONG ulNameLength,
7443     _In_ ULONG ulFlags)
7444 {
7445     TRACE("CM_Request_Device_EjectA(%lx %p %s %lu %lx)\n",
7446           dnDevInst, pVetoType, debugstr_a(pszVetoName), ulNameLength, ulFlags);
7447 
7448     return CM_Request_Device_Eject_ExA(dnDevInst, pVetoType, pszVetoName,
7449                                        ulNameLength, ulFlags, NULL);
7450 }
7451 
7452 
7453 /***********************************************************************
7454  * CM_Request_Device_EjectW [SETUPAPI.@]
7455  */
7456 CONFIGRET
7457 WINAPI
7458 CM_Request_Device_EjectW(
7459     _In_ DEVINST dnDevInst,
7460     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7461     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7462     _In_ ULONG ulNameLength,
7463     _In_ ULONG ulFlags)
7464 {
7465     TRACE("CM_Request_Device_EjectW(%lx %p %s %lu %lx)\n",
7466           dnDevInst, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags);
7467 
7468     return CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, pszVetoName,
7469                                        ulNameLength, ulFlags, NULL);
7470 }
7471 
7472 
7473 /***********************************************************************
7474  * CM_Request_Device_Eject_ExA [SETUPAPI.@]
7475  */
7476 CONFIGRET
7477 WINAPI
7478 CM_Request_Device_Eject_ExA(
7479     _In_ DEVINST dnDevInst,
7480     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7481     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7482     _In_ ULONG ulNameLength,
7483     _In_ ULONG ulFlags,
7484     _In_opt_ HMACHINE hMachine)
7485 {
7486     LPWSTR lpLocalVetoName;
7487     CONFIGRET ret;
7488 
7489     TRACE("CM_Request_Device_Eject_ExA(%lx %p %s %lu %lx %p)\n",
7490           dnDevInst, pVetoType, debugstr_a(pszVetoName), ulNameLength, ulFlags, hMachine);
7491 
7492     if (pszVetoName == NULL && ulNameLength == 0)
7493         return CR_INVALID_POINTER;
7494 
7495     lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
7496     if (lpLocalVetoName == NULL)
7497         return CR_OUT_OF_MEMORY;
7498 
7499     ret = CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, lpLocalVetoName,
7500                                       ulNameLength, ulFlags, hMachine);
7501     if (ret == CR_REMOVE_VETOED)
7502     {
7503         if (WideCharToMultiByte(CP_ACP,
7504                                 0,
7505                                 lpLocalVetoName,
7506                                 ulNameLength,
7507                                 pszVetoName,
7508                                 ulNameLength,
7509                                 NULL,
7510                                 NULL) == 0)
7511             ret = CR_FAILURE;
7512     }
7513 
7514     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
7515 
7516     return ret;
7517 }
7518 
7519 
7520 /***********************************************************************
7521  * CM_Request_Device_Eject_ExW [SETUPAPI.@]
7522  */
7523 CONFIGRET
7524 WINAPI
7525 CM_Request_Device_Eject_ExW(
7526     _In_ DEVINST dnDevInst,
7527     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7528     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7529     _In_ ULONG ulNameLength,
7530     _In_ ULONG ulFlags,
7531     _In_opt_ HMACHINE hMachine)
7532 {
7533     RPC_BINDING_HANDLE BindingHandle = NULL;
7534     HSTRING_TABLE StringTable = NULL;
7535     LPWSTR lpDevInst;
7536     CONFIGRET ret;
7537 
7538     TRACE("CM_Request_Device_Eject_ExW(%lx %p %s %lu %lx %p)\n",
7539           dnDevInst, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags, hMachine);
7540 
7541     if (dnDevInst == 0)
7542         return CR_INVALID_DEVNODE;
7543 
7544     if (ulFlags != 0)
7545         return CR_INVALID_FLAG;
7546 
7547     if (pszVetoName == NULL && ulNameLength == 0)
7548         return CR_INVALID_POINTER;
7549 
7550     if (hMachine != NULL)
7551     {
7552         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7553         if (BindingHandle == NULL)
7554             return CR_FAILURE;
7555 
7556         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7557         if (StringTable == 0)
7558             return CR_FAILURE;
7559     }
7560     else
7561     {
7562         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7563             return CR_FAILURE;
7564     }
7565 
7566     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7567     if (lpDevInst == NULL)
7568         return CR_INVALID_DEVNODE;
7569 
7570     RpcTryExcept
7571     {
7572         ret = PNP_RequestDeviceEject(BindingHandle,
7573                                      lpDevInst,
7574                                      pVetoType,
7575                                      pszVetoName,
7576                                      ulNameLength,
7577                                      ulFlags);
7578     }
7579     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7580     {
7581         ret = RpcStatusToCmStatus(RpcExceptionCode());
7582     }
7583     RpcEndExcept;
7584 
7585     return ret;
7586 }
7587 
7588 
7589 /***********************************************************************
7590  * CM_Request_Eject_PC [SETUPAPI.@]
7591  */
7592 CONFIGRET
7593 WINAPI
7594 CM_Request_Eject_PC(VOID)
7595 {
7596     TRACE("CM_Request_Eject_PC()\n");
7597 
7598     return CM_Request_Eject_PC_Ex(NULL);
7599 }
7600 
7601 
7602 /***********************************************************************
7603  * CM_Request_Eject_PC_Ex [SETUPAPI.@]
7604  */
7605 CONFIGRET
7606 WINAPI
7607 CM_Request_Eject_PC_Ex(
7608     _In_opt_ HMACHINE hMachine)
7609 {
7610     RPC_BINDING_HANDLE BindingHandle = NULL;
7611     CONFIGRET ret;
7612 
7613     TRACE("CM_Request_Eject_PC_Ex(%p)\n", hMachine);
7614 
7615     if (hMachine != NULL)
7616     {
7617         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7618         if (BindingHandle == NULL)
7619             return CR_FAILURE;
7620     }
7621     else
7622     {
7623         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7624             return CR_FAILURE;
7625     }
7626 
7627     RpcTryExcept
7628     {
7629         ret = PNP_RequestEjectPC(BindingHandle);
7630     }
7631     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7632     {
7633         ret = RpcStatusToCmStatus(RpcExceptionCode());
7634     }
7635     RpcEndExcept;
7636 
7637     return ret;
7638 }
7639 
7640 
7641 /***********************************************************************
7642  * CM_Run_Detection [SETUPAPI.@]
7643  */
7644 CONFIGRET
7645 WINAPI
7646 CM_Run_Detection(
7647     _In_ ULONG ulFlags)
7648 {
7649     TRACE("CM_Run_Detection(%lx)\n", ulFlags);
7650 
7651     return CM_Run_Detection_Ex(ulFlags, NULL);
7652 }
7653 
7654 
7655 /***********************************************************************
7656  * CM_Run_Detection_Ex [SETUPAPI.@]
7657  */
7658 CONFIGRET
7659 WINAPI
7660 CM_Run_Detection_Ex(
7661     _In_ ULONG ulFlags,
7662     _In_opt_ HMACHINE hMachine)
7663 {
7664     RPC_BINDING_HANDLE BindingHandle = NULL;
7665     CONFIGRET ret;
7666 
7667     TRACE("CM_Run_Detection_Ex(%lx %p)\n",
7668           ulFlags, hMachine);
7669 
7670     if (!pSetupIsUserAdmin())
7671         return CR_ACCESS_DENIED;
7672 
7673     if (ulFlags & ~CM_DETECT_BITS)
7674         return CR_INVALID_FLAG;
7675 
7676     if (hMachine != NULL)
7677     {
7678         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7679         if (BindingHandle == NULL)
7680             return CR_FAILURE;
7681     }
7682     else
7683     {
7684         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7685             return CR_FAILURE;
7686     }
7687 
7688     RpcTryExcept
7689     {
7690         ret = PNP_RunDetection(BindingHandle,
7691                                ulFlags);
7692     }
7693     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7694     {
7695         ret = RpcStatusToCmStatus(RpcExceptionCode());
7696     }
7697     RpcEndExcept;
7698 
7699     return ret;
7700 }
7701 
7702 
7703 /***********************************************************************
7704  * CM_Set_Class_Registry_PropertyA [SETUPAPI.@]
7705  */
7706 CONFIGRET
7707 WINAPI
7708 CM_Set_Class_Registry_PropertyA(
7709     _In_ LPGUID ClassGuid,
7710     _In_ ULONG ulProperty,
7711     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7712     _In_ ULONG ulLength,
7713     _In_ ULONG ulFlags,
7714     _In_opt_ HMACHINE hMachine)
7715 {
7716     FIXME("CM_Set_Class_Registry_PropertyA(%p %lx %p %lu %lx %p)\n",
7717           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7718 
7719     return CR_CALL_NOT_IMPLEMENTED;
7720 }
7721 
7722 
7723 /***********************************************************************
7724  * CM_Set_Class_Registry_PropertyW [SETUPAPI.@]
7725  */
7726 CONFIGRET
7727 WINAPI
7728 CM_Set_Class_Registry_PropertyW(
7729     _In_ LPGUID ClassGuid,
7730     _In_ ULONG ulProperty,
7731     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7732     _In_ ULONG ulLength,
7733     _In_ ULONG ulFlags,
7734     _In_opt_ HMACHINE hMachine)
7735 {
7736     FIXME("CM_Set_Class_Registry_PropertyW(%p %lx %p %lu %lx %p)\n",
7737           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7738 
7739     return CR_CALL_NOT_IMPLEMENTED;
7740 }
7741 
7742 
7743 /***********************************************************************
7744  * CM_Set_DevNode_Problem [SETUPAPI.@]
7745  */
7746 CONFIGRET
7747 WINAPI
7748 CM_Set_DevNode_Problem(
7749     _In_ DEVINST dnDevInst,
7750     _In_ ULONG ulProblem,
7751     _In_ ULONG ulFlags)
7752 {
7753     TRACE("CM_Set_DevNode_Problem(%lx %lx %lx)\n",
7754           dnDevInst, ulProblem, ulFlags);
7755 
7756     return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
7757 }
7758 
7759 
7760 /***********************************************************************
7761  * CM_Set_DevNode_Problem_Ex [SETUPAPI.@]
7762  */
7763 CONFIGRET
7764 WINAPI
7765 CM_Set_DevNode_Problem_Ex(
7766     _In_ DEVINST dnDevInst,
7767     _In_ ULONG ulProblem,
7768     _In_ ULONG ulFlags,
7769     _In_opt_ HMACHINE hMachine)
7770 {
7771     RPC_BINDING_HANDLE BindingHandle = NULL;
7772     HSTRING_TABLE StringTable = NULL;
7773     LPWSTR lpDevInst;
7774     CONFIGRET ret;
7775 
7776     TRACE("CM_Set_DevNode_Problem_Ex(%lx %lx %lx %p)\n",
7777           dnDevInst, ulProblem, ulFlags, hMachine);
7778 
7779     if (dnDevInst == 0)
7780         return CR_INVALID_DEVNODE;
7781 
7782     if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
7783         return CR_INVALID_FLAG;
7784 
7785     if (hMachine != NULL)
7786     {
7787         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7788         if (BindingHandle == NULL)
7789             return CR_FAILURE;
7790 
7791         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7792         if (StringTable == 0)
7793             return CR_FAILURE;
7794     }
7795     else
7796     {
7797         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7798             return CR_FAILURE;
7799     }
7800 
7801     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7802     if (lpDevInst == NULL)
7803         return CR_INVALID_DEVNODE;
7804 
7805     RpcTryExcept
7806     {
7807         ret = PNP_SetDeviceProblem(BindingHandle,
7808                                    lpDevInst,
7809                                    ulProblem,
7810                                    ulFlags);
7811     }
7812     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7813     {
7814         ret = RpcStatusToCmStatus(RpcExceptionCode());
7815     }
7816     RpcEndExcept;
7817 
7818     return ret;
7819 }
7820 
7821 
7822 /***********************************************************************
7823  * CM_Set_DevNode_Registry_PropertyA [SETUPAPI.@]
7824  */
7825 CONFIGRET
7826 WINAPI
7827 CM_Set_DevNode_Registry_PropertyA(
7828   _In_ DEVINST dnDevInst,
7829   _In_ ULONG ulProperty,
7830   _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7831   _In_ ULONG ulLength,
7832   _In_ ULONG ulFlags)
7833 {
7834     TRACE("CM_Set_DevNode_Registry_PropertyA(%lx %lu %p %lx %lx)\n",
7835           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7836 
7837     return CM_Set_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
7838                                                 Buffer, ulLength,
7839                                                 ulFlags, NULL);
7840 }
7841 
7842 
7843 /***********************************************************************
7844  * CM_Set_DevNode_Registry_PropertyW [SETUPAPI.@]
7845  */
7846 CONFIGRET
7847 WINAPI
7848 CM_Set_DevNode_Registry_PropertyW(
7849     _In_ DEVINST dnDevInst,
7850     _In_ ULONG ulProperty,
7851     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7852     _In_ ULONG ulLength,
7853     _In_ ULONG ulFlags)
7854 {
7855     TRACE("CM_Set_DevNode_Registry_PropertyW(%lx %lu %p %lx %lx)\n",
7856           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7857 
7858     return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
7859                                                 Buffer, ulLength,
7860                                                 ulFlags, NULL);
7861 }
7862 
7863 
7864 /***********************************************************************
7865  * CM_Set_DevNode_Registry_Property_ExA [SETUPAPI.@]
7866  */
7867 CONFIGRET
7868 WINAPI
7869 CM_Set_DevNode_Registry_Property_ExA(
7870     _In_ DEVINST dnDevInst,
7871     _In_ ULONG ulProperty,
7872     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7873     _In_ ULONG ulLength,
7874     _In_ ULONG ulFlags,
7875     _In_opt_ HMACHINE hMachine)
7876 {
7877     CONFIGRET ret = CR_SUCCESS;
7878     LPWSTR lpBuffer;
7879     ULONG ulType;
7880 
7881     FIXME("CM_Set_DevNode_Registry_Property_ExA(%lx %lu %p %lx %lx %p)\n",
7882           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7883 
7884     if (Buffer == NULL && ulLength != 0)
7885         return CR_INVALID_POINTER;
7886 
7887     if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7888         return CR_INVALID_PROPERTY;
7889 
7890     if (Buffer == NULL)
7891     {
7892         ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7893                                                    ulProperty,
7894                                                    NULL,
7895                                                    0,
7896                                                    ulFlags,
7897                                                    hMachine);
7898     }
7899     else
7900     {
7901         /* Get property type */
7902         ulType = GetRegistryPropertyType(ulProperty);
7903 
7904         /* Allocate buffer if needed */
7905         if (ulType == REG_SZ ||
7906             ulType == REG_MULTI_SZ)
7907         {
7908             lpBuffer = MyMalloc(ulLength * sizeof(WCHAR));
7909             if (lpBuffer == NULL)
7910             {
7911                 ret = CR_OUT_OF_MEMORY;
7912             }
7913             else
7914             {
7915                 if (!MultiByteToWideChar(CP_ACP, 0, Buffer,
7916                                          ulLength, lpBuffer, ulLength))
7917                 {
7918                     MyFree(lpBuffer);
7919                     ret = CR_FAILURE;
7920                 }
7921                 else
7922                 {
7923                     ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7924                                                                ulProperty,
7925                                                                lpBuffer,
7926                                                                ulLength * sizeof(WCHAR),
7927                                                                ulFlags,
7928                                                                hMachine);
7929                     MyFree(lpBuffer);
7930                 }
7931             }
7932         }
7933         else
7934         {
7935             ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7936                                                        ulProperty,
7937                                                        Buffer,
7938                                                        ulLength,
7939                                                        ulFlags,
7940                                                        hMachine);
7941         }
7942 
7943         ret = CR_CALL_NOT_IMPLEMENTED;
7944     }
7945 
7946     return ret;
7947 }
7948 
7949 
7950 /***********************************************************************
7951  * CM_Set_DevNode_Registry_Property_ExW [SETUPAPI.@]
7952  */
7953 CONFIGRET
7954 WINAPI
7955 CM_Set_DevNode_Registry_Property_ExW(
7956     _In_ DEVINST dnDevInst,
7957     _In_ ULONG ulProperty,
7958     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7959     _In_ ULONG ulLength,
7960     _In_ ULONG ulFlags,
7961     _In_opt_ HMACHINE hMachine)
7962 {
7963     RPC_BINDING_HANDLE BindingHandle = NULL;
7964     HSTRING_TABLE StringTable = NULL;
7965     LPWSTR lpDevInst;
7966     ULONG ulType;
7967     CONFIGRET ret;
7968 
7969     TRACE("CM_Set_DevNode_Registry_Property_ExW(%lx %lu %p %lx %lx %p)\n",
7970           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7971 
7972     if (dnDevInst == 0)
7973         return CR_INVALID_DEVNODE;
7974 
7975     if (ulProperty <  CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7976         return CR_INVALID_PROPERTY;
7977 
7978     if (Buffer != NULL && ulLength == 0)
7979         return CR_INVALID_POINTER;
7980 
7981     if (ulFlags != 0)
7982         return CR_INVALID_FLAG;
7983 
7984     if (hMachine != NULL)
7985     {
7986         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7987         if (BindingHandle == NULL)
7988             return CR_FAILURE;
7989 
7990         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7991         if (StringTable == 0)
7992             return CR_FAILURE;
7993     }
7994     else
7995     {
7996         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7997             return CR_FAILURE;
7998     }
7999 
8000     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
8001     if (lpDevInst == NULL)
8002         return CR_INVALID_DEVNODE;
8003 
8004     /* Get property type */
8005     ulType = GetRegistryPropertyType(ulProperty);
8006 
8007     RpcTryExcept
8008     {
8009         ret = PNP_SetDeviceRegProp(BindingHandle,
8010                                    lpDevInst,
8011                                    ulProperty,
8012                                    ulType,
8013                                    (BYTE *)Buffer,
8014                                    ulLength,
8015                                    ulFlags);
8016     }
8017     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8018     {
8019         ret = RpcStatusToCmStatus(RpcExceptionCode());
8020     }
8021     RpcEndExcept;
8022 
8023     return ret;
8024 }
8025 
8026 
8027 /***********************************************************************
8028  * CM_Set_HW_Prof [SETUPAPI.@]
8029  */
8030 CONFIGRET
8031 WINAPI
8032 CM_Set_HW_Prof(
8033     _In_ ULONG ulHardwareProfile,
8034     _In_ ULONG ulFlags)
8035 {
8036     TRACE("CM_Set_HW_Prof(%lu %lx)\n",
8037           ulHardwareProfile, ulFlags);
8038 
8039     return CM_Set_HW_Prof_Ex(ulHardwareProfile, ulFlags, NULL);
8040 }
8041 
8042 
8043 /***********************************************************************
8044  * CM_Set_HW_Prof_Ex [SETUPAPI.@]
8045  */
8046 CONFIGRET
8047 WINAPI
8048 CM_Set_HW_Prof_Ex(
8049     _In_ ULONG ulHardwareProfile,
8050     _In_ ULONG ulFlags,
8051     _In_opt_ HMACHINE hMachine)
8052 {
8053     RPC_BINDING_HANDLE BindingHandle = NULL;
8054     CONFIGRET ret;
8055 
8056     TRACE("CM_Set_HW_Prof_Ex(%lu %lx %p)\n",
8057           ulHardwareProfile, ulFlags, hMachine);
8058 
8059     if (!pSetupIsUserAdmin())
8060         return CR_ACCESS_DENIED;
8061 
8062     if (ulFlags != 0)
8063         return CR_INVALID_FLAG;
8064 
8065     if (hMachine != NULL)
8066     {
8067         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8068         if (BindingHandle == NULL)
8069             return CR_FAILURE;
8070     }
8071     else
8072     {
8073         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8074             return CR_FAILURE;
8075     }
8076 
8077     RpcTryExcept
8078     {
8079         ret = PNP_SetHwProf(BindingHandle, ulHardwareProfile, ulFlags);
8080     }
8081     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8082     {
8083         ret = RpcStatusToCmStatus(RpcExceptionCode());
8084     }
8085     RpcEndExcept;
8086 
8087     return ret;
8088 }
8089 
8090 
8091 /***********************************************************************
8092  * CM_Set_HW_Prof_FlagsA [SETUPAPI.@]
8093  */
8094 CONFIGRET
8095 WINAPI
8096 CM_Set_HW_Prof_FlagsA(
8097     _In_ DEVINSTID_A szDevInstName,
8098     _In_ ULONG ulConfig,
8099     _In_ ULONG ulValue,
8100     _In_ ULONG ulFlags)
8101 {
8102     TRACE("CM_Set_HW_Prof_FlagsA(%s %lu %lu %lx)\n",
8103           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags);
8104 
8105     return CM_Set_HW_Prof_Flags_ExA(szDevInstName, ulConfig, ulValue,
8106                                     ulFlags, NULL);
8107 }
8108 
8109 
8110 /***********************************************************************
8111  * CM_Set_HW_Prof_FlagsW [SETUPAPI.@]
8112  */
8113 CONFIGRET
8114 WINAPI
8115 CM_Set_HW_Prof_FlagsW(
8116     _In_ DEVINSTID_W szDevInstName,
8117     _In_ ULONG ulConfig,
8118     _In_ ULONG ulValue,
8119     _In_ ULONG ulFlags)
8120 {
8121     TRACE("CM_Set_HW_Prof_FlagsW(%s %lu %lu %lx)\n",
8122           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags);
8123 
8124     return CM_Set_HW_Prof_Flags_ExW(szDevInstName, ulConfig, ulValue,
8125                                     ulFlags, NULL);
8126 }
8127 
8128 
8129 /***********************************************************************
8130  * CM_Set_HW_Prof_Flags_ExA [SETUPAPI.@]
8131  */
8132 CONFIGRET
8133 WINAPI
8134 CM_Set_HW_Prof_Flags_ExA(
8135     _In_ DEVINSTID_A szDevInstName,
8136     _In_ ULONG ulConfig,
8137     _In_ ULONG ulValue,
8138     _In_ ULONG ulFlags,
8139     _In_opt_ HMACHINE hMachine)
8140 {
8141     DEVINSTID_W pszDevIdW = NULL;
8142     CONFIGRET ret = CR_SUCCESS;
8143 
8144     TRACE("CM_Set_HW_Prof_Flags_ExA(%s %lu %lu %lx %p)\n",
8145           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
8146 
8147     if (szDevInstName != NULL)
8148     {
8149        if (pSetupCaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
8150          return CR_INVALID_DEVICE_ID;
8151     }
8152 
8153     ret = CM_Set_HW_Prof_Flags_ExW(pszDevIdW, ulConfig, ulValue,
8154                                    ulFlags, hMachine);
8155 
8156     if (pszDevIdW != NULL)
8157         MyFree(pszDevIdW);
8158 
8159     return ret;
8160 }
8161 
8162 
8163 /***********************************************************************
8164  * CM_Set_HW_Prof_Flags_ExW [SETUPAPI.@]
8165  */
8166 CONFIGRET
8167 WINAPI
8168 CM_Set_HW_Prof_Flags_ExW(
8169     _In_ DEVINSTID_W szDevInstName,
8170     _In_ ULONG ulConfig,
8171     _In_ ULONG ulValue,
8172     _In_ ULONG ulFlags,
8173     _In_opt_ HMACHINE hMachine)
8174 {
8175     RPC_BINDING_HANDLE BindingHandle = NULL;
8176     CONFIGRET ret;
8177 
8178     FIXME("CM_Set_HW_Prof_Flags_ExW(%s %lu %lu %lx %p)\n",
8179           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
8180 
8181     if (szDevInstName == NULL)
8182         return CR_INVALID_POINTER;
8183 
8184     if (ulFlags & ~ CM_SET_HW_PROF_FLAGS_BITS)
8185         return CR_INVALID_FLAG;
8186 
8187     /* FIXME: Check whether szDevInstName is valid */
8188 
8189     if (hMachine != NULL)
8190     {
8191         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8192         if (BindingHandle == NULL)
8193             return CR_FAILURE;
8194     }
8195     else
8196     {
8197         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8198             return CR_FAILURE;
8199     }
8200 
8201     RpcTryExcept
8202     {
8203         ret = PNP_HwProfFlags(BindingHandle, PNP_SET_HWPROFFLAGS, szDevInstName,
8204                               ulConfig, &ulValue, NULL, NULL, 0, 0);
8205     }
8206     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8207     {
8208         ret = RpcStatusToCmStatus(RpcExceptionCode());
8209     }
8210     RpcEndExcept;
8211 
8212     return ret;
8213 }
8214 
8215 
8216 /***********************************************************************
8217  * CM_Setup_DevNode [SETUPAPI.@]
8218  */
8219 CONFIGRET
8220 WINAPI
8221 CM_Setup_DevNode(
8222     _In_ DEVINST dnDevInst,
8223     _In_ ULONG ulFlags)
8224 {
8225     TRACE("CM_Setup_DevNode(%lx %lx)\n",
8226           dnDevInst, ulFlags);
8227 
8228     return CM_Setup_DevNode_Ex(dnDevInst, ulFlags, NULL);
8229 }
8230 
8231 
8232 /***********************************************************************
8233  * CM_Setup_DevNode_Ex [SETUPAPI.@]
8234  */
8235 CONFIGRET
8236 WINAPI
8237 CM_Setup_DevNode_Ex(
8238     _In_ DEVINST dnDevInst,
8239     _In_ ULONG ulFlags,
8240     _In_opt_ HMACHINE hMachine)
8241 {
8242     RPC_BINDING_HANDLE BindingHandle = NULL;
8243     HSTRING_TABLE StringTable = NULL;
8244     LPWSTR lpDevInst;
8245     CONFIGRET ret;
8246 
8247     FIXME("CM_Setup_DevNode_Ex(%lx %lx %p)\n",
8248           dnDevInst, ulFlags, hMachine);
8249 
8250     if (!pSetupIsUserAdmin())
8251         return CR_ACCESS_DENIED;
8252 
8253     if (dnDevInst == 0)
8254         return CR_INVALID_DEVNODE;
8255 
8256     if (ulFlags & ~CM_SETUP_BITS)
8257         return CR_INVALID_FLAG;
8258 
8259     if (hMachine != NULL)
8260     {
8261         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8262         if (BindingHandle == NULL)
8263             return CR_FAILURE;
8264 
8265         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
8266         if (StringTable == 0)
8267             return CR_FAILURE;
8268     }
8269     else
8270     {
8271         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8272             return CR_FAILURE;
8273     }
8274 
8275     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
8276     if (lpDevInst == NULL)
8277         return CR_INVALID_DEVNODE;
8278 
8279     RpcTryExcept
8280     {
8281         ret = PNP_DeviceInstanceAction(BindingHandle,
8282                                        PNP_DEVINST_SETUP,
8283                                        ulFlags,
8284                                        lpDevInst,
8285                                        NULL);
8286     }
8287     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8288     {
8289         ret = RpcStatusToCmStatus(RpcExceptionCode());
8290     }
8291     RpcEndExcept;
8292 
8293     return ret;
8294 }
8295 
8296 
8297 /***********************************************************************
8298  * CM_Test_Range_Available [SETUPAPI.@]
8299  */
8300 CONFIGRET
8301 WINAPI
8302 CM_Test_Range_Available(
8303     _In_ DWORDLONG ullStartValue,
8304     _In_ DWORDLONG ullEndValue,
8305     _In_ RANGE_LIST rlh,
8306     _In_ ULONG ulFlags)
8307 {
8308     FIXME("CM_Test_Range_Available(%I64u %I64u %p %lx)\n",
8309           ullStartValue, ullEndValue, rlh, ulFlags);
8310     return CR_CALL_NOT_IMPLEMENTED;
8311 }
8312 
8313 
8314 /***********************************************************************
8315  * CM_Uninstall_DevNode [SETUPAPI.@]
8316  */
8317 CONFIGRET
8318 WINAPI
8319 CM_Uninstall_DevNode(
8320     _In_ DEVINST dnPhantom,
8321     _In_ ULONG ulFlags)
8322 {
8323     TRACE("CM_Uninstall_DevNode(%lx %lx)\n",
8324           dnPhantom, ulFlags);
8325 
8326     return CM_Uninstall_DevNode_Ex(dnPhantom, ulFlags, NULL);
8327 }
8328 
8329 
8330 /***********************************************************************
8331  * CM_Uninstall_DevNode_Ex [SETUPAPI.@]
8332  */
8333 CONFIGRET
8334 WINAPI
8335 CM_Uninstall_DevNode_Ex(
8336     _In_ DEVINST dnPhantom,
8337     _In_ ULONG ulFlags,
8338     _In_opt_ HMACHINE hMachine)
8339 {
8340     RPC_BINDING_HANDLE BindingHandle = NULL;
8341     HSTRING_TABLE StringTable = NULL;
8342     LPWSTR lpDevInst;
8343     CONFIGRET ret;
8344 
8345     TRACE("CM_Uninstall_DevNode_Ex(%lx %lx %p)\n",
8346           dnPhantom, ulFlags, hMachine);
8347 
8348     if (dnPhantom == 0)
8349         return CR_INVALID_DEVNODE;
8350 
8351     if (ulFlags != 0)
8352         return CR_INVALID_FLAG;
8353 
8354     if (hMachine != NULL)
8355     {
8356         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8357         if (BindingHandle == NULL)
8358             return CR_FAILURE;
8359 
8360         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
8361         if (StringTable == 0)
8362             return CR_FAILURE;
8363     }
8364     else
8365     {
8366         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8367             return CR_FAILURE;
8368     }
8369 
8370     lpDevInst = pSetupStringTableStringFromId(StringTable, dnPhantom);
8371     if (lpDevInst == NULL)
8372         return CR_INVALID_DEVNODE;
8373 
8374     RpcTryExcept
8375     {
8376         ret = PNP_UninstallDevInst(BindingHandle,
8377                                    lpDevInst,
8378                                    ulFlags);
8379     }
8380     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8381     {
8382         ret = RpcStatusToCmStatus(RpcExceptionCode());
8383     }
8384     RpcEndExcept;
8385 
8386     return ret;
8387 }
8388 
8389 
8390 /***********************************************************************
8391  * CM_Unregister_Device_InterfaceA [SETUPAPI.@]
8392  */
8393 CONFIGRET
8394 WINAPI
8395 CM_Unregister_Device_InterfaceA(
8396     _In_ LPCSTR pszDeviceInterface,
8397     _In_ ULONG ulFlags)
8398 {
8399     TRACE("CM_Unregister_Device_InterfaceA(%s %lx)\n",
8400           debugstr_a(pszDeviceInterface), ulFlags);
8401 
8402     return CM_Unregister_Device_Interface_ExA(pszDeviceInterface,
8403                                               ulFlags, NULL);
8404 }
8405 
8406 
8407 /***********************************************************************
8408  * CM_Unregister_Device_InterfaceW [SETUPAPI.@]
8409  */
8410 CONFIGRET
8411 WINAPI
8412 CM_Unregister_Device_InterfaceW(
8413     _In_ LPCWSTR pszDeviceInterface,
8414     _In_ ULONG ulFlags)
8415 {
8416     TRACE("CM_Unregister_Device_InterfaceW(%s %lx)\n",
8417           debugstr_w(pszDeviceInterface), ulFlags);
8418 
8419     return CM_Unregister_Device_Interface_ExW(pszDeviceInterface,
8420                                               ulFlags, NULL);
8421 }
8422 
8423 
8424 /***********************************************************************
8425  * CM_Unregister_Device_Interface_ExA [SETUPAPI.@]
8426  */
8427 CONFIGRET
8428 WINAPI
8429 CM_Unregister_Device_Interface_ExA(
8430     _In_ LPCSTR pszDeviceInterface,
8431     _In_ ULONG ulFlags,
8432     _In_opt_ HMACHINE hMachine)
8433 {
8434     LPWSTR pszDeviceInterfaceW = NULL;
8435     CONFIGRET ret;
8436 
8437     TRACE("CM_Unregister_Device_Interface_ExA(%s %lx %p)\n",
8438           debugstr_a(pszDeviceInterface), ulFlags, hMachine);
8439 
8440     if (pszDeviceInterface == NULL)
8441         return CR_INVALID_POINTER;
8442 
8443     if (pSetupCaptureAndConvertAnsiArg(pszDeviceInterface, &pszDeviceInterfaceW))
8444         return CR_INVALID_DATA;
8445 
8446     ret = CM_Unregister_Device_Interface_ExW(pszDeviceInterfaceW,
8447                                              ulFlags, hMachine);
8448 
8449     if (pszDeviceInterfaceW != NULL)
8450         MyFree(pszDeviceInterfaceW);
8451 
8452     return ret;
8453 }
8454 
8455 
8456 /***********************************************************************
8457  * CM_Unregister_Device_Interface_ExW [SETUPAPI.@]
8458  */
8459 CONFIGRET
8460 WINAPI
8461 CM_Unregister_Device_Interface_ExW(
8462     _In_ LPCWSTR pszDeviceInterface,
8463     _In_ ULONG ulFlags,
8464     _In_opt_ HMACHINE hMachine)
8465 {
8466     RPC_BINDING_HANDLE BindingHandle = NULL;
8467     CONFIGRET ret;
8468 
8469     TRACE("CM_Unregister_Device_Interface_ExW(%s %lx %p)\n",
8470           debugstr_w(pszDeviceInterface), ulFlags, hMachine);
8471 
8472     if (pszDeviceInterface == NULL)
8473         return CR_INVALID_POINTER;
8474 
8475     if (ulFlags != 0)
8476         return CR_INVALID_FLAG;
8477 
8478     if (hMachine != NULL)
8479     {
8480         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8481         if (BindingHandle == NULL)
8482             return CR_FAILURE;
8483     }
8484     else
8485     {
8486         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8487             return CR_FAILURE;
8488     }
8489 
8490     RpcTryExcept
8491     {
8492         ret = PNP_UnregisterDeviceClassAssociation(BindingHandle,
8493                                                    (LPWSTR)pszDeviceInterface,
8494                                                    ulFlags);
8495     }
8496     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8497     {
8498         ret = RpcStatusToCmStatus(RpcExceptionCode());
8499     }
8500     RpcEndExcept;
8501 
8502     return ret;
8503 }
8504