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