xref: /reactos/dll/win32/setupapi/cfgmgr.c (revision 177ae91b)
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     TRACE("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_DisableDevInst(BindingHandle,
1834                                  lpDevInst,
1835                                  NULL,
1836                                  NULL,
1837                                  0,
1838                                  ulFlags);
1839     }
1840     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1841     {
1842         ret = RpcStatusToCmStatus(RpcExceptionCode());
1843     }
1844     RpcEndExcept;
1845 
1846     return ret;
1847 }
1848 
1849 
1850 /***********************************************************************
1851  * CM_Disconnect_Machine [SETUPAPI.@]
1852  */
1853 CONFIGRET
1854 WINAPI
1855 CM_Disconnect_Machine(
1856     _In_opt_ HMACHINE hMachine)
1857 {
1858     PMACHINE_INFO pMachine;
1859 
1860     TRACE("CM_Disconnect_Machine(%p)\n", hMachine);
1861 
1862     pMachine = (PMACHINE_INFO)hMachine;
1863     if (pMachine == NULL)
1864         return CR_SUCCESS;
1865 
1866     if (pMachine->bLocal == FALSE)
1867     {
1868         if (pMachine->StringTable != NULL)
1869             pSetupStringTableDestroy(pMachine->StringTable);
1870 
1871         if (!PnpUnbindRpc(pMachine->BindingHandle))
1872             return CR_ACCESS_DENIED;
1873     }
1874 
1875     HeapFree(GetProcessHeap(), 0, pMachine);
1876 
1877     return CR_SUCCESS;
1878 }
1879 
1880 
1881 /***********************************************************************
1882  * CM_Dup_Range_List [SETUPAPI.@]
1883  */
1884 CONFIGRET
1885 WINAPI
1886 CM_Dup_Range_List(
1887     _In_ RANGE_LIST rlhOld,
1888     _In_ RANGE_LIST rlhNew,
1889     _In_ ULONG ulFlags)
1890 {
1891     FIXME("CM_Dup_Range_List(%p %p %lx)\n",
1892           rlhOld, rlhNew, ulFlags);
1893 
1894     return CR_CALL_NOT_IMPLEMENTED;
1895 }
1896 
1897 
1898 /***********************************************************************
1899  * CM_Enable_DevNode [SETUPAPI.@]
1900  */
1901 CONFIGRET
1902 WINAPI
1903 CM_Enable_DevNode(
1904     _In_ DEVINST dnDevInst,
1905     _In_ ULONG ulFlags)
1906 {
1907     TRACE("CM_Enable_DevNode(%p %lx)\n",
1908           dnDevInst, ulFlags);
1909 
1910     return CM_Enable_DevNode_Ex(dnDevInst, ulFlags, NULL);
1911 }
1912 
1913 
1914 /***********************************************************************
1915  * CM_Enable_DevNode_Ex [SETUPAPI.@]
1916  */
1917 CONFIGRET
1918 WINAPI
1919 CM_Enable_DevNode_Ex(
1920     _In_ DEVINST dnDevInst,
1921     _In_ ULONG ulFlags,
1922     _In_opt_ HMACHINE hMachine)
1923 {
1924     RPC_BINDING_HANDLE BindingHandle = NULL;
1925     HSTRING_TABLE StringTable = NULL;
1926     LPWSTR lpDevInst;
1927     CONFIGRET ret;
1928 
1929     TRACE("CM_Enable_DevNode_Ex(%p %lx %p)\n",
1930           dnDevInst, ulFlags, hMachine);
1931 
1932     if (!pSetupIsUserAdmin())
1933         return CR_ACCESS_DENIED;
1934 
1935     if (dnDevInst == 0)
1936         return CR_INVALID_DEVINST;
1937 
1938     if (ulFlags != 0)
1939         return CR_INVALID_FLAG;
1940 
1941     if (hMachine != NULL)
1942     {
1943         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1944         if (BindingHandle == NULL)
1945             return CR_FAILURE;
1946 
1947         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1948         if (StringTable == 0)
1949             return CR_FAILURE;
1950     }
1951     else
1952     {
1953         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1954             return CR_FAILURE;
1955     }
1956 
1957     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
1958     if (lpDevInst == NULL)
1959         return CR_INVALID_DEVNODE;
1960 
1961     RpcTryExcept
1962     {
1963         ret = PNP_DeviceInstanceAction(BindingHandle,
1964                                        PNP_DEVINST_ENABLE,
1965                                        ulFlags,
1966                                        lpDevInst,
1967                                        NULL);
1968     }
1969     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1970     {
1971         ret = RpcStatusToCmStatus(RpcExceptionCode());
1972     }
1973     RpcEndExcept;
1974 
1975     return ret;
1976 }
1977 
1978 
1979 /***********************************************************************
1980  * CM_Enumerate_Classes [SETUPAPI.@]
1981  */
1982 CONFIGRET
1983 WINAPI
1984 CM_Enumerate_Classes(
1985     _In_ ULONG ulClassIndex,
1986     _Out_ LPGUID ClassGuid,
1987     _In_ ULONG ulFlags)
1988 {
1989     TRACE("CM_Enumerate_Classes(%lx %p %lx)\n",
1990           ulClassIndex, ClassGuid, ulFlags);
1991 
1992     return CM_Enumerate_Classes_Ex(ulClassIndex, ClassGuid, ulFlags, NULL);
1993 }
1994 
1995 
1996 /***********************************************************************
1997  * CM_Enumerate_Classes_Ex [SETUPAPI.@]
1998  */
1999 CONFIGRET
2000 WINAPI
2001 CM_Enumerate_Classes_Ex(
2002     _In_ ULONG ulClassIndex,
2003     _Out_ LPGUID ClassGuid,
2004     _In_ ULONG ulFlags,
2005     _In_opt_ HMACHINE hMachine)
2006 {
2007     WCHAR szBuffer[MAX_GUID_STRING_LEN];
2008     RPC_BINDING_HANDLE BindingHandle = NULL;
2009     CONFIGRET ret = CR_SUCCESS;
2010     ULONG ulLength = MAX_GUID_STRING_LEN;
2011 
2012     TRACE("CM_Enumerate_Classes_Ex(%lx %p %lx %p)\n",
2013           ulClassIndex, ClassGuid, ulFlags, hMachine);
2014 
2015     if (ClassGuid == NULL)
2016         return CR_INVALID_POINTER;
2017 
2018     if (ulFlags != 0)
2019         return CR_INVALID_FLAG;
2020 
2021     if (hMachine != NULL)
2022     {
2023         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2024         if (BindingHandle == NULL)
2025             return CR_FAILURE;
2026     }
2027     else
2028     {
2029         if (!PnpGetLocalHandles(&BindingHandle, NULL))
2030             return CR_FAILURE;
2031     }
2032 
2033     RpcTryExcept
2034     {
2035         ret = PNP_EnumerateSubKeys(BindingHandle,
2036                                    PNP_CLASS_SUBKEYS,
2037                                    ulClassIndex,
2038                                    szBuffer,
2039                                    MAX_GUID_STRING_LEN,
2040                                    &ulLength,
2041                                    ulFlags);
2042     }
2043     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2044     {
2045         ret = RpcStatusToCmStatus(RpcExceptionCode());
2046     }
2047     RpcEndExcept;
2048 
2049     if (ret == CR_SUCCESS)
2050     {
2051         /* Remove the {} */
2052         szBuffer[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
2053 
2054         /* Convert the buffer to a GUID */
2055         if (UuidFromStringW(&szBuffer[1], ClassGuid) != RPC_S_OK)
2056             return CR_FAILURE;
2057     }
2058 
2059     return ret;
2060 }
2061 
2062 
2063 /***********************************************************************
2064  * CM_Enumerate_EnumeratorsA [SETUPAPI.@]
2065  */
2066 CONFIGRET
2067 WINAPI
2068 CM_Enumerate_EnumeratorsA(
2069     _In_ ULONG ulEnumIndex,
2070     _Out_writes_(*pulLength) PCHAR Buffer,
2071     _Inout_ PULONG pulLength,
2072     _In_ ULONG ulFlags)
2073 {
2074     TRACE("CM_Enumerate_EnumeratorsA(%lu %p %p %lx)\n",
2075           ulEnumIndex, Buffer, pulLength, ulFlags);
2076 
2077     return CM_Enumerate_Enumerators_ExA(ulEnumIndex, Buffer, pulLength,
2078                                         ulFlags, NULL);
2079 }
2080 
2081 
2082 /***********************************************************************
2083  * CM_Enumerate_EnumeratorsW [SETUPAPI.@]
2084  */
2085 CONFIGRET
2086 WINAPI
2087 CM_Enumerate_EnumeratorsW(
2088     _In_ ULONG ulEnumIndex,
2089     _Out_writes_(*pulLength) PWCHAR Buffer,
2090     _Inout_ PULONG pulLength,
2091     _In_ ULONG ulFlags)
2092 {
2093     TRACE("CM_Enumerate_EnumeratorsW(%lu %p %p %lx)\n",
2094           ulEnumIndex, Buffer, pulLength, ulFlags);
2095 
2096     return CM_Enumerate_Enumerators_ExW(ulEnumIndex, Buffer, pulLength,
2097                                         ulFlags, NULL);
2098 }
2099 
2100 
2101 /***********************************************************************
2102  * CM_Enumerate_Enumerators_ExA [SETUPAPI.@]
2103  */
2104 CONFIGRET
2105 WINAPI
2106 CM_Enumerate_Enumerators_ExA(
2107     _In_ ULONG ulEnumIndex,
2108     _Out_writes_(*pulLength) PCHAR Buffer,
2109     _Inout_ PULONG pulLength,
2110     _In_ ULONG ulFlags,
2111     _In_opt_ HMACHINE hMachine)
2112 {
2113     WCHAR szBuffer[MAX_DEVICE_ID_LEN];
2114     ULONG ulOrigLength;
2115     ULONG ulLength;
2116     CONFIGRET ret = CR_SUCCESS;
2117 
2118     TRACE("CM_Enumerate_Enumerators_ExA(%lu %p %p %lx %p)\n",
2119           ulEnumIndex, Buffer, pulLength, ulFlags, hMachine);
2120 
2121     if (Buffer == NULL || pulLength == NULL)
2122         return CR_INVALID_POINTER;
2123 
2124     if (ulFlags != 0)
2125         return CR_INVALID_FLAG;
2126 
2127     ulOrigLength = *pulLength;
2128     *pulLength = 0;
2129 
2130     ulLength = MAX_DEVICE_ID_LEN;
2131     ret = CM_Enumerate_Enumerators_ExW(ulEnumIndex, szBuffer, &ulLength,
2132                                        ulFlags, hMachine);
2133     if (ret == CR_SUCCESS)
2134     {
2135         if (WideCharToMultiByte(CP_ACP,
2136                                 0,
2137                                 szBuffer,
2138                                 ulLength,
2139                                 Buffer,
2140                                 ulOrigLength,
2141                                 NULL,
2142                                 NULL) == 0)
2143             ret = CR_FAILURE;
2144         else
2145             *pulLength = lstrlenA(Buffer) + 1;
2146     }
2147 
2148     return ret;
2149 }
2150 
2151 
2152 /***********************************************************************
2153  * CM_Enumerate_Enumerators_ExW [SETUPAPI.@]
2154  */
2155 CONFIGRET
2156 WINAPI
2157 CM_Enumerate_Enumerators_ExW(
2158     _In_ ULONG ulEnumIndex,
2159     _Out_writes_(*pulLength) PWCHAR Buffer,
2160     _Inout_ PULONG pulLength,
2161     _In_ ULONG ulFlags,
2162     _In_opt_ HMACHINE hMachine)
2163 {
2164     RPC_BINDING_HANDLE BindingHandle = NULL;
2165     CONFIGRET ret;
2166 
2167     TRACE("CM_Enumerate_Enumerators_ExW(%lu %p %p %lx %p)\n",
2168           ulEnumIndex, Buffer, pulLength, ulFlags, hMachine);
2169 
2170     if (Buffer == NULL || pulLength == NULL)
2171         return CR_INVALID_POINTER;
2172 
2173     if (ulFlags != 0)
2174         return CR_INVALID_FLAG;
2175 
2176     *Buffer = UNICODE_NULL;
2177 
2178     if (hMachine != NULL)
2179     {
2180         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2181         if (BindingHandle == NULL)
2182             return CR_FAILURE;
2183     }
2184     else
2185     {
2186         if (!PnpGetLocalHandles(&BindingHandle, NULL))
2187             return CR_FAILURE;
2188     }
2189 
2190     RpcTryExcept
2191     {
2192         ret = PNP_EnumerateSubKeys(BindingHandle,
2193                                    PNP_ENUMERATOR_SUBKEYS,
2194                                    ulEnumIndex,
2195                                    Buffer,
2196                                    *pulLength,
2197                                    pulLength,
2198                                    ulFlags);
2199     }
2200     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2201     {
2202         ret = RpcStatusToCmStatus(RpcExceptionCode());
2203     }
2204     RpcEndExcept;
2205 
2206     return ret;
2207 }
2208 
2209 
2210 /***********************************************************************
2211  * CM_Find_Range [SETUPAPI.@]
2212  */
2213 CONFIGRET
2214 WINAPI
2215 CM_Find_Range(
2216     _Out_ PDWORDLONG pullStart,
2217     _In_ DWORDLONG ullStart,
2218     _In_ ULONG ulLength,
2219     _In_ DWORDLONG ullAlignment,
2220     _In_ DWORDLONG ullEnd,
2221     _In_ RANGE_LIST rlh,
2222     _In_ ULONG ulFlags)
2223 {
2224     FIXME("CM_Find_Range(%p %I64u %lu %I64u %I64u %p %lx)\n",
2225           pullStart, ullStart, ulLength, ullAlignment, ullEnd, rlh, ulFlags);
2226 
2227     return CR_CALL_NOT_IMPLEMENTED;
2228 }
2229 
2230 
2231 /***********************************************************************
2232  * CM_First_Range [SETUPAPI.@]
2233  */
2234 CONFIGRET
2235 WINAPI
2236 CM_First_Range(
2237     _In_ RANGE_LIST rlh,
2238     _Out_ PDWORDLONG pullStart,
2239     _Out_ PDWORDLONG pullEnd,
2240     _Out_ PRANGE_ELEMENT preElement,
2241     _In_ ULONG ulFlags)
2242 {
2243     PINTERNAL_RANGE_LIST pRangeList;
2244     PINTERNAL_RANGE pRange;
2245     PLIST_ENTRY ListEntry;
2246     CONFIGRET ret = CR_SUCCESS;
2247 
2248     FIXME("CM_First_Range(%p %p %p %p %lx)\n",
2249           rlh, pullStart, pullEnd, preElement, ulFlags);
2250 
2251     pRangeList = (PINTERNAL_RANGE_LIST)rlh;
2252 
2253     if (!IsValidRangeList(pRangeList))
2254         return CR_INVALID_RANGE_LIST;
2255 
2256     if (pullStart == NULL || pullEnd == NULL || preElement == NULL)
2257         return CR_INVALID_POINTER;
2258 
2259     if (ulFlags != 0)
2260         return CR_INVALID_FLAG;
2261 
2262     /* Lock the range list */
2263     WaitForSingleObject(pRangeList->hMutex, INFINITE);
2264 
2265     /* Fail, if the list is empty */
2266     if (IsListEmpty(&pRangeList->ListHead))
2267     {
2268         ret = CR_FAILURE;
2269         goto done;
2270     }
2271 
2272     /* Get the first range */
2273     ListEntry = pRangeList->ListHead.Flink;
2274     pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
2275 
2276     /* Return the range data */
2277     *pullStart = pRange->ullStart;
2278     *pullEnd = pRange->ullEnd;
2279     *preElement = (RANGE_ELEMENT)pRange;
2280 
2281 done:
2282     /* Unlock the range list */
2283     ReleaseMutex(pRangeList->hMutex);
2284 
2285     return ret;
2286 }
2287 
2288 
2289 /***********************************************************************
2290  * CM_Free_Log_Conf [SETUPAPI.@]
2291  */
2292 CONFIGRET
2293 WINAPI
2294 CM_Free_Log_Conf(
2295     _In_ LOG_CONF lcLogConfToBeFreed,
2296     _In_ ULONG ulFlags)
2297 {
2298     TRACE("CM_Free_Log_Conf(%lx %lx)\n",
2299           lcLogConfToBeFreed, ulFlags);
2300 
2301     return CM_Free_Log_Conf_Ex(lcLogConfToBeFreed, ulFlags, NULL);
2302 }
2303 
2304 
2305 /***********************************************************************
2306  * CM_Free_Log_Conf_Ex [SETUPAPI.@]
2307  */
2308 CONFIGRET
2309 WINAPI
2310 CM_Free_Log_Conf_Ex(
2311     _In_ LOG_CONF lcLogConfToBeFreed,
2312     _In_ ULONG ulFlags,
2313     _In_opt_ HMACHINE hMachine)
2314 {
2315     RPC_BINDING_HANDLE BindingHandle = NULL;
2316     HSTRING_TABLE StringTable = NULL;
2317     LPWSTR lpDevInst;
2318     PLOG_CONF_INFO pLogConfInfo;
2319     CONFIGRET ret;
2320 
2321     TRACE("CM_Free_Log_Conf_Ex(%lx %lx %p)\n",
2322           lcLogConfToBeFreed, ulFlags, hMachine);
2323 
2324     if (!pSetupIsUserAdmin())
2325         return CR_ACCESS_DENIED;
2326 
2327     pLogConfInfo = (PLOG_CONF_INFO)lcLogConfToBeFreed;
2328     if (!IsValidLogConf(pLogConfInfo))
2329         return CR_INVALID_LOG_CONF;
2330 
2331     if (ulFlags != 0)
2332         return CR_INVALID_FLAG;
2333 
2334     if (hMachine != NULL)
2335     {
2336         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2337         if (BindingHandle == NULL)
2338             return CR_FAILURE;
2339 
2340         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
2341         if (StringTable == 0)
2342             return CR_FAILURE;
2343     }
2344     else
2345     {
2346         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
2347             return CR_FAILURE;
2348     }
2349 
2350     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
2351     if (lpDevInst == NULL)
2352         return CR_INVALID_DEVNODE;
2353 
2354     RpcTryExcept
2355     {
2356         ret = PNP_FreeLogConf(BindingHandle, lpDevInst, pLogConfInfo->ulFlags,
2357                               pLogConfInfo->ulTag, 0);
2358     }
2359     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2360     {
2361         ret = RpcStatusToCmStatus(RpcExceptionCode());
2362     }
2363     RpcEndExcept;
2364 
2365     return ret;
2366 }
2367 
2368 
2369 /***********************************************************************
2370  * CM_Free_Log_Conf_Handle [SETUPAPI.@]
2371  */
2372 CONFIGRET
2373 WINAPI
2374 CM_Free_Log_Conf_Handle(
2375     _In_ LOG_CONF lcLogConf)
2376 {
2377     PLOG_CONF_INFO pLogConfInfo;
2378 
2379     TRACE("CM_Free_Log_Conf_Handle(%lx)\n", lcLogConf);
2380 
2381     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
2382     if (!IsValidLogConf(pLogConfInfo))
2383         return CR_INVALID_LOG_CONF;
2384 
2385     HeapFree(GetProcessHeap(), 0, pLogConfInfo);
2386 
2387     return CR_SUCCESS;
2388 }
2389 
2390 
2391 /***********************************************************************
2392  * CM_Free_Range_List [SETUPAPI.@]
2393  */
2394 CONFIGRET
2395 WINAPI
2396 CM_Free_Range_List(
2397     _In_ RANGE_LIST RangeList,
2398     _In_ ULONG ulFlags)
2399 {
2400     PINTERNAL_RANGE_LIST pRangeList;
2401     PINTERNAL_RANGE pRange;
2402     PLIST_ENTRY ListEntry;
2403 
2404     FIXME("CM_Free_Range_List(%p %lx)\n",
2405           RangeList, ulFlags);
2406 
2407     pRangeList = (PINTERNAL_RANGE_LIST)RangeList;
2408 
2409     if (!IsValidRangeList(pRangeList))
2410         return CR_INVALID_RANGE_LIST;
2411 
2412     if (ulFlags != 0)
2413         return CR_INVALID_FLAG;
2414 
2415     /* Lock the range list */
2416     WaitForSingleObject(pRangeList->hMutex, INFINITE);
2417 
2418     /* Free the list of ranges */
2419     while (!IsListEmpty(&pRangeList->ListHead))
2420     {
2421         ListEntry = RemoveHeadList(&pRangeList->ListHead);
2422         pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
2423         HeapFree(GetProcessHeap(), 0, pRange);
2424     }
2425 
2426     /* Unlock the range list */
2427     ReleaseMutex(pRangeList->hMutex);
2428 
2429     /* Close the mutex */
2430     CloseHandle(pRangeList->hMutex);
2431 
2432     /* Free the range list */
2433     HeapFree(GetProcessHeap(), 0, pRangeList);
2434 
2435     return CR_SUCCESS;
2436 }
2437 
2438 
2439 /***********************************************************************
2440  * CM_Free_Res_Des [SETUPAPI.@]
2441  */
2442 CONFIGRET
2443 WINAPI
2444 CM_Free_Res_Des(
2445     _Out_ PRES_DES prdResDes,
2446     _In_ RES_DES rdResDes,
2447     _In_ ULONG ulFlags)
2448 {
2449     TRACE("CM_Free_Res_Des(%p %p %lx)\n",
2450           prdResDes, rdResDes, ulFlags);
2451 
2452     return CM_Free_Res_Des_Ex(prdResDes, rdResDes, ulFlags, NULL);
2453 }
2454 
2455 
2456 /***********************************************************************
2457  * CM_Free_Res_Des_Ex [SETUPAPI.@]
2458  */
2459 CONFIGRET
2460 WINAPI
2461 CM_Free_Res_Des_Ex(
2462     _Out_ PRES_DES prdResDes,
2463     _In_ RES_DES rdResDes,
2464     _In_ ULONG ulFlags,
2465     _In_opt_ HMACHINE hMachine)
2466 {
2467     FIXME("CM_Free_Res_Des_Ex(%p %p %lx %p)\n",
2468           prdResDes, rdResDes, ulFlags, hMachine);
2469 
2470     return CR_CALL_NOT_IMPLEMENTED;
2471 }
2472 
2473 
2474 /***********************************************************************
2475  * CM_Free_Res_Des_Handle [SETUPAPI.@]
2476  */
2477 CONFIGRET
2478 WINAPI
2479 CM_Free_Res_Des_Handle(
2480     _In_ RES_DES rdResDes)
2481 {
2482     FIXME("CM_Free_Res_Des_Handle(%p)\n", rdResDes);
2483 
2484     return CR_CALL_NOT_IMPLEMENTED;
2485 }
2486 
2487 
2488 /***********************************************************************
2489  * CM_Free_Resource_Conflict_Handle [SETUPAPI.@]
2490  */
2491 CONFIGRET
2492 WINAPI
2493 CM_Free_Resource_Conflict_Handle(
2494     _In_ CONFLICT_LIST clConflictList)
2495 {
2496     PCONFLICT_DATA pConflictData;
2497 
2498     FIXME("CM_Free_Resource_Conflict_Handle(%p)\n",
2499           clConflictList);
2500 
2501     pConflictData = (PCONFLICT_DATA)clConflictList;
2502     if (!IsValidConflictData(pConflictData))
2503         return CR_INVALID_CONFLICT_LIST;
2504 
2505     if (pConflictData->pConflictList != NULL)
2506         MyFree(pConflictData->pConflictList);
2507 
2508     MyFree(pConflictData);
2509 
2510     return CR_SUCCESS;
2511 }
2512 
2513 
2514 /***********************************************************************
2515  * CM_Get_Child [SETUPAPI.@]
2516  */
2517 CONFIGRET
2518 WINAPI
2519 CM_Get_Child(
2520     _Out_ PDEVINST pdnDevInst,
2521     _In_ DEVINST dnDevInst,
2522     _In_ ULONG ulFlags)
2523 {
2524     TRACE("CM_Get_Child(%p %p %lx)\n",
2525           pdnDevInst, dnDevInst, ulFlags);
2526 
2527     return CM_Get_Child_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
2528 }
2529 
2530 
2531 /***********************************************************************
2532  * CM_Get_Child_Ex [SETUPAPI.@]
2533  */
2534 CONFIGRET
2535 WINAPI
2536 CM_Get_Child_Ex(
2537     _Out_ PDEVINST pdnDevInst,
2538     _In_ DEVINST dnDevInst,
2539     _In_ ULONG ulFlags,
2540     _In_opt_ HMACHINE hMachine)
2541 {
2542     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
2543     RPC_BINDING_HANDLE BindingHandle = NULL;
2544     HSTRING_TABLE StringTable = NULL;
2545     LPWSTR lpDevInst;
2546     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
2547     CONFIGRET ret;
2548 
2549     TRACE("CM_Get_Child_Ex(%p %lx %lx %p)\n",
2550           pdnDevInst, dnDevInst, ulFlags, hMachine);
2551 
2552     if (pdnDevInst == NULL)
2553         return CR_INVALID_POINTER;
2554 
2555     if (dnDevInst == 0)
2556         return CR_INVALID_DEVINST;
2557 
2558     if (ulFlags != 0)
2559         return CR_INVALID_FLAG;
2560 
2561     *pdnDevInst = -1;
2562 
2563     if (hMachine != NULL)
2564     {
2565         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2566         if (BindingHandle == NULL)
2567             return CR_FAILURE;
2568 
2569         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
2570         if (StringTable == 0)
2571             return CR_FAILURE;
2572     }
2573     else
2574     {
2575         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
2576             return CR_FAILURE;
2577     }
2578 
2579     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
2580     if (lpDevInst == NULL)
2581         return CR_INVALID_DEVNODE;
2582 
2583     RpcTryExcept
2584     {
2585         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
2586                                            PNP_GET_CHILD_DEVICE_INSTANCE,
2587                                            lpDevInst,
2588                                            szRelatedDevInst,
2589                                            &dwLength,
2590                                            0);
2591     }
2592     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2593     {
2594         ret = RpcStatusToCmStatus(RpcExceptionCode());
2595     }
2596     RpcEndExcept;
2597 
2598     if (ret != CR_SUCCESS)
2599         return ret;
2600 
2601     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
2602 
2603     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
2604     if (dwIndex == -1)
2605         return CR_FAILURE;
2606 
2607     *pdnDevInst = dwIndex;
2608 
2609     return CR_SUCCESS;
2610 }
2611 
2612 
2613 /***********************************************************************
2614  * CM_Get_Class_Key_NameA [SETUPAPI.@]
2615  */
2616 CONFIGRET
2617 WINAPI
2618 CM_Get_Class_Key_NameA(
2619     _In_ LPGUID ClassGuid,
2620     _Out_writes_opt_(*pulLength) LPSTR pszKeyName,
2621     _Inout_ PULONG pulLength,
2622     _In_ ULONG ulFlags)
2623 {
2624     TRACE("CM_Get_Class_Key_NameA(%p %p %p %lx)\n",
2625           ClassGuid, pszKeyName, pulLength, ulFlags);
2626 
2627     return CM_Get_Class_Key_Name_ExA(ClassGuid, pszKeyName, pulLength,
2628                                      ulFlags, NULL);
2629 }
2630 
2631 
2632 /***********************************************************************
2633  * CM_Get_Class_Key_NameW [SETUPAPI.@]
2634  */
2635 CONFIGRET
2636 WINAPI
2637 CM_Get_Class_Key_NameW(
2638     _In_ LPGUID ClassGuid,
2639     _Out_writes_opt_(*pulLength) LPWSTR pszKeyName,
2640     _Inout_ PULONG pulLength,
2641     _In_ ULONG ulFlags)
2642 {
2643     TRACE("CM_Get_Class_Key_NameW(%p %p %p %lx)\n",
2644           ClassGuid, pszKeyName, pulLength, ulFlags);
2645 
2646     return CM_Get_Class_Key_Name_ExW(ClassGuid, pszKeyName, pulLength,
2647                                      ulFlags, NULL);
2648 }
2649 
2650 
2651 /***********************************************************************
2652  * CM_Get_Class_Key_Name_ExA [SETUPAPI.@]
2653  */
2654 CONFIGRET
2655 WINAPI
2656 CM_Get_Class_Key_Name_ExA(
2657     _In_ LPGUID ClassGuid,
2658     _Out_writes_opt_(*pulLength) LPSTR pszKeyName,
2659     _Inout_ PULONG pulLength,
2660     _In_ ULONG ulFlags,
2661     _In_opt_ HMACHINE hMachine)
2662 {
2663     WCHAR szBuffer[MAX_GUID_STRING_LEN];
2664     CONFIGRET ret = CR_SUCCESS;
2665     ULONG ulLength;
2666     ULONG ulOrigLength;
2667 
2668     TRACE("CM_Get_Class_Key_Name_ExA(%p %p %p %lx %p)\n",
2669           ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
2670 
2671     if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
2672         return CR_INVALID_POINTER;
2673 
2674     ulOrigLength = *pulLength;
2675     *pulLength = 0;
2676 
2677     ulLength = MAX_GUID_STRING_LEN;
2678     ret = CM_Get_Class_Key_Name_ExW(ClassGuid, szBuffer, &ulLength,
2679                                     ulFlags, hMachine);
2680     if (ret == CR_SUCCESS)
2681     {
2682         if (WideCharToMultiByte(CP_ACP,
2683                                 0,
2684                                 szBuffer,
2685                                 ulLength,
2686                                 pszKeyName,
2687                                 ulOrigLength,
2688                                 NULL,
2689                                 NULL) == 0)
2690             ret = CR_FAILURE;
2691         else
2692             *pulLength = lstrlenA(pszKeyName) + 1;
2693     }
2694 
2695     return CR_SUCCESS;
2696 }
2697 
2698 
2699 /***********************************************************************
2700  * CM_Get_Class_Key_Name_ExW [SETUPAPI.@]
2701  */
2702 CONFIGRET
2703 WINAPI
2704 CM_Get_Class_Key_Name_ExW(
2705     _In_ LPGUID ClassGuid,
2706     _Out_writes_opt_(*pulLength) LPWSTR pszKeyName,
2707     _Inout_ PULONG pulLength,
2708     _In_ ULONG ulFlags,
2709     _In_opt_ HMACHINE hMachine)
2710 {
2711     TRACE("CM_Get_Class_Key_Name_ExW(%p %p %p %lx %p)\n",
2712           ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
2713 
2714     if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
2715         return CR_INVALID_POINTER;
2716 
2717     if (ulFlags != 0)
2718         return CR_INVALID_FLAG;
2719 
2720     if (*pulLength < MAX_GUID_STRING_LEN)
2721     {
2722         *pulLength = 0;
2723         return CR_BUFFER_SMALL;
2724     }
2725 
2726     if (!GuidToString(ClassGuid, pszKeyName))
2727         return CR_INVALID_DATA;
2728 
2729     *pulLength = MAX_GUID_STRING_LEN;
2730 
2731     return CR_SUCCESS;
2732 }
2733 
2734 
2735 /***********************************************************************
2736  * CM_Get_Class_NameA [SETUPAPI.@]
2737  */
2738 CONFIGRET
2739 WINAPI
2740 CM_Get_Class_NameA(
2741     _In_ LPGUID ClassGuid,
2742     _Out_writes_opt_(*pulLength) PCHAR Buffer,
2743     _Inout_ PULONG pulLength,
2744     _In_ ULONG ulFlags)
2745 {
2746     TRACE("CM_Get_Class_NameA(%p %p %p %lx)\n",
2747           ClassGuid, Buffer, pulLength, ulFlags);
2748 
2749     return CM_Get_Class_Name_ExA(ClassGuid, Buffer, pulLength, ulFlags,
2750                                  NULL);
2751 }
2752 
2753 
2754 /***********************************************************************
2755  * CM_Get_Class_NameW [SETUPAPI.@]
2756  */
2757 CONFIGRET
2758 WINAPI
2759 CM_Get_Class_NameW(
2760     _In_ LPGUID ClassGuid,
2761     _Out_writes_opt_(*pulLength) PWCHAR Buffer,
2762     _Inout_ PULONG pulLength,
2763     _In_ ULONG ulFlags)
2764 {
2765     TRACE("CM_Get_Class_NameW(%p %p %p %lx)\n",
2766           ClassGuid, Buffer, pulLength, ulFlags);
2767 
2768     return CM_Get_Class_Name_ExW(ClassGuid, Buffer, pulLength, ulFlags,
2769                                  NULL);
2770 }
2771 
2772 
2773 /***********************************************************************
2774  * CM_Get_Class_Name_ExA [SETUPAPI.@]
2775  */
2776 CONFIGRET
2777 WINAPI
2778 CM_Get_Class_Name_ExA(
2779     _In_ LPGUID ClassGuid,
2780     _Out_writes_opt_(*pulLength) PCHAR Buffer,
2781     _Inout_ PULONG pulLength,
2782     _In_ ULONG ulFlags,
2783     _In_opt_ HMACHINE hMachine)
2784 {
2785     WCHAR szBuffer[MAX_CLASS_NAME_LEN];
2786     CONFIGRET ret = CR_SUCCESS;
2787     ULONG ulLength;
2788     ULONG ulOrigLength;
2789 
2790     TRACE("CM_Get_Class_Name_ExA(%p %p %p %lx %p)\n",
2791           ClassGuid, Buffer, pulLength, ulFlags, hMachine);
2792 
2793     if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
2794         return CR_INVALID_POINTER;
2795 
2796     ulOrigLength = *pulLength;
2797     *pulLength = 0;
2798 
2799     ulLength = MAX_CLASS_NAME_LEN;
2800     ret = CM_Get_Class_Name_ExW(ClassGuid, szBuffer, &ulLength,
2801                                 ulFlags, hMachine);
2802     if (ret == CR_SUCCESS)
2803     {
2804         if (WideCharToMultiByte(CP_ACP,
2805                                 0,
2806                                 szBuffer,
2807                                 ulLength,
2808                                 Buffer,
2809                                 ulOrigLength,
2810                                 NULL,
2811                                 NULL) == 0)
2812             ret = CR_FAILURE;
2813         else
2814             *pulLength = lstrlenA(Buffer) + 1;
2815     }
2816 
2817     return ret;
2818 }
2819 
2820 
2821 /***********************************************************************
2822  * CM_Get_Class_Name_ExW [SETUPAPI.@]
2823  */
2824 CONFIGRET
2825 WINAPI
2826 CM_Get_Class_Name_ExW(
2827     _In_ LPGUID ClassGuid,
2828     _Out_writes_opt_(*pulLength) PWCHAR Buffer,
2829     _Inout_ PULONG pulLength,
2830     _In_ ULONG ulFlags,
2831     _In_opt_ HMACHINE hMachine)
2832 {
2833     WCHAR szGuidString[MAX_GUID_STRING_LEN];
2834     RPC_BINDING_HANDLE BindingHandle = NULL;
2835     CONFIGRET ret;
2836 
2837     TRACE("CM_Get_Class_Name_ExW(%p %p %p %lx %p\n",
2838           ClassGuid, Buffer, pulLength, ulFlags, hMachine);
2839 
2840     if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
2841         return CR_INVALID_POINTER;
2842 
2843     if (ulFlags != 0)
2844         return CR_INVALID_FLAG;
2845 
2846     if (!GuidToString(ClassGuid, szGuidString))
2847         return CR_INVALID_DATA;
2848 
2849     TRACE("Guid %s\n", debugstr_w(szGuidString));
2850 
2851     if (hMachine != NULL)
2852     {
2853         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
2854         if (BindingHandle == NULL)
2855             return CR_FAILURE;
2856     }
2857     else
2858     {
2859         if (!PnpGetLocalHandles(&BindingHandle, NULL))
2860             return CR_FAILURE;
2861     }
2862 
2863     RpcTryExcept
2864     {
2865         ret = PNP_GetClassName(BindingHandle,
2866                                szGuidString,
2867                                Buffer,
2868                                pulLength,
2869                                ulFlags);
2870     }
2871     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2872     {
2873         ret = RpcStatusToCmStatus(RpcExceptionCode());
2874     }
2875     RpcEndExcept;
2876 
2877     return ret;
2878 }
2879 
2880 
2881 /***********************************************************************
2882  * CM_Get_Class_Registry_PropertyA [SETUPAPI.@]
2883  */
2884 CONFIGRET
2885 WINAPI
2886 CM_Get_Class_Registry_PropertyA(
2887     LPGUID ClassGuid,
2888     ULONG ulProperty,
2889     PULONG pulRegDataType,
2890     PVOID Buffer,
2891     PULONG pulLength,
2892     ULONG ulFlags,
2893     HMACHINE hMachine)
2894 {
2895     PWSTR BufferW = NULL;
2896     ULONG ulLength = 0;
2897     ULONG ulType;
2898     CONFIGRET ret;
2899 
2900     TRACE("CM_Get_Class_Registry_PropertyA(%p %lu %p %p %p %lx %p)\n",
2901           ClassGuid, ulProperty, pulRegDataType, Buffer, pulLength,
2902           ulFlags, hMachine);
2903 
2904     if (pulLength == NULL)
2905         return CR_INVALID_POINTER;
2906 
2907     if (ulProperty < CM_CRP_MIN || ulProperty > CM_CRP_MAX)
2908         return CR_INVALID_PROPERTY;
2909 
2910     ulType = GetRegistryPropertyType(ulProperty);
2911     if (ulType == REG_SZ || ulType == REG_MULTI_SZ)
2912     {
2913         /* Get the required buffer size */
2914         ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2915                                               NULL, &ulLength, ulFlags, hMachine);
2916         if (ret != CR_BUFFER_SMALL)
2917             return ret;
2918 
2919         /* Allocate the unicode buffer */
2920         BufferW = HeapAlloc(GetProcessHeap(), 0, ulLength);
2921         if (BufferW == NULL)
2922             return CR_OUT_OF_MEMORY;
2923 
2924         /* Get the property */
2925         ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2926                                               BufferW, &ulLength, ulFlags, hMachine);
2927         if (ret != CR_SUCCESS)
2928         {
2929             HeapFree(GetProcessHeap(), 0, BufferW);
2930             return ret;
2931         }
2932 
2933         /* Do W->A conversion */
2934         *pulLength = WideCharToMultiByte(CP_ACP,
2935                                          0,
2936                                          BufferW,
2937                                          lstrlenW(BufferW) + 1,
2938                                          Buffer,
2939                                          *pulLength,
2940                                          NULL,
2941                                          NULL);
2942 
2943         /* Release the unicode buffer */
2944         HeapFree(GetProcessHeap(), 0, BufferW);
2945 
2946         if (*pulLength == 0)
2947             ret = CR_FAILURE;
2948     }
2949     else
2950     {
2951         /* Get the property */
2952         ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
2953                                               Buffer, pulLength, ulFlags, hMachine);
2954     }
2955 
2956     return ret;
2957 }
2958 
2959 
2960 /***********************************************************************
2961  * CM_Get_Class_Registry_PropertyW [SETUPAPI.@]
2962  */
2963 CONFIGRET
2964 WINAPI
2965 CM_Get_Class_Registry_PropertyW(
2966     LPGUID ClassGuid,
2967     ULONG ulProperty,
2968     PULONG pulRegDataType,
2969     PVOID Buffer,
2970     PULONG pulLength,
2971     ULONG ulFlags,
2972     HMACHINE hMachine)
2973 {
2974     RPC_BINDING_HANDLE BindingHandle = NULL;
2975     WCHAR szGuidString[PNP_MAX_GUID_STRING_LEN + 1];
2976     ULONG ulType = 0;
2977     ULONG ulTransferLength = 0;
2978     CONFIGRET ret;
2979 
2980     TRACE("CM_Get_Class_Registry_PropertyW(%p %lu %p %p %p %lx %p)\n",
2981           ClassGuid, ulProperty, pulRegDataType, Buffer, pulLength,
2982           ulFlags, hMachine);
2983 
2984     if (ClassGuid == NULL || pulLength == NULL)
2985         return CR_INVALID_POINTER;
2986 
2987     if (ulFlags != 0)
2988         return CR_INVALID_FLAG;
2989 
2990     if (pSetupStringFromGuid(ClassGuid,
2991                              szGuidString,
2992                              PNP_MAX_GUID_STRING_LEN) != 0)
2993         return CR_INVALID_DATA;
2994 
2995     if (ulProperty < CM_CRP_MIN || ulProperty > CM_CRP_MAX)
2996         return CR_INVALID_PROPERTY;
2997 
2998     if (hMachine != NULL)
2999     {
3000         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3001         if (BindingHandle == NULL)
3002             return CR_FAILURE;
3003     }
3004     else
3005     {
3006         if (!PnpGetLocalHandles(&BindingHandle, NULL))
3007             return CR_FAILURE;
3008     }
3009 
3010     ulTransferLength = *pulLength;
3011 
3012     RpcTryExcept
3013     {
3014         ret = PNP_GetClassRegProp(BindingHandle,
3015                                   szGuidString,
3016                                   ulProperty,
3017                                   &ulType,
3018                                   Buffer,
3019                                   &ulTransferLength,
3020                                   pulLength,
3021                                   ulFlags);
3022     }
3023     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3024     {
3025         ret = RpcStatusToCmStatus(RpcExceptionCode());
3026     }
3027     RpcEndExcept;
3028 
3029     if (ret == CR_SUCCESS)
3030     {
3031         if (pulRegDataType != NULL)
3032             *pulRegDataType = ulType;
3033     }
3034 
3035     return ret;
3036 }
3037 
3038 
3039 /***********************************************************************
3040  * CM_Get_Depth [SETUPAPI.@]
3041  */
3042 CONFIGRET
3043 WINAPI
3044 CM_Get_Depth(
3045     _Out_ PULONG pulDepth,
3046     _In_ DEVINST dnDevInst,
3047     _In_ ULONG ulFlags)
3048 {
3049     TRACE("CM_Get_Depth(%p %lx %lx)\n",
3050           pulDepth, dnDevInst, ulFlags);
3051 
3052     return CM_Get_Depth_Ex(pulDepth, dnDevInst, ulFlags, NULL);
3053 }
3054 
3055 
3056 /***********************************************************************
3057  * CM_Get_Depth_Ex [SETUPAPI.@]
3058  */
3059 CONFIGRET
3060 WINAPI
3061 CM_Get_Depth_Ex(
3062     _Out_ PULONG pulDepth,
3063     _In_ DEVINST dnDevInst,
3064     _In_ ULONG ulFlags,
3065     _In_opt_ HMACHINE hMachine)
3066 {
3067     RPC_BINDING_HANDLE BindingHandle = NULL;
3068     HSTRING_TABLE StringTable = NULL;
3069     LPWSTR lpDevInst;
3070     CONFIGRET ret;
3071 
3072     TRACE("CM_Get_Depth_Ex(%p %lx %lx %p)\n",
3073           pulDepth, dnDevInst, ulFlags, hMachine);
3074 
3075     if (pulDepth == NULL)
3076         return CR_INVALID_POINTER;
3077 
3078     if (dnDevInst == 0)
3079         return CR_INVALID_DEVINST;
3080 
3081     if (ulFlags != 0)
3082         return CR_INVALID_FLAG;
3083 
3084     if (hMachine != NULL)
3085     {
3086         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3087         if (BindingHandle == NULL)
3088             return CR_FAILURE;
3089 
3090         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3091         if (StringTable == 0)
3092             return CR_FAILURE;
3093     }
3094     else
3095     {
3096         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3097             return CR_FAILURE;
3098     }
3099 
3100     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3101     if (lpDevInst == NULL)
3102         return CR_INVALID_DEVNODE;
3103 
3104     RpcTryExcept
3105     {
3106         ret = PNP_GetDepth(BindingHandle,
3107                            lpDevInst,
3108                            pulDepth,
3109                            ulFlags);
3110     }
3111     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3112     {
3113         ret = RpcStatusToCmStatus(RpcExceptionCode());
3114     }
3115     RpcEndExcept;
3116 
3117     return ret;
3118 }
3119 
3120 
3121 /***********************************************************************
3122  * CM_Get_DevNode_Custom_PropertyA [SETUPAPI.@]
3123  */
3124 CONFIGRET
3125 WINAPI
3126 CM_Get_DevNode_Custom_PropertyA(
3127     _In_ DEVINST dnDevInst,
3128     _In_ PCSTR pszCustomPropertyName,
3129     _Out_opt_ PULONG pulRegDataType,
3130     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3131     _Inout_ PULONG pulLength,
3132     _In_ ULONG ulFlags)
3133 {
3134     TRACE("CM_Get_DevNode_Custom_PropertyA(%lx %s %p %p %p %lx)\n",
3135           dnDevInst, pszCustomPropertyName, pulRegDataType,
3136           Buffer, pulLength, ulFlags);
3137 
3138     return CM_Get_DevNode_Custom_Property_ExA(dnDevInst, pszCustomPropertyName,
3139                                               pulRegDataType, Buffer,
3140                                               pulLength, ulFlags, NULL);
3141 }
3142 
3143 
3144 /***********************************************************************
3145  * CM_Get_DevNode_Custom_PropertyW [SETUPAPI.@]
3146  */
3147 CONFIGRET
3148 WINAPI
3149 CM_Get_DevNode_Custom_PropertyW(
3150     _In_ DEVINST dnDevInst,
3151     _In_ PCWSTR pszCustomPropertyName,
3152     _Out_opt_ PULONG pulRegDataType,
3153     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3154     _Inout_ PULONG pulLength,
3155     _In_ ULONG ulFlags)
3156 {
3157     TRACE("CM_Get_DevNode_Custom_PropertyW(%lx %s %p %p %p %lx)\n",
3158           dnDevInst, debugstr_w(pszCustomPropertyName), pulRegDataType,
3159           Buffer, pulLength, ulFlags);
3160 
3161     return CM_Get_DevNode_Custom_Property_ExW(dnDevInst, pszCustomPropertyName,
3162                                               pulRegDataType, Buffer,
3163                                               pulLength, ulFlags, NULL);
3164 }
3165 
3166 
3167 /***********************************************************************
3168  * CM_Get_DevNode_Custom_Property_ExA [SETUPAPI.@]
3169  */
3170 CONFIGRET
3171 WINAPI
3172 CM_Get_DevNode_Custom_Property_ExA(
3173     _In_ DEVINST dnDevInst,
3174     _In_ PCSTR pszCustomPropertyName,
3175     _Out_opt_ PULONG pulRegDataType,
3176     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3177     _Inout_ PULONG pulLength,
3178     _In_ ULONG ulFlags,
3179     _In_opt_ HMACHINE hMachine)
3180 {
3181     LPWSTR pszPropertyNameW = NULL;
3182     PVOID BufferW;
3183     ULONG ulLengthW;
3184     ULONG ulDataType = REG_NONE;
3185     CONFIGRET ret;
3186 
3187     TRACE("CM_Get_DevNode_Custom_Property_ExA(%lx %s %p %p %p %lx %p)\n",
3188           dnDevInst, pszCustomPropertyName, pulRegDataType,
3189           Buffer, pulLength, ulFlags, hMachine);
3190 
3191     if (!pulLength)
3192         return CR_INVALID_POINTER;
3193 
3194     ulLengthW = *pulLength * sizeof(WCHAR);
3195     BufferW = HeapAlloc(GetProcessHeap(), 0, ulLengthW);
3196     if (!BufferW)
3197         return CR_OUT_OF_MEMORY;
3198 
3199     pszPropertyNameW = pSetupMultiByteToUnicode(pszCustomPropertyName,
3200                                                 CP_ACP);
3201     if (pszPropertyNameW == NULL)
3202     {
3203         HeapFree(GetProcessHeap(), 0, BufferW);
3204         return CR_OUT_OF_MEMORY;
3205     }
3206 
3207     ret = CM_Get_DevNode_Custom_Property_ExW(dnDevInst,
3208                                              pszPropertyNameW,
3209                                              &ulDataType,
3210                                              BufferW,
3211                                              &ulLengthW,
3212                                              ulFlags,
3213                                              hMachine);
3214     if (ret == CR_SUCCESS)
3215     {
3216         if (ulDataType == REG_SZ ||
3217             ulDataType == REG_EXPAND_SZ ||
3218             ulDataType == REG_MULTI_SZ)
3219         {
3220             /* Do W->A conversion */
3221             *pulLength = WideCharToMultiByte(CP_ACP,
3222                                              0,
3223                                              BufferW,
3224                                              lstrlenW(BufferW) + 1,
3225                                              Buffer,
3226                                              *pulLength,
3227                                              NULL,
3228                                              NULL);
3229             if (*pulLength == 0)
3230                 ret = CR_FAILURE;
3231         }
3232         else
3233         {
3234             /* Directly copy the value */
3235             if (ulLengthW <= *pulLength)
3236                 memcpy(Buffer, BufferW, ulLengthW);
3237             else
3238             {
3239                 *pulLength = ulLengthW;
3240                 ret = CR_BUFFER_SMALL;
3241             }
3242         }
3243     }
3244 
3245     if (pulRegDataType)
3246         *pulRegDataType = ulDataType;
3247 
3248     HeapFree(GetProcessHeap(), 0, BufferW);
3249     MyFree(pszPropertyNameW);
3250 
3251     return ret;
3252 }
3253 
3254 
3255 /***********************************************************************
3256  * CM_Get_DevNode_Custom_Property_ExW [SETUPAPI.@]
3257  */
3258 CONFIGRET
3259 WINAPI
3260 CM_Get_DevNode_Custom_Property_ExW(
3261     _In_ DEVINST dnDevInst,
3262     _In_ PCWSTR pszCustomPropertyName,
3263     _Out_opt_ PULONG pulRegDataType,
3264     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3265     _Inout_ PULONG pulLength,
3266     _In_ ULONG ulFlags,
3267     _In_opt_ HMACHINE hMachine)
3268 {
3269     RPC_BINDING_HANDLE BindingHandle = NULL;
3270     HSTRING_TABLE StringTable = NULL;
3271     LPWSTR lpDevInst;
3272     ULONG ulDataType = REG_NONE;
3273     ULONG ulTransferLength;
3274     CONFIGRET ret = CR_SUCCESS;
3275 
3276     TRACE("CM_Get_DevNode_Custom_Property_ExW(%lx %s %p %p %p %lx %p)\n",
3277           dnDevInst, debugstr_w(pszCustomPropertyName), pulRegDataType,
3278           Buffer, pulLength, ulFlags, hMachine);
3279 
3280     if (dnDevInst == 0)
3281         return CR_INVALID_DEVNODE;
3282 
3283     if (pszCustomPropertyName == NULL ||
3284         pulLength == NULL ||
3285         *pulLength == 0)
3286         return CR_INVALID_POINTER;
3287 
3288     if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
3289         return CR_INVALID_FLAG;
3290 
3291     if (hMachine != NULL)
3292     {
3293         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3294         if (BindingHandle == NULL)
3295             return CR_FAILURE;
3296 
3297         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3298         if (StringTable == 0)
3299             return CR_FAILURE;
3300     }
3301     else
3302     {
3303         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3304             return CR_FAILURE;
3305     }
3306 
3307     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3308     if (lpDevInst == NULL)
3309         return CR_INVALID_DEVNODE;
3310 
3311     ulTransferLength = *pulLength;
3312 
3313     RpcTryExcept
3314     {
3315         ret = PNP_GetCustomDevProp(BindingHandle,
3316                                    lpDevInst,
3317                                    (LPWSTR)pszCustomPropertyName,
3318                                    &ulDataType,
3319                                    Buffer,
3320                                    &ulTransferLength,
3321                                    pulLength,
3322                                    ulFlags);
3323     }
3324     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3325     {
3326         ret = RpcStatusToCmStatus(RpcExceptionCode());
3327     }
3328     RpcEndExcept;
3329 
3330     if (ret == CR_SUCCESS)
3331     {
3332         if (pulRegDataType != NULL)
3333             *pulRegDataType = ulDataType;
3334     }
3335 
3336     return ret;
3337 }
3338 
3339 
3340 /***********************************************************************
3341  * CM_Get_DevNode_Registry_PropertyA [SETUPAPI.@]
3342  */
3343 CONFIGRET
3344 WINAPI
3345 CM_Get_DevNode_Registry_PropertyA(
3346     _In_ DEVINST dnDevInst,
3347     _In_ ULONG ulProperty,
3348     _Out_opt_ PULONG pulRegDataType,
3349     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3350     _Inout_ PULONG pulLength,
3351     _In_ ULONG ulFlags)
3352 {
3353     TRACE("CM_Get_DevNode_Registry_PropertyA(%lx %lu %p %p %p %lx)\n",
3354           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
3355 
3356     return CM_Get_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
3357                                                 pulRegDataType, Buffer,
3358                                                 pulLength, ulFlags, NULL);
3359 }
3360 
3361 
3362 /***********************************************************************
3363  * CM_Get_DevNode_Registry_PropertyW [SETUPAPI.@]
3364  */
3365 CONFIGRET
3366 WINAPI
3367 CM_Get_DevNode_Registry_PropertyW(
3368     _In_ DEVINST dnDevInst,
3369     _In_ ULONG ulProperty,
3370     _Out_opt_ PULONG pulRegDataType,
3371     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3372     _Inout_ PULONG pulLength,
3373     _In_ ULONG ulFlags)
3374 {
3375     TRACE("CM_Get_DevNode_Registry_PropertyW(%lx %lu %p %p %p %lx)\n",
3376           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
3377 
3378     return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
3379                                                 pulRegDataType, Buffer,
3380                                                 pulLength, ulFlags, NULL);
3381 }
3382 
3383 
3384 /***********************************************************************
3385  * CM_Get_DevNode_Registry_Property_ExA [SETUPAPI.@]
3386  */
3387 CONFIGRET
3388 WINAPI
3389 CM_Get_DevNode_Registry_Property_ExA(
3390     _In_ DEVINST dnDevInst,
3391     _In_ ULONG ulProperty,
3392     _Out_opt_ PULONG pulRegDataType,
3393     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3394     _Inout_ PULONG pulLength,
3395     _In_ ULONG ulFlags,
3396     _In_opt_ HMACHINE hMachine)
3397 {
3398     PVOID BufferW;
3399     ULONG LengthW;
3400     ULONG ulDataType = REG_NONE;
3401     CONFIGRET ret;
3402 
3403     TRACE("CM_Get_DevNode_Registry_Property_ExA(%lx %lu %p %p %p %lx %p)\n",
3404           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
3405           ulFlags, hMachine);
3406 
3407     if (!pulLength)
3408         return CR_INVALID_POINTER;
3409 
3410     LengthW = *pulLength * sizeof(WCHAR);
3411     BufferW = HeapAlloc(GetProcessHeap(), 0, LengthW);
3412 
3413     if (!BufferW)
3414         return CR_OUT_OF_MEMORY;
3415 
3416     ret = CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
3417                                                ulProperty,
3418                                                &ulDataType,
3419                                                BufferW,
3420                                                &LengthW,
3421                                                ulFlags,
3422                                                hMachine);
3423 
3424     if (ret == CR_SUCCESS)
3425     {
3426         if (ulDataType == REG_SZ ||
3427             ulDataType == REG_EXPAND_SZ ||
3428             ulDataType == REG_MULTI_SZ)
3429         {
3430             /* Do W->A conversion */
3431             *pulLength = WideCharToMultiByte(CP_ACP,
3432                                              0,
3433                                              BufferW,
3434                                              lstrlenW(BufferW) + 1,
3435                                              Buffer,
3436                                              *pulLength,
3437                                              NULL,
3438                                              NULL);
3439             if (*pulLength == 0)
3440                 ret = CR_FAILURE;
3441         }
3442         else
3443         {
3444             /* Directly copy the value */
3445             if (LengthW <= *pulLength)
3446                 memcpy(Buffer, BufferW, LengthW);
3447             else
3448             {
3449                 *pulLength = LengthW;
3450                 ret = CR_BUFFER_SMALL;
3451             }
3452         }
3453     }
3454 
3455     if (pulRegDataType)
3456         *pulRegDataType = ulDataType;
3457 
3458     HeapFree(GetProcessHeap(), 0, BufferW);
3459 
3460     return ret;
3461 }
3462 
3463 
3464 /***********************************************************************
3465  * CM_Get_DevNode_Registry_Property_ExW [SETUPAPI.@]
3466  */
3467 CONFIGRET
3468 WINAPI
3469 CM_Get_DevNode_Registry_Property_ExW(
3470     _In_ DEVINST dnDevInst,
3471     _In_ ULONG ulProperty,
3472     _Out_opt_ PULONG pulRegDataType,
3473     _Out_writes_bytes_opt_(*pulLength) PVOID Buffer,
3474     _Inout_ PULONG pulLength,
3475     _In_ ULONG ulFlags,
3476     _In_opt_ HMACHINE hMachine)
3477 {
3478     RPC_BINDING_HANDLE BindingHandle = NULL;
3479     HSTRING_TABLE StringTable = NULL;
3480     CONFIGRET ret = CR_SUCCESS;
3481     LPWSTR lpDevInst;
3482     ULONG ulDataType = REG_NONE;
3483     ULONG ulTransferLength = 0;
3484 
3485     TRACE("CM_Get_DevNode_Registry_Property_ExW(%lx %lu %p %p %p %lx %p)\n",
3486           dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
3487           ulFlags, hMachine);
3488 
3489     if (dnDevInst == 0)
3490         return CR_INVALID_DEVNODE;
3491 
3492     if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
3493         return CR_INVALID_PROPERTY;
3494 
3495     /* pulRegDataType is optional */
3496 
3497     /* Buffer is optional */
3498 
3499     if (pulLength == NULL)
3500         return CR_INVALID_POINTER;
3501 
3502     if (*pulLength == 0)
3503         return CR_INVALID_POINTER;
3504 
3505     if (ulFlags != 0)
3506         return CR_INVALID_FLAG;
3507 
3508     if (hMachine != NULL)
3509     {
3510         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3511         if (BindingHandle == NULL)
3512             return CR_FAILURE;
3513 
3514         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3515         if (StringTable == 0)
3516             return CR_FAILURE;
3517     }
3518     else
3519     {
3520         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3521             return CR_FAILURE;
3522     }
3523 
3524     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3525     if (lpDevInst == NULL)
3526         return CR_INVALID_DEVNODE;
3527 
3528     ulTransferLength = *pulLength;
3529 
3530     RpcTryExcept
3531     {
3532         ret = PNP_GetDeviceRegProp(BindingHandle,
3533                                    lpDevInst,
3534                                    ulProperty,
3535                                    &ulDataType,
3536                                    Buffer,
3537                                    &ulTransferLength,
3538                                    pulLength,
3539                                    ulFlags);
3540     }
3541     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3542     {
3543         ret = RpcStatusToCmStatus(RpcExceptionCode());
3544     }
3545     RpcEndExcept;
3546 
3547     if (ret == CR_SUCCESS)
3548     {
3549         if (pulRegDataType != NULL)
3550             *pulRegDataType = ulDataType;
3551     }
3552 
3553     return ret;
3554 }
3555 
3556 
3557 /***********************************************************************
3558  * CM_Get_DevNode_Status [SETUPAPI.@]
3559  */
3560 CONFIGRET
3561 WINAPI
3562 CM_Get_DevNode_Status(
3563     _Out_ PULONG pulStatus,
3564     _Out_ PULONG pulProblemNumber,
3565     _In_ DEVINST dnDevInst,
3566     _In_ ULONG ulFlags)
3567 {
3568     TRACE("CM_Get_DevNode_Status(%p %p %lx %lx)\n",
3569           pulStatus, pulProblemNumber, dnDevInst, ulFlags);
3570 
3571     return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber, dnDevInst,
3572                                     ulFlags, NULL);
3573 }
3574 
3575 
3576 /***********************************************************************
3577  * CM_Get_DevNode_Status_Ex [SETUPAPI.@]
3578  */
3579 CONFIGRET
3580 WINAPI
3581 CM_Get_DevNode_Status_Ex(
3582     _Out_ PULONG pulStatus,
3583     _Out_ PULONG pulProblemNumber,
3584     _In_ DEVINST dnDevInst,
3585     _In_ ULONG ulFlags,
3586     _In_opt_ HMACHINE hMachine)
3587 {
3588     RPC_BINDING_HANDLE BindingHandle = NULL;
3589     HSTRING_TABLE StringTable = NULL;
3590     LPWSTR lpDevInst;
3591     CONFIGRET ret;
3592 
3593     TRACE("CM_Get_DevNode_Status_Ex(%p %p %lx %lx %p)\n",
3594           pulStatus, pulProblemNumber, dnDevInst, ulFlags, hMachine);
3595 
3596     if (pulStatus == NULL || pulProblemNumber == NULL)
3597         return CR_INVALID_POINTER;
3598 
3599     if (dnDevInst == 0)
3600         return CR_INVALID_DEVINST;
3601 
3602     if (ulFlags != 0)
3603         return CR_INVALID_FLAG;
3604 
3605     if (hMachine != NULL)
3606     {
3607         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3608         if (BindingHandle == NULL)
3609             return CR_FAILURE;
3610 
3611         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3612         if (StringTable == 0)
3613             return CR_FAILURE;
3614     }
3615     else
3616     {
3617         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
3618             return CR_FAILURE;
3619     }
3620 
3621     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
3622     if (lpDevInst == NULL)
3623         return CR_INVALID_DEVNODE;
3624 
3625     RpcTryExcept
3626     {
3627         ret = PNP_GetDeviceStatus(BindingHandle,
3628                                   lpDevInst,
3629                                   pulStatus,
3630                                   pulProblemNumber,
3631                                   ulFlags);
3632     }
3633     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3634     {
3635         ret = RpcStatusToCmStatus(RpcExceptionCode());
3636     }
3637     RpcEndExcept;
3638 
3639     return ret;
3640 }
3641 
3642 
3643 /***********************************************************************
3644  * CM_Get_Device_IDA [SETUPAPI.@]
3645  */
3646 CONFIGRET
3647 WINAPI
3648 CM_Get_Device_IDA(
3649     _In_ DEVINST dnDevInst,
3650     _Out_writes_(BufferLen) PCHAR Buffer,
3651     _In_ ULONG BufferLen,
3652     _In_ ULONG ulFlags)
3653 {
3654     TRACE("CM_Get_Device_IDA(%lx %p %lu %lx)\n",
3655           dnDevInst, Buffer, BufferLen, ulFlags);
3656 
3657     return CM_Get_Device_ID_ExA(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
3658 }
3659 
3660 
3661 /***********************************************************************
3662  * CM_Get_Device_IDW [SETUPAPI.@]
3663  */
3664 CONFIGRET
3665 WINAPI
3666 CM_Get_Device_IDW(
3667     _In_ DEVINST dnDevInst,
3668     _Out_writes_(BufferLen) PWCHAR Buffer,
3669     _In_ ULONG BufferLen,
3670     _In_ ULONG ulFlags)
3671 {
3672     TRACE("CM_Get_Device_IDW(%lx %p %lu %lx)\n",
3673           dnDevInst, Buffer, BufferLen, ulFlags);
3674 
3675     return CM_Get_Device_ID_ExW(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
3676 }
3677 
3678 
3679 /***********************************************************************
3680  * CM_Get_Device_ID_ExA [SETUPAPI.@]
3681  */
3682 CONFIGRET
3683 WINAPI
3684 CM_Get_Device_ID_ExA(
3685     _In_ DEVINST dnDevInst,
3686     _Out_writes_(BufferLen) PCHAR Buffer,
3687     _In_ ULONG BufferLen,
3688     _In_ ULONG ulFlags,
3689     _In_opt_ HMACHINE hMachine)
3690 {
3691     WCHAR szBufferW[MAX_DEVICE_ID_LEN];
3692     CONFIGRET ret = CR_SUCCESS;
3693 
3694     TRACE("CM_Get_Device_ID_ExA(%lx %p %lu %lx %p)\n",
3695           dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
3696 
3697     if (Buffer == NULL)
3698         return CR_INVALID_POINTER;
3699 
3700     ret = CM_Get_Device_ID_ExW(dnDevInst,
3701                                szBufferW,
3702                                MAX_DEVICE_ID_LEN,
3703                                ulFlags,
3704                                hMachine);
3705     if (ret == CR_SUCCESS)
3706     {
3707         if (WideCharToMultiByte(CP_ACP,
3708                                 0,
3709                                 szBufferW,
3710                                 lstrlenW(szBufferW) + 1,
3711                                 Buffer,
3712                                 BufferLen,
3713                                 NULL,
3714                                 NULL) == 0)
3715             ret = CR_FAILURE;
3716     }
3717 
3718     return ret;
3719 }
3720 
3721 
3722 /***********************************************************************
3723  * CM_Get_Device_ID_ExW [SETUPAPI.@]
3724  */
3725 CONFIGRET
3726 WINAPI
3727 CM_Get_Device_ID_ExW(
3728     _In_ DEVINST dnDevInst,
3729     _Out_writes_(BufferLen) PWCHAR Buffer,
3730     _In_ ULONG BufferLen,
3731     _In_ ULONG ulFlags,
3732     _In_opt_ HMACHINE hMachine)
3733 {
3734     HSTRING_TABLE StringTable = NULL;
3735 
3736     TRACE("CM_Get_Device_ID_ExW(%lx %p %lu %lx %p)\n",
3737           dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
3738 
3739     if (dnDevInst == 0)
3740         return CR_INVALID_DEVINST;
3741 
3742     if (Buffer == NULL)
3743         return CR_INVALID_POINTER;
3744 
3745     if (ulFlags != 0)
3746         return CR_INVALID_FLAG;
3747 
3748     if (hMachine != NULL)
3749     {
3750         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
3751         if (StringTable == NULL)
3752             return CR_FAILURE;
3753     }
3754     else
3755     {
3756         if (!PnpGetLocalHandles(NULL, &StringTable))
3757             return CR_FAILURE;
3758     }
3759 
3760     if (!pSetupStringTableStringFromIdEx(StringTable,
3761                                          dnDevInst,
3762                                          Buffer,
3763                                          &BufferLen))
3764         return CR_FAILURE;
3765 
3766     return CR_SUCCESS;
3767 }
3768 
3769 
3770 /***********************************************************************
3771  * CM_Get_Device_ID_ListA [SETUPAPI.@]
3772  */
3773 CONFIGRET
3774 WINAPI
3775 CM_Get_Device_ID_ListA(
3776     _In_ PCSTR pszFilter,
3777     _Out_writes_(BufferLen) PCHAR Buffer,
3778     _In_ ULONG BufferLen,
3779     _In_ ULONG ulFlags)
3780 {
3781     TRACE("CM_Get_Device_ID_ListA(%p %p %lu %lx)\n",
3782           pszFilter, Buffer, BufferLen, ulFlags);
3783 
3784     return CM_Get_Device_ID_List_ExA(pszFilter, Buffer, BufferLen,
3785                                      ulFlags, NULL);
3786 }
3787 
3788 
3789 /***********************************************************************
3790  * CM_Get_Device_ID_ListW [SETUPAPI.@]
3791  */
3792 CONFIGRET
3793 WINAPI
3794 CM_Get_Device_ID_ListW(
3795     _In_ PCWSTR pszFilter,
3796     _Out_writes_(BufferLen) PWCHAR Buffer,
3797     _In_ ULONG BufferLen,
3798     _In_ ULONG ulFlags)
3799 {
3800     TRACE("CM_Get_Device_ID_ListW(%p %p %lu %lx)\n",
3801           pszFilter, Buffer, BufferLen, ulFlags);
3802 
3803     return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen,
3804                                      ulFlags, NULL);
3805 }
3806 
3807 
3808 /***********************************************************************
3809  * CM_Get_Device_ID_List_ExA [SETUPAPI.@]
3810  */
3811 CONFIGRET
3812 WINAPI
3813 CM_Get_Device_ID_List_ExA(
3814     _In_ PCSTR pszFilter,
3815     _Out_writes_(BufferLen) PCHAR Buffer,
3816     _In_ ULONG BufferLen,
3817     _In_ ULONG ulFlags,
3818     _In_opt_ HMACHINE hMachine)
3819 {
3820     LPWSTR BufferW = NULL;
3821     LPWSTR pszFilterW = NULL;
3822     CONFIGRET ret = CR_SUCCESS;
3823 
3824     TRACE("CM_Get_Device_ID_List_ExA(%p %p %lu %lx %p)\n",
3825           pszFilter, Buffer, BufferLen, ulFlags, hMachine);
3826 
3827     BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
3828     if (BufferW == NULL)
3829         return CR_OUT_OF_MEMORY;
3830 
3831     if (pszFilter == NULL)
3832     {
3833         ret = CM_Get_Device_ID_List_ExW(NULL,
3834                                         BufferW,
3835                                         BufferLen,
3836                                         ulFlags,
3837                                         hMachine);
3838     }
3839     else
3840     {
3841         if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
3842         {
3843             ret = CR_INVALID_DEVICE_ID;
3844             goto Done;
3845         }
3846 
3847         ret = CM_Get_Device_ID_List_ExW(pszFilterW,
3848                                         BufferW,
3849                                         BufferLen,
3850                                         ulFlags,
3851                                         hMachine);
3852 
3853         MyFree(pszFilterW);
3854     }
3855 
3856     if (WideCharToMultiByte(CP_ACP,
3857                             0,
3858                             BufferW,
3859                             lstrlenW(BufferW) + 1,
3860                             Buffer,
3861                             BufferLen,
3862                             NULL,
3863                             NULL) == 0)
3864         ret = CR_FAILURE;
3865 
3866 Done:
3867     MyFree(BufferW);
3868 
3869     return ret;
3870 }
3871 
3872 
3873 /***********************************************************************
3874  * CM_Get_Device_ID_List_ExW [SETUPAPI.@]
3875  */
3876 CONFIGRET
3877 WINAPI
3878 CM_Get_Device_ID_List_ExW(
3879     _In_ PCWSTR pszFilter,
3880     _Out_writes_(BufferLen) PWCHAR Buffer,
3881     _In_ ULONG BufferLen,
3882     _In_ ULONG ulFlags,
3883     _In_opt_ HMACHINE hMachine)
3884 {
3885     RPC_BINDING_HANDLE BindingHandle = NULL;
3886     CONFIGRET ret;
3887 
3888     TRACE("CM_Get_Device_ID_List_ExW(%p %p %lu %lx %p)\n",
3889           pszFilter, Buffer, BufferLen, ulFlags, hMachine);
3890 
3891     if (Buffer == NULL || BufferLen == 0)
3892         return CR_INVALID_POINTER;
3893 
3894     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
3895         return CR_INVALID_FLAG;
3896 
3897     if (hMachine != NULL)
3898     {
3899         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
3900         if (BindingHandle == NULL)
3901             return CR_FAILURE;
3902     }
3903     else
3904     {
3905         if (!PnpGetLocalHandles(&BindingHandle, NULL))
3906             return CR_FAILURE;
3907     }
3908 
3909     *Buffer = 0;
3910 
3911     RpcTryExcept
3912     {
3913         ret = PNP_GetDeviceList(BindingHandle,
3914                                 (LPWSTR)pszFilter,
3915                                 Buffer,
3916                                 &BufferLen,
3917                                 ulFlags);
3918     }
3919     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3920     {
3921         ret = RpcStatusToCmStatus(RpcExceptionCode());
3922     }
3923     RpcEndExcept;
3924 
3925     return ret;
3926 }
3927 
3928 
3929 /***********************************************************************
3930  * CM_Get_Device_ID_List_SizeA [SETUPAPI.@]
3931  */
3932 CONFIGRET
3933 WINAPI
3934 CM_Get_Device_ID_List_SizeA(
3935     _Out_ PULONG pulLen,
3936     _In_opt_ PCSTR pszFilter,
3937     _In_ ULONG ulFlags)
3938 {
3939     TRACE("CM_Get_Device_ID_List_SizeA(%p %s %lx)\n",
3940           pulLen, debugstr_a(pszFilter), ulFlags);
3941 
3942     return CM_Get_Device_ID_List_Size_ExA(pulLen, pszFilter, ulFlags, NULL);
3943 }
3944 
3945 
3946 /***********************************************************************
3947  * CM_Get_Device_ID_List_SizeW [SETUPAPI.@]
3948  */
3949 CONFIGRET
3950 WINAPI
3951 CM_Get_Device_ID_List_SizeW(
3952     _Out_ PULONG pulLen,
3953     _In_opt_ PCWSTR pszFilter,
3954     _In_ ULONG ulFlags)
3955 {
3956     TRACE("CM_Get_Device_ID_List_SizeW(%p %s %lx)\n",
3957           pulLen, debugstr_w(pszFilter), ulFlags);
3958 
3959     return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL);
3960 }
3961 
3962 
3963 /***********************************************************************
3964  * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@]
3965  */
3966 CONFIGRET
3967 WINAPI
3968 CM_Get_Device_ID_List_Size_ExA(
3969     _Out_ PULONG pulLen,
3970     _In_opt_ PCSTR pszFilter,
3971     _In_ ULONG ulFlags,
3972     _In_opt_ HMACHINE hMachine)
3973 {
3974     LPWSTR pszFilterW = NULL;
3975     CONFIGRET ret = CR_SUCCESS;
3976 
3977     FIXME("CM_Get_Device_ID_List_Size_ExA(%p %s %lx %p)\n",
3978           pulLen, debugstr_a(pszFilter), ulFlags, hMachine);
3979 
3980     if (pszFilter == NULL)
3981     {
3982         ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
3983                                              NULL,
3984                                              ulFlags,
3985                                              hMachine);
3986     }
3987     else
3988     {
3989         if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
3990             return CR_INVALID_DEVICE_ID;
3991 
3992         ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
3993                                              pszFilterW,
3994                                              ulFlags,
3995                                              hMachine);
3996 
3997         MyFree(pszFilterW);
3998     }
3999 
4000     return ret;
4001 }
4002 
4003 
4004 /***********************************************************************
4005  * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@]
4006  */
4007 CONFIGRET
4008 WINAPI
4009 CM_Get_Device_ID_List_Size_ExW(
4010     _Out_ PULONG pulLen,
4011     _In_opt_ PCWSTR pszFilter,
4012     _In_ ULONG ulFlags,
4013     _In_opt_ HMACHINE hMachine)
4014 {
4015     RPC_BINDING_HANDLE BindingHandle = NULL;
4016     CONFIGRET ret;
4017 
4018     FIXME("CM_Get_Device_ID_List_Size_ExW(%p %s %lx %p)\n",
4019           pulLen, debugstr_w(pszFilter), ulFlags, hMachine);
4020 
4021     if (pulLen == NULL)
4022         return CR_INVALID_POINTER;
4023 
4024     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
4025         return CR_INVALID_FLAG;
4026 
4027     if (hMachine != NULL)
4028     {
4029         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4030         if (BindingHandle == NULL)
4031             return CR_FAILURE;
4032     }
4033     else
4034     {
4035         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4036             return CR_FAILURE;
4037     }
4038 
4039     *pulLen = 0;
4040 
4041     RpcTryExcept
4042     {
4043         ret = PNP_GetDeviceListSize(BindingHandle,
4044                                     (LPWSTR)pszFilter,
4045                                     pulLen,
4046                                     ulFlags);
4047     }
4048     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4049     {
4050         ret = RpcStatusToCmStatus(RpcExceptionCode());
4051     }
4052     RpcEndExcept;
4053 
4054     return ret;
4055 }
4056 
4057 
4058 /***********************************************************************
4059  * CM_Get_Device_ID_Size [SETUPAPI.@]
4060  */
4061 CONFIGRET
4062 WINAPI
4063 CM_Get_Device_ID_Size(
4064     _Out_ PULONG pulLen,
4065     _In_ DEVINST dnDevInst,
4066     _In_ ULONG ulFlags)
4067 {
4068     TRACE("CM_Get_Device_ID_Size(%p %lx %lx)\n",
4069           pulLen, dnDevInst, ulFlags);
4070 
4071     return CM_Get_Device_ID_Size_Ex(pulLen, dnDevInst, ulFlags, NULL);
4072 }
4073 
4074 
4075 /***********************************************************************
4076  * CM_Get_Device_ID_Size_Ex [SETUPAPI.@]
4077  */
4078 CONFIGRET
4079 WINAPI
4080 CM_Get_Device_ID_Size_Ex(
4081     _Out_ PULONG pulLen,
4082     _In_ DEVINST dnDevInst,
4083     _In_ ULONG ulFlags,
4084     _In_opt_ HMACHINE hMachine)
4085 {
4086     HSTRING_TABLE StringTable = NULL;
4087     LPWSTR DeviceId;
4088 
4089     TRACE("CM_Get_Device_ID_Size_Ex(%p %lx %lx %p)\n",
4090           pulLen, dnDevInst, ulFlags, hMachine);
4091 
4092     if (pulLen == NULL)
4093         return CR_INVALID_POINTER;
4094 
4095     if (dnDevInst == 0)
4096         return CR_INVALID_DEVINST;
4097 
4098     if (ulFlags != 0)
4099         return CR_INVALID_FLAG;
4100 
4101     if (hMachine != NULL)
4102     {
4103         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
4104         if (StringTable == NULL)
4105             return CR_FAILURE;
4106     }
4107     else
4108     {
4109         if (!PnpGetLocalHandles(NULL, &StringTable))
4110             return CR_FAILURE;
4111     }
4112 
4113     DeviceId = pSetupStringTableStringFromId(StringTable, dnDevInst);
4114     if (DeviceId == NULL)
4115     {
4116         *pulLen = 0;
4117         return CR_SUCCESS;
4118     }
4119 
4120     *pulLen = lstrlenW(DeviceId);
4121 
4122     return CR_SUCCESS;
4123 }
4124 
4125 
4126 /***********************************************************************
4127  * CM_Get_Device_Interface_AliasA [SETUPAPI.@]
4128  */
4129 CONFIGRET
4130 WINAPI
4131 CM_Get_Device_Interface_AliasA(
4132     _In_ LPCSTR pszDeviceInterface,
4133     _In_ LPGUID AliasInterfaceGuid,
4134     _Out_writes_(*pulLength) LPSTR pszAliasDeviceInterface,
4135     _Inout_ PULONG pulLength,
4136     _In_ ULONG ulFlags)
4137 {
4138     TRACE("CM_Get_Device_Interface_AliasA(%p %p %p %p %lx)\n",
4139           pszDeviceInterface, AliasInterfaceGuid,
4140           pszAliasDeviceInterface, pulLength, ulFlags);
4141 
4142     return CM_Get_Device_Interface_Alias_ExA(pszDeviceInterface,
4143         AliasInterfaceGuid, pszAliasDeviceInterface, pulLength,
4144         ulFlags, NULL);
4145 }
4146 
4147 
4148 /***********************************************************************
4149  * CM_Get_Device_Interface_AliasW [SETUPAPI.@]
4150  */
4151 CONFIGRET
4152 WINAPI
4153 CM_Get_Device_Interface_AliasW(
4154     _In_ LPCWSTR pszDeviceInterface,
4155     _In_ LPGUID AliasInterfaceGuid,
4156     _Out_writes_(*pulLength) LPWSTR pszAliasDeviceInterface,
4157     _Inout_ PULONG pulLength,
4158     _In_ ULONG ulFlags)
4159 {
4160     TRACE("CM_Get_Device_Interface_AliasW(%p %p %p %p %lx)\n",
4161           pszDeviceInterface, AliasInterfaceGuid,
4162           pszAliasDeviceInterface, pulLength, ulFlags);
4163 
4164     return CM_Get_Device_Interface_Alias_ExW(pszDeviceInterface,
4165         AliasInterfaceGuid, pszAliasDeviceInterface, pulLength,
4166         ulFlags, NULL);
4167 }
4168 
4169 
4170 /***********************************************************************
4171  * CM_Get_Device_Interface_Alias_ExA [SETUPAPI.@]
4172  */
4173 CONFIGRET
4174 WINAPI
4175 CM_Get_Device_Interface_Alias_ExA(
4176     _In_ LPCSTR pszDeviceInterface,
4177     _In_ LPGUID AliasInterfaceGuid,
4178     _Out_writes_(*pulLength) LPSTR pszAliasDeviceInterface,
4179     _Inout_ PULONG pulLength,
4180     _In_ ULONG ulFlags,
4181     _In_opt_ HMACHINE hMachine)
4182 {
4183     FIXME("CM_Get_Device_Interface_Alias_ExA(%p %p %p %p %lx %p)\n",
4184           pszDeviceInterface, AliasInterfaceGuid,
4185           pszAliasDeviceInterface, pulLength, ulFlags, hMachine);
4186 
4187     return CR_CALL_NOT_IMPLEMENTED;
4188 }
4189 
4190 
4191 /***********************************************************************
4192  * CM_Get_Device_Interface_Alias_ExW [SETUPAPI.@]
4193  */
4194 CONFIGRET
4195 WINAPI
4196 CM_Get_Device_Interface_Alias_ExW(
4197     _In_ LPCWSTR pszDeviceInterface,
4198     _In_ LPGUID AliasInterfaceGuid,
4199     _Out_writes_(*pulLength) LPWSTR pszAliasDeviceInterface,
4200     _Inout_ PULONG pulLength,
4201     _In_ ULONG ulFlags,
4202     _In_opt_ HMACHINE hMachine)
4203 {
4204     RPC_BINDING_HANDLE BindingHandle = NULL;
4205     ULONG ulTransferLength;
4206     CONFIGRET ret = CR_SUCCESS;
4207 
4208     TRACE("CM_Get_Device_Interface_Alias_ExW(%p %p %p %p %lx %p)\n",
4209           pszDeviceInterface, AliasInterfaceGuid,
4210           pszAliasDeviceInterface, pulLength, ulFlags, hMachine);
4211 
4212     if (pszDeviceInterface == NULL ||
4213         AliasInterfaceGuid == NULL ||
4214         pszAliasDeviceInterface == NULL ||
4215         pulLength == NULL)
4216         return CR_INVALID_POINTER;
4217 
4218     if (ulFlags != 0)
4219         return CR_INVALID_FLAG;
4220 
4221     if (hMachine != NULL)
4222     {
4223         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4224         if (BindingHandle == NULL)
4225             return CR_FAILURE;
4226     }
4227     else
4228     {
4229         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4230             return CR_FAILURE;
4231     }
4232 
4233     ulTransferLength = *pulLength;
4234 
4235     RpcTryExcept
4236     {
4237         ret = PNP_GetInterfaceDeviceAlias(BindingHandle,
4238                                           (LPWSTR)pszDeviceInterface,
4239                                           AliasInterfaceGuid,
4240                                           pszAliasDeviceInterface,
4241                                           pulLength,
4242                                           &ulTransferLength,
4243                                           0);
4244     }
4245     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4246     {
4247         ret = RpcStatusToCmStatus(RpcExceptionCode());
4248     }
4249     RpcEndExcept;
4250 
4251     return ret;
4252 }
4253 
4254 
4255 /***********************************************************************
4256  *      CM_Get_Device_Interface_ListA (SETUPAPI.@)
4257  */
4258 CONFIGRET
4259 WINAPI
4260 CM_Get_Device_Interface_ListA(
4261     _In_ LPGUID InterfaceClassGuid,
4262     _In_opt_ DEVINSTID_A pDeviceID,
4263     _Out_writes_(BufferLen) PCHAR Buffer,
4264     _In_ ULONG BufferLen,
4265     _In_ ULONG ulFlags)
4266 {
4267     TRACE("CM_Get_Device_Interface_ListA(%s %s %p %lu 0x%08lx)\n",
4268           debugstr_guid(InterfaceClassGuid), debugstr_a(pDeviceID),
4269           Buffer, BufferLen, ulFlags);
4270 
4271     return CM_Get_Device_Interface_List_ExA(InterfaceClassGuid, pDeviceID,
4272                                             Buffer, BufferLen, ulFlags, NULL);
4273 }
4274 
4275 
4276 /***********************************************************************
4277  *      CM_Get_Device_Interface_ListW (SETUPAPI.@)
4278  */
4279 CONFIGRET
4280 WINAPI
4281 CM_Get_Device_Interface_ListW(
4282     _In_ LPGUID InterfaceClassGuid,
4283     _In_opt_ DEVINSTID_W pDeviceID,
4284     _Out_writes_(BufferLen) PWCHAR Buffer,
4285     _In_ ULONG BufferLen,
4286     _In_ ULONG ulFlags)
4287 {
4288     TRACE("CM_Get_Device_Interface_ListW(%s %s %p %lu 0x%08lx)\n",
4289           debugstr_guid(InterfaceClassGuid), debugstr_w(pDeviceID),
4290           Buffer, BufferLen, ulFlags);
4291 
4292     return CM_Get_Device_Interface_List_ExW(InterfaceClassGuid, pDeviceID,
4293                                             Buffer, BufferLen, ulFlags, NULL);
4294 }
4295 
4296 
4297 /***********************************************************************
4298  *      CM_Get_Device_Interface_List_ExA (SETUPAPI.@)
4299  */
4300 CONFIGRET
4301 WINAPI
4302 CM_Get_Device_Interface_List_ExA(
4303     _In_ LPGUID InterfaceClassGuid,
4304     _In_opt_ DEVINSTID_A pDeviceID,
4305     _Out_writes_(BufferLen) PCHAR Buffer,
4306     _In_ ULONG BufferLen,
4307     _In_ ULONG ulFlags,
4308     _In_opt_ HMACHINE hMachine)
4309 {
4310     DEVINSTID_W pDeviceIdW = NULL;
4311     PWCHAR BufferW = NULL;
4312     CONFIGRET ret = CR_SUCCESS;
4313 
4314     TRACE("CM_Get_Device_Interface_List_ExA(%s %s %p %lu 0x%08lx %p)\n",
4315           debugstr_guid(InterfaceClassGuid), debugstr_a(pDeviceID),
4316           Buffer, BufferLen, ulFlags, hMachine);
4317 
4318     if (Buffer == NULL ||
4319         BufferLen == 0)
4320         return CR_INVALID_POINTER;
4321 
4322     if (pDeviceID != NULL)
4323     {
4324         if (!pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIdW))
4325             return CR_INVALID_DEVICE_ID;
4326     }
4327 
4328     BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
4329     if (BufferW == NULL)
4330     {
4331         ret = CR_OUT_OF_MEMORY;
4332         goto Done;
4333     }
4334 
4335     ret = CM_Get_Device_Interface_List_ExW(InterfaceClassGuid, pDeviceIdW,
4336                                            BufferW, BufferLen, ulFlags,
4337                                            hMachine);
4338     if (ret != CR_SUCCESS)
4339         goto Done;
4340 
4341     if (WideCharToMultiByte(CP_ACP,
4342                             0,
4343                             BufferW,
4344                             lstrlenW(BufferW) + 1,
4345                             Buffer,
4346                             BufferLen,
4347                             NULL,
4348                             NULL) == 0)
4349         ret = CR_FAILURE;
4350 
4351 Done:
4352     if (BufferW != NULL)
4353         MyFree(BufferW);
4354 
4355     if (pDeviceIdW != NULL)
4356         MyFree(pDeviceIdW);
4357 
4358     return ret;
4359 }
4360 
4361 
4362 /***********************************************************************
4363  *      CM_Get_Device_Interface_List_ExW (SETUPAPI.@)
4364  */
4365 CONFIGRET
4366 WINAPI
4367 CM_Get_Device_Interface_List_ExW(
4368     _In_ LPGUID InterfaceClassGuid,
4369     _In_opt_ DEVINSTID_W pDeviceID,
4370     _Out_writes_(BufferLen) PWCHAR Buffer,
4371     _In_ ULONG BufferLen,
4372     _In_ ULONG ulFlags,
4373     _In_opt_ HMACHINE hMachine)
4374 {
4375     RPC_BINDING_HANDLE BindingHandle = NULL;
4376     PNP_RPC_BUFFER_SIZE BufferSize = 0;
4377     CONFIGRET ret = CR_SUCCESS;
4378 
4379     TRACE("CM_Get_Device_Interface_List_ExW(%s %s %p %lu 0x%08lx %p)\n",
4380           debugstr_guid(InterfaceClassGuid), debugstr_w(pDeviceID),
4381           Buffer, BufferLen, ulFlags, hMachine);
4382 
4383     if (Buffer == NULL ||
4384         BufferLen == 0)
4385         return CR_INVALID_POINTER;
4386 
4387     if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
4388         return CR_INVALID_FLAG;
4389 
4390     if (hMachine != NULL)
4391     {
4392         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4393         if (BindingHandle == NULL)
4394             return CR_FAILURE;
4395     }
4396     else
4397     {
4398         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4399             return CR_FAILURE;
4400     }
4401 
4402     *Buffer = 0;
4403     BufferSize = BufferLen;
4404 
4405     RpcTryExcept
4406     {
4407         ret = PNP_GetInterfaceDeviceList(BindingHandle,
4408                                          InterfaceClassGuid,
4409                                          pDeviceID,
4410                                          (LPBYTE)Buffer,
4411                                          &BufferSize,
4412                                          ulFlags);
4413     }
4414     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4415     {
4416         ret = RpcStatusToCmStatus(RpcExceptionCode());
4417     }
4418     RpcEndExcept;
4419 
4420     return ret;
4421 }
4422 
4423 
4424 /***********************************************************************
4425  *      CM_Get_Device_Interface_List_SizeA (SETUPAPI.@)
4426  */
4427 CONFIGRET
4428 WINAPI
4429 CM_Get_Device_Interface_List_SizeA(
4430     _Out_ PULONG pulLen,
4431     _In_ LPGUID InterfaceClassGuid,
4432     _In_opt_ DEVINSTID_A pDeviceID,
4433     _In_ ULONG ulFlags)
4434 {
4435     TRACE("CM_Get_Device_Interface_List_SizeA(%p %p %s 0x%08lx)\n",
4436           pulLen, InterfaceClassGuid, debugstr_a(pDeviceID), ulFlags);
4437 
4438     return CM_Get_Device_Interface_List_Size_ExA(pulLen, InterfaceClassGuid,
4439                                                  pDeviceID, ulFlags, NULL);
4440 }
4441 
4442 
4443 /***********************************************************************
4444  *      CM_Get_Device_Interface_List_SizeW (SETUPAPI.@)
4445  */
4446 CONFIGRET
4447 WINAPI
4448 CM_Get_Device_Interface_List_SizeW(
4449     _Out_ PULONG pulLen,
4450     _In_ LPGUID InterfaceClassGuid,
4451     _In_opt_ DEVINSTID_W pDeviceID,
4452     _In_ ULONG ulFlags)
4453 {
4454     TRACE("CM_Get_Device_Interface_List_SizeW(%p %p %s 0x%08lx)\n",
4455           pulLen, InterfaceClassGuid, debugstr_w(pDeviceID), ulFlags);
4456 
4457     return CM_Get_Device_Interface_List_Size_ExW(pulLen, InterfaceClassGuid,
4458                                                  pDeviceID, ulFlags, NULL);
4459 }
4460 
4461 
4462 /***********************************************************************
4463  *      CM_Get_Device_Interface_List_Size_ExA (SETUPAPI.@)
4464  */
4465 CONFIGRET
4466 WINAPI
4467 CM_Get_Device_Interface_List_Size_ExA(
4468     _Out_ PULONG pulLen,
4469     _In_ LPGUID InterfaceClassGuid,
4470     _In_opt_ DEVINSTID_A pDeviceID,
4471     _In_ ULONG ulFlags,
4472     _In_opt_ HMACHINE hMachine)
4473 {
4474     DEVINSTID_W pDeviceIdW = NULL;
4475     CONFIGRET ret = CR_SUCCESS;
4476 
4477     TRACE("CM_Get_Device_Interface_List_Size_ExA(%p %p %s 0x%08lx %p)\n",
4478           pulLen, InterfaceClassGuid, debugstr_a(pDeviceID), ulFlags, hMachine);
4479 
4480     if (pulLen == NULL)
4481         return CR_INVALID_POINTER;
4482 
4483     if (pDeviceID != NULL)
4484     {
4485         if (!pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDeviceIdW))
4486             return CR_INVALID_DEVICE_ID;
4487     }
4488 
4489     *pulLen = 0;
4490 
4491     ret = CM_Get_Device_Interface_List_Size_ExW(pulLen, InterfaceClassGuid,
4492                                                 pDeviceIdW, ulFlags, hMachine);
4493 
4494     if (pDeviceIdW != NULL)
4495         MyFree(pDeviceIdW);
4496 
4497     return ret;
4498 }
4499 
4500 
4501 /***********************************************************************
4502  *      CM_Get_Device_Interface_List_Size_ExW (SETUPAPI.@)
4503  */
4504 CONFIGRET
4505 WINAPI
4506 CM_Get_Device_Interface_List_Size_ExW(
4507     _Out_ PULONG pulLen,
4508     _In_ LPGUID InterfaceClassGuid,
4509     _In_opt_ DEVINSTID_W pDeviceID,
4510     _In_ ULONG ulFlags,
4511     _In_opt_ HMACHINE hMachine)
4512 {
4513     RPC_BINDING_HANDLE BindingHandle = NULL;
4514     CONFIGRET ret = CR_SUCCESS;
4515 
4516     TRACE("CM_Get_Device_Interface_List_Size_ExW(%p %p %s 0x%08lx %p)\n",
4517           pulLen, InterfaceClassGuid, debugstr_w(pDeviceID), ulFlags, hMachine);
4518 
4519     if (pulLen == NULL)
4520         return CR_INVALID_POINTER;
4521 
4522     if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
4523         return CR_INVALID_FLAG;
4524 
4525     if (hMachine != NULL)
4526     {
4527         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4528         if (BindingHandle == NULL)
4529             return CR_FAILURE;
4530     }
4531     else
4532     {
4533         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4534             return CR_FAILURE;
4535     }
4536 
4537     *pulLen = 0;
4538 
4539     RpcTryExcept
4540     {
4541         ret = PNP_GetInterfaceDeviceListSize(BindingHandle,
4542                                              pulLen,
4543                                              InterfaceClassGuid,
4544                                              pDeviceID,
4545                                              ulFlags);
4546     }
4547     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4548     {
4549         ret = RpcStatusToCmStatus(RpcExceptionCode());
4550     }
4551     RpcEndExcept;
4552 
4553     return ret;
4554 }
4555 
4556 
4557 /***********************************************************************
4558  * CM_Get_First_Log_Conf [SETUPAPI.@]
4559  */
4560 CONFIGRET
4561 WINAPI
4562 CM_Get_First_Log_Conf(
4563     _Out_opt_ PLOG_CONF plcLogConf,
4564     _In_ DEVINST dnDevInst,
4565     _In_ ULONG ulFlags)
4566 {
4567     TRACE("CM_Get_First_Log_Conf(%p %lx %lx)\n",
4568           plcLogConf, dnDevInst, ulFlags);
4569 
4570     return CM_Get_First_Log_Conf_Ex(plcLogConf, dnDevInst, ulFlags, NULL);
4571 }
4572 
4573 
4574 /***********************************************************************
4575  * CM_Get_First_Log_Conf_Ex [SETUPAPI.@]
4576  */
4577 CONFIGRET
4578 WINAPI
4579 CM_Get_First_Log_Conf_Ex(
4580     _Out_opt_ PLOG_CONF plcLogConf,
4581     _In_ DEVINST dnDevInst,
4582     _In_ ULONG ulFlags,
4583     _In_opt_ HMACHINE hMachine)
4584 {
4585     RPC_BINDING_HANDLE BindingHandle = NULL;
4586     HSTRING_TABLE StringTable = NULL;
4587     LPWSTR lpDevInst = NULL;
4588     CONFIGRET ret = CR_SUCCESS;
4589     ULONG ulTag;
4590     PLOG_CONF_INFO pLogConfInfo;
4591 
4592     FIXME("CM_Get_First_Log_Conf_Ex(%p %lx %lx %p)\n",
4593           plcLogConf, dnDevInst, ulFlags, hMachine);
4594 
4595     if (dnDevInst == 0)
4596         return CR_INVALID_DEVINST;
4597 
4598     if (ulFlags & ~LOG_CONF_BITS)
4599         return CR_INVALID_FLAG;
4600 
4601     if (plcLogConf)
4602         *plcLogConf = 0;
4603 
4604     if (hMachine != NULL)
4605     {
4606         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4607         if (BindingHandle == NULL)
4608             return CR_FAILURE;
4609 
4610         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
4611         if (StringTable == 0)
4612             return CR_FAILURE;
4613     }
4614     else
4615     {
4616         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
4617             return CR_FAILURE;
4618     }
4619 
4620     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
4621     if (lpDevInst == NULL)
4622         return CR_INVALID_DEVNODE;
4623 
4624     RpcTryExcept
4625     {
4626         ret = PNP_GetFirstLogConf(BindingHandle,
4627                                   lpDevInst,
4628                                   ulFlags,
4629                                   &ulTag,
4630                                   ulFlags);
4631     }
4632     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4633     {
4634         ret = RpcStatusToCmStatus(RpcExceptionCode());
4635     }
4636     RpcEndExcept;
4637 
4638     if (ret != CR_SUCCESS)
4639         return ret;
4640 
4641     if (plcLogConf)
4642     {
4643         pLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
4644         if (pLogConfInfo == NULL)
4645             return CR_OUT_OF_MEMORY;
4646 
4647         pLogConfInfo->ulMagic = LOG_CONF_MAGIC;
4648         pLogConfInfo->dnDevInst = dnDevInst;
4649         pLogConfInfo->ulFlags = ulFlags;
4650         pLogConfInfo->ulTag = ulTag;
4651 
4652         *plcLogConf = (LOG_CONF)pLogConfInfo;
4653     }
4654 
4655     return CR_SUCCESS;
4656 }
4657 
4658 
4659 /***********************************************************************
4660  * CM_Get_Global_State [SETUPAPI.@]
4661  */
4662 CONFIGRET
4663 WINAPI
4664 CM_Get_Global_State(
4665     _Out_ PULONG pulState,
4666     _In_ ULONG ulFlags)
4667 {
4668     TRACE("CM_Get_Global_State(%p %lx)\n",
4669           pulState, ulFlags);
4670 
4671     return CM_Get_Global_State_Ex(pulState, ulFlags, NULL);
4672 }
4673 
4674 
4675 /***********************************************************************
4676  * CM_Get_Global_State_Ex [SETUPAPI.@]
4677  */
4678 CONFIGRET
4679 WINAPI
4680 CM_Get_Global_State_Ex(
4681     _Out_ PULONG pulState,
4682     _In_ ULONG ulFlags,
4683     _In_opt_ HMACHINE hMachine)
4684 {
4685     RPC_BINDING_HANDLE BindingHandle = NULL;
4686     CONFIGRET ret;
4687 
4688     TRACE("CM_Get_Global_State_Ex(%p %lx %p)\n",
4689           pulState, ulFlags, hMachine);
4690 
4691     if (pulState == NULL)
4692         return CR_INVALID_POINTER;
4693 
4694     if (ulFlags != 0)
4695         return CR_INVALID_FLAG;
4696 
4697     if (hMachine != NULL)
4698     {
4699         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4700         if (BindingHandle == NULL)
4701             return CR_FAILURE;
4702     }
4703     else
4704     {
4705         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4706             return CR_FAILURE;
4707     }
4708 
4709     RpcTryExcept
4710     {
4711         ret = PNP_GetGlobalState(BindingHandle, pulState, ulFlags);
4712     }
4713     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4714     {
4715         ret = RpcStatusToCmStatus(RpcExceptionCode());
4716     }
4717     RpcEndExcept;
4718 
4719     return ret;
4720 }
4721 
4722 
4723 /***********************************************************************
4724  * CM_Get_HW_Prof_FlagsA [SETUPAPI.@]
4725  */
4726 CONFIGRET
4727 WINAPI
4728 CM_Get_HW_Prof_FlagsA(
4729     _In_ DEVINSTID_A szDevInstName,
4730     _In_ ULONG ulHardwareProfile,
4731     _Out_ PULONG pulValue,
4732     _In_ ULONG ulFlags)
4733 {
4734     TRACE("CM_Get_HW_Prof_FlagsA(%s %lu %p %lx)\n",
4735           debugstr_a(szDevInstName), ulHardwareProfile, pulValue, ulFlags);
4736 
4737     return CM_Get_HW_Prof_Flags_ExA(szDevInstName, ulHardwareProfile,
4738                                     pulValue, ulFlags, NULL);
4739 }
4740 
4741 
4742 /***********************************************************************
4743  * CM_Get_HW_Prof_FlagsW [SETUPAPI.@]
4744  */
4745 CONFIGRET
4746 WINAPI
4747 CM_Get_HW_Prof_FlagsW(
4748     _In_ DEVINSTID_W szDevInstName,
4749     _In_ ULONG ulHardwareProfile,
4750     _Out_ PULONG pulValue,
4751     _In_ ULONG ulFlags)
4752 {
4753     TRACE("CM_Get_HW_Prof_FlagsW(%s %lu %p %lx)\n",
4754           debugstr_w(szDevInstName), ulHardwareProfile, pulValue, ulFlags);
4755 
4756     return CM_Get_HW_Prof_Flags_ExW(szDevInstName, ulHardwareProfile,
4757                                     pulValue, ulFlags, NULL);
4758 }
4759 
4760 
4761 /***********************************************************************
4762  * CM_Get_HW_Prof_Flags_ExA [SETUPAPI.@]
4763  */
4764 CONFIGRET
4765 WINAPI
4766 CM_Get_HW_Prof_Flags_ExA(
4767     _In_ DEVINSTID_A szDevInstName,
4768     _In_ ULONG ulHardwareProfile,
4769     _Out_ PULONG pulValue,
4770     _In_ ULONG ulFlags,
4771     _In_opt_ HMACHINE hMachine)
4772 {
4773     DEVINSTID_W pszDevIdW = NULL;
4774     CONFIGRET ret = CR_SUCCESS;
4775 
4776     TRACE("CM_Get_HW_Prof_Flags_ExA(%s %lu %p %lx %p)\n",
4777           debugstr_a(szDevInstName), ulHardwareProfile, pulValue, ulFlags, hMachine);
4778 
4779     if (szDevInstName != NULL)
4780     {
4781        if (pSetupCaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
4782          return CR_INVALID_DEVICE_ID;
4783     }
4784 
4785     ret = CM_Get_HW_Prof_Flags_ExW(pszDevIdW, ulHardwareProfile,
4786                                    pulValue, ulFlags, hMachine);
4787 
4788     if (pszDevIdW != NULL)
4789         MyFree(pszDevIdW);
4790 
4791     return ret;
4792 }
4793 
4794 
4795 /***********************************************************************
4796  * CM_Get_HW_Prof_Flags_ExW [SETUPAPI.@]
4797  */
4798 CONFIGRET
4799 WINAPI
4800 CM_Get_HW_Prof_Flags_ExW(
4801     _In_ DEVINSTID_W szDevInstName,
4802     _In_ ULONG ulHardwareProfile,
4803     _Out_ PULONG pulValue,
4804     _In_ ULONG ulFlags,
4805     _In_opt_ HMACHINE hMachine)
4806 {
4807     RPC_BINDING_HANDLE BindingHandle = NULL;
4808     CONFIGRET ret;
4809 
4810     FIXME("CM_Get_HW_Prof_Flags_ExW(%s %lu %p %lx %p)\n",
4811           debugstr_w(szDevInstName), ulHardwareProfile, pulValue, ulFlags, hMachine);
4812 
4813     if ((szDevInstName == NULL) || (pulValue == NULL))
4814         return CR_INVALID_POINTER;
4815 
4816     if (ulFlags != 0)
4817         return CR_INVALID_FLAG;
4818 
4819     /* FIXME: Check whether szDevInstName is valid */
4820 
4821     if (hMachine != NULL)
4822     {
4823         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4824         if (BindingHandle == NULL)
4825             return CR_FAILURE;
4826     }
4827     else
4828     {
4829         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4830             return CR_FAILURE;
4831     }
4832 
4833     RpcTryExcept
4834     {
4835         ret = PNP_HwProfFlags(BindingHandle, PNP_GET_HWPROFFLAGS, szDevInstName,
4836                               ulHardwareProfile, pulValue, NULL, NULL, 0, 0);
4837     }
4838     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4839     {
4840         ret = RpcStatusToCmStatus(RpcExceptionCode());
4841     }
4842     RpcEndExcept;
4843 
4844     return ret;
4845 }
4846 
4847 
4848 /***********************************************************************
4849  * CM_Get_Hardware_Profile_InfoA [SETUPAPI.@]
4850  */
4851 CONFIGRET
4852 WINAPI
4853 CM_Get_Hardware_Profile_InfoA(
4854     _In_ ULONG ulIndex,
4855     _Out_ PHWPROFILEINFO_A pHWProfileInfo,
4856     _In_ ULONG ulFlags)
4857 {
4858     TRACE("CM_Get_Hardware_Profile_InfoA(%lu %p %lx)\n",
4859           ulIndex, pHWProfileInfo, ulFlags);
4860 
4861     return CM_Get_Hardware_Profile_Info_ExA(ulIndex, pHWProfileInfo,
4862                                             ulFlags, NULL);
4863 }
4864 
4865 
4866 /***********************************************************************
4867  * CM_Get_Hardware_Profile_InfoW [SETUPAPI.@]
4868  */
4869 CONFIGRET
4870 WINAPI
4871 CM_Get_Hardware_Profile_InfoW(
4872     _In_ ULONG ulIndex,
4873     _Out_ PHWPROFILEINFO_W pHWProfileInfo,
4874     _In_ ULONG ulFlags)
4875 {
4876     TRACE("CM_Get_Hardware_Profile_InfoW(%lu %p %lx)\n",
4877           ulIndex, pHWProfileInfo, ulFlags);
4878 
4879     return CM_Get_Hardware_Profile_Info_ExW(ulIndex, pHWProfileInfo,
4880                                             ulFlags, NULL);
4881 }
4882 
4883 
4884 /***********************************************************************
4885  * CM_Get_Hardware_Profile_Info_ExA [SETUPAPI.@]
4886  */
4887 CONFIGRET
4888 WINAPI
4889 CM_Get_Hardware_Profile_Info_ExA(
4890     _In_ ULONG ulIndex,
4891     _Out_ PHWPROFILEINFO_A pHWProfileInfo,
4892     _In_ ULONG ulFlags,
4893     _In_opt_ HMACHINE hMachine)
4894 {
4895     HWPROFILEINFO_W LocalProfileInfo;
4896     CONFIGRET ret;
4897 
4898     TRACE("CM_Get_Hardware_Profile_Info_ExA(%lu %p %lx %p)\n",
4899           ulIndex, pHWProfileInfo, ulFlags, hMachine);
4900 
4901     if (pHWProfileInfo == NULL)
4902         return CR_INVALID_POINTER;
4903 
4904     ret = CM_Get_Hardware_Profile_Info_ExW(ulIndex, &LocalProfileInfo,
4905                                            ulFlags, hMachine);
4906     if (ret == CR_SUCCESS)
4907     {
4908         pHWProfileInfo->HWPI_ulHWProfile = LocalProfileInfo.HWPI_ulHWProfile;
4909         pHWProfileInfo->HWPI_dwFlags = LocalProfileInfo.HWPI_dwFlags;
4910 
4911         if (WideCharToMultiByte(CP_ACP,
4912                                 0,
4913                                 LocalProfileInfo.HWPI_szFriendlyName,
4914                                 lstrlenW(LocalProfileInfo.HWPI_szFriendlyName) + 1,
4915                                 pHWProfileInfo->HWPI_szFriendlyName,
4916                                 MAX_PROFILE_LEN,
4917                                 NULL,
4918                                 NULL) == 0)
4919             ret = CR_FAILURE;
4920     }
4921 
4922     return ret;
4923 }
4924 
4925 
4926 /***********************************************************************
4927  * CM_Get_Hardware_Profile_Info_ExW [SETUPAPI.@]
4928  */
4929 CONFIGRET
4930 WINAPI
4931 CM_Get_Hardware_Profile_Info_ExW(
4932     _In_ ULONG ulIndex,
4933     _Out_ PHWPROFILEINFO_W pHWProfileInfo,
4934     _In_ ULONG ulFlags,
4935     _In_opt_ HMACHINE hMachine)
4936 {
4937     RPC_BINDING_HANDLE BindingHandle = NULL;
4938     CONFIGRET ret;
4939 
4940     TRACE("CM_Get_Hardware_Profile_Info_ExW(%lu %p %lx %p)\n",
4941           ulIndex, pHWProfileInfo, ulFlags, hMachine);
4942 
4943     if (pHWProfileInfo == NULL)
4944         return CR_INVALID_POINTER;
4945 
4946     if (ulFlags != 0)
4947         return CR_INVALID_FLAG;
4948 
4949     if (hMachine != NULL)
4950     {
4951         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
4952         if (BindingHandle == NULL)
4953             return CR_FAILURE;
4954     }
4955     else
4956     {
4957         if (!PnpGetLocalHandles(&BindingHandle, NULL))
4958             return CR_FAILURE;
4959     }
4960 
4961     RpcTryExcept
4962     {
4963         ret = PNP_GetHwProfInfo(BindingHandle, ulIndex, pHWProfileInfo,
4964                                 sizeof(HWPROFILEINFO_W), 0);
4965     }
4966     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
4967     {
4968         ret = RpcStatusToCmStatus(RpcExceptionCode());
4969     }
4970     RpcEndExcept;
4971 
4972     return ret;
4973 }
4974 
4975 
4976 /***********************************************************************
4977  * CM_Get_Log_Conf_Priority [SETUPAPI.@]
4978  */
4979 CONFIGRET
4980 WINAPI
4981 CM_Get_Log_Conf_Priority(
4982     _In_ LOG_CONF lcLogConf,
4983     _Out_ PPRIORITY pPriority,
4984     _In_ ULONG ulFlags)
4985 {
4986     TRACE("CM_Get_Log_Conf_Priority(%p %p %lx)\n",
4987           lcLogConf, pPriority, ulFlags);
4988 
4989     return CM_Get_Log_Conf_Priority_Ex(lcLogConf, pPriority, ulFlags, NULL);
4990 }
4991 
4992 
4993 /***********************************************************************
4994  * CM_Get_Log_Conf_Priority_Ex [SETUPAPI.@]
4995  */
4996 CONFIGRET
4997 WINAPI
4998 CM_Get_Log_Conf_Priority_Ex(
4999     _In_ LOG_CONF lcLogConf,
5000     _Out_ PPRIORITY pPriority,
5001     _In_ ULONG ulFlags,
5002     _In_opt_ HMACHINE hMachine)
5003 {
5004     RPC_BINDING_HANDLE BindingHandle = NULL;
5005     HSTRING_TABLE StringTable = NULL;
5006     PLOG_CONF_INFO pLogConfInfo;
5007     LPWSTR lpDevInst;
5008     CONFIGRET ret;
5009 
5010     FIXME("CM_Get_Log_Conf_Priority_Ex(%p %p %lx %p)\n",
5011           lcLogConf, pPriority, ulFlags, hMachine);
5012 
5013     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
5014     if (!IsValidLogConf(pLogConfInfo))
5015         return CR_INVALID_LOG_CONF;
5016 
5017     if (pPriority == NULL)
5018         return CR_INVALID_POINTER;
5019 
5020     if (ulFlags != 0)
5021         return CR_INVALID_FLAG;
5022 
5023     if (hMachine != NULL)
5024     {
5025         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5026         if (BindingHandle == NULL)
5027             return CR_FAILURE;
5028 
5029         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5030         if (StringTable == 0)
5031             return CR_FAILURE;
5032     }
5033     else
5034     {
5035         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5036             return CR_FAILURE;
5037     }
5038 
5039     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
5040     if (lpDevInst == NULL)
5041         return CR_INVALID_DEVNODE;
5042 
5043     RpcTryExcept
5044     {
5045         ret = PNP_GetLogConfPriority(BindingHandle,
5046                                      lpDevInst,
5047                                      pLogConfInfo->ulFlags,
5048                                      pLogConfInfo->ulTag,
5049                                      pPriority,
5050                                      0);
5051     }
5052     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5053     {
5054         ret = RpcStatusToCmStatus(RpcExceptionCode());
5055     }
5056     RpcEndExcept;
5057 
5058     return ret;
5059 }
5060 
5061 
5062 /***********************************************************************
5063  * CM_Get_Next_Log_Conf [SETUPAPI.@]
5064  */
5065 CONFIGRET
5066 WINAPI
5067 CM_Get_Next_Log_Conf(
5068     _Out_opt_ PLOG_CONF plcLogConf,
5069     _In_ LOG_CONF lcLogConf,
5070     _In_ ULONG ulFlags)
5071 {
5072     TRACE("CM_Get_Next_Log_Conf(%p %p %lx)\n",
5073           plcLogConf, lcLogConf, ulFlags);
5074 
5075     return CM_Get_Next_Log_Conf_Ex(plcLogConf, lcLogConf, ulFlags, NULL);
5076 }
5077 
5078 
5079 /***********************************************************************
5080  * CM_Get_Next_Log_Conf_Ex [SETUPAPI.@]
5081  */
5082 CONFIGRET
5083 WINAPI
5084 CM_Get_Next_Log_Conf_Ex(
5085     _Out_opt_ PLOG_CONF plcLogConf,
5086     _In_ LOG_CONF lcLogConf,
5087     _In_ ULONG ulFlags,
5088     _In_opt_ HMACHINE hMachine)
5089 {
5090     RPC_BINDING_HANDLE BindingHandle = NULL;
5091     HSTRING_TABLE StringTable = NULL;
5092     PLOG_CONF_INFO pLogConfInfo;
5093     PLOG_CONF_INFO pNewLogConfInfo;
5094     ULONG ulNewTag;
5095     LPWSTR lpDevInst;
5096     CONFIGRET ret;
5097 
5098     FIXME("CM_Get_Next_Log_Conf_Ex(%p %p %lx %p)\n",
5099           plcLogConf, lcLogConf, ulFlags, hMachine);
5100 
5101     if (plcLogConf)
5102         *plcLogConf = 0;
5103 
5104     pLogConfInfo = (PLOG_CONF_INFO)lcLogConf;
5105     if (!IsValidLogConf(pLogConfInfo))
5106         return CR_INVALID_LOG_CONF;
5107 
5108     if (ulFlags != 0)
5109         return CR_INVALID_FLAG;
5110 
5111     if (hMachine != NULL)
5112     {
5113         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5114         if (BindingHandle == NULL)
5115             return CR_FAILURE;
5116 
5117         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5118         if (StringTable == 0)
5119             return CR_FAILURE;
5120     }
5121     else
5122     {
5123         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5124             return CR_FAILURE;
5125     }
5126 
5127     lpDevInst = pSetupStringTableStringFromId(StringTable, pLogConfInfo->dnDevInst);
5128     if (lpDevInst == NULL)
5129         return CR_INVALID_DEVNODE;
5130 
5131     RpcTryExcept
5132     {
5133         ret = PNP_GetNextLogConf(BindingHandle,
5134                                  lpDevInst,
5135                                  pLogConfInfo->ulFlags,
5136                                  pLogConfInfo->ulTag,
5137                                  &ulNewTag,
5138                                  0);
5139     }
5140     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5141     {
5142         ret = RpcStatusToCmStatus(RpcExceptionCode());
5143     }
5144     RpcEndExcept;
5145 
5146     if (ret != CR_SUCCESS)
5147         return ret;
5148 
5149     if (plcLogConf)
5150     {
5151         pNewLogConfInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(LOG_CONF_INFO));
5152         if (pNewLogConfInfo == NULL)
5153             return CR_OUT_OF_MEMORY;
5154 
5155         pNewLogConfInfo->ulMagic = LOG_CONF_MAGIC;
5156         pNewLogConfInfo->dnDevInst = pLogConfInfo->dnDevInst;
5157         pNewLogConfInfo->ulFlags = pLogConfInfo->ulFlags;
5158         pNewLogConfInfo->ulTag = ulNewTag;
5159 
5160         *plcLogConf = (LOG_CONF)pNewLogConfInfo;
5161     }
5162 
5163     return CR_SUCCESS;
5164 }
5165 
5166 
5167 /***********************************************************************
5168  * CM_Get_Next_Re_Des [SETUPAPI.@]
5169  */
5170 CONFIGRET
5171 WINAPI
5172 CM_Get_Next_Res_Des(
5173     _Out_ PRES_DES prdResDes,
5174     _In_ RES_DES rdResDes,
5175     _In_ RESOURCEID ForResource,
5176     _Out_opt_ PRESOURCEID pResourceID,
5177     _In_ ULONG ulFlags)
5178 {
5179     TRACE("CM_Get_Next_Res_Des(%p %p %lu %p %lx)\n",
5180           prdResDes, rdResDes, ForResource, pResourceID, ulFlags);
5181 
5182     return CM_Get_Next_Res_Des_Ex(prdResDes, rdResDes, ForResource,
5183                                   pResourceID, ulFlags, NULL);
5184 }
5185 
5186 
5187 /***********************************************************************
5188  * CM_Get_Next_Re_Des_Ex [SETUPAPI.@]
5189  */
5190 CONFIGRET
5191 WINAPI
5192 CM_Get_Next_Res_Des_Ex(
5193     _Out_ PRES_DES prdResDes,
5194     _In_ RES_DES rdResDes,
5195     _In_ RESOURCEID ForResource,
5196     _Out_opt_ PRESOURCEID pResourceID,
5197     _In_ ULONG ulFlags,
5198     _In_opt_ HMACHINE hMachine)
5199 {
5200     FIXME("CM_Get_Next_Res_Des_Ex(%p %p %lu %p %lx %p)\n",
5201           prdResDes, rdResDes, ForResource, pResourceID, ulFlags, hMachine);
5202 
5203     return CR_CALL_NOT_IMPLEMENTED;
5204 }
5205 
5206 
5207 /***********************************************************************
5208  * CM_Get_Parent [SETUPAPI.@]
5209  */
5210 CONFIGRET
5211 WINAPI
5212 CM_Get_Parent(
5213     _Out_ PDEVINST pdnDevInst,
5214     _In_ DEVINST dnDevInst,
5215     _In_ ULONG ulFlags)
5216 {
5217     TRACE("CM_Get_Parent(%p %p %lx)\n",
5218           pdnDevInst, dnDevInst, ulFlags);
5219 
5220     return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
5221 }
5222 
5223 
5224 /***********************************************************************
5225  * CM_Get_Parent_Ex [SETUPAPI.@]
5226  */
5227 CONFIGRET
5228 WINAPI
5229 CM_Get_Parent_Ex(
5230     _Out_ PDEVINST pdnDevInst,
5231     _In_ DEVINST dnDevInst,
5232     _In_ ULONG ulFlags,
5233     _In_opt_ HMACHINE hMachine)
5234 {
5235     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
5236     RPC_BINDING_HANDLE BindingHandle = NULL;
5237     HSTRING_TABLE StringTable = NULL;
5238     LPWSTR lpDevInst;
5239     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
5240     CONFIGRET ret;
5241 
5242     TRACE("CM_Get_Parent_Ex(%p %lx %lx %p)\n",
5243           pdnDevInst, dnDevInst, ulFlags, hMachine);
5244 
5245     if (pdnDevInst == NULL)
5246         return CR_INVALID_POINTER;
5247 
5248     if (dnDevInst == 0)
5249         return CR_INVALID_DEVINST;
5250 
5251     if (ulFlags != 0)
5252         return CR_INVALID_FLAG;
5253 
5254     *pdnDevInst = -1;
5255 
5256     if (hMachine != NULL)
5257     {
5258         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5259         if (BindingHandle == NULL)
5260             return CR_FAILURE;
5261 
5262         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5263         if (StringTable == 0)
5264             return CR_FAILURE;
5265     }
5266     else
5267     {
5268         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5269             return CR_FAILURE;
5270     }
5271 
5272     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
5273     if (lpDevInst == NULL)
5274         return CR_INVALID_DEVNODE;
5275 
5276     RpcTryExcept
5277     {
5278         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
5279                                            PNP_GET_PARENT_DEVICE_INSTANCE,
5280                                            lpDevInst,
5281                                            szRelatedDevInst,
5282                                            &dwLength,
5283                                            0);
5284     }
5285     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5286     {
5287         ret = RpcStatusToCmStatus(RpcExceptionCode());
5288     }
5289     RpcEndExcept;
5290 
5291     if (ret != CR_SUCCESS)
5292         return ret;
5293 
5294     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
5295 
5296     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
5297     if (dwIndex == -1)
5298         return CR_FAILURE;
5299 
5300     *pdnDevInst = dwIndex;
5301 
5302     return CR_SUCCESS;
5303 }
5304 
5305 
5306 /***********************************************************************
5307  * CM_Get_Res_Des_Data [SETUPAPI.@]
5308  */
5309 CONFIGRET
5310 WINAPI
5311 CM_Get_Res_Des_Data(
5312     _In_ RES_DES rdResDes,
5313     _Out_writes_bytes_(BufferLen) PVOID Buffer,
5314     _In_ ULONG BufferLen,
5315     _In_ ULONG ulFlags)
5316 {
5317     TRACE("CM_Get_Res_Des_Data(%p %p %lu %lx)\n",
5318           rdResDes, Buffer, BufferLen, ulFlags);
5319 
5320     return CM_Get_Res_Des_Data_Ex(rdResDes, Buffer, BufferLen, ulFlags, NULL);
5321 }
5322 
5323 
5324 /***********************************************************************
5325  * CM_Get_Res_Des_Data_Ex [SETUPAPI.@]
5326  */
5327 CONFIGRET
5328 WINAPI
5329 CM_Get_Res_Des_Data_Ex(
5330     _In_ RES_DES rdResDes,
5331     _Out_writes_bytes_(BufferLen) PVOID Buffer,
5332     _In_ ULONG BufferLen,
5333     _In_ ULONG ulFlags,
5334     _In_opt_ HMACHINE hMachine)
5335 {
5336     FIXME("CM_Get_Res_Des_Data_Ex(%p %p %lu %lx %p)\n",
5337           rdResDes, Buffer, BufferLen, ulFlags, hMachine);
5338 
5339     return CR_CALL_NOT_IMPLEMENTED;
5340 }
5341 
5342 
5343 /***********************************************************************
5344  * CM_Get_Res_Des_Size [SETUPAPI.@]
5345  */
5346 CONFIGRET
5347 WINAPI
5348 CM_Get_Res_Des_Data_Size(
5349     _Out_ PULONG pulSize,
5350     _In_ RES_DES rdResDes,
5351     _In_ ULONG ulFlags)
5352 {
5353     TRACE("CM_Get_Res_Des_Data_Size(%p %p %lx)\n",
5354           pulSize, rdResDes, ulFlags);
5355 
5356     return CM_Get_Res_Des_Data_Size_Ex(pulSize, rdResDes, ulFlags, NULL);
5357 }
5358 
5359 
5360 /***********************************************************************
5361  * CM_Get_Res_Des_Size_Ex [SETUPAPI.@]
5362  */
5363 CONFIGRET
5364 WINAPI
5365 CM_Get_Res_Des_Data_Size_Ex(
5366     _Out_ PULONG pulSize,
5367     _In_ RES_DES rdResDes,
5368     _In_ ULONG ulFlags,
5369     _In_opt_ HMACHINE hMachine)
5370 {
5371     TRACE("CM_Get_Res_Des_Data_Size_Ex(%p %p %lx %p)\n",
5372           pulSize, rdResDes, ulFlags, hMachine);
5373 
5374     return CR_CALL_NOT_IMPLEMENTED;
5375 }
5376 
5377 
5378 /***********************************************************************
5379  * CM_Get_Resource_Conflict_Count [SETUPAPI.@]
5380  */
5381 CONFIGRET
5382 WINAPI
5383 CM_Get_Resource_Conflict_Count(
5384     _In_ CONFLICT_LIST clConflictList,
5385     _Out_ PULONG pulCount)
5386 {
5387     PCONFLICT_DATA pConflictData;
5388 
5389     FIXME("CM_Get_Resource_Conflict_Count(%p %p)\n",
5390           clConflictList, pulCount);
5391 
5392     pConflictData = (PCONFLICT_DATA)clConflictList;
5393     if (!IsValidConflictData(pConflictData))
5394         return CR_INVALID_CONFLICT_LIST;
5395 
5396     if (pulCount == NULL)
5397         return CR_INVALID_POINTER;
5398 
5399     *pulCount = pConflictData->pConflictList->ConflictsListed;
5400 
5401     return CR_SUCCESS;
5402 }
5403 
5404 
5405 /***********************************************************************
5406  * CM_Get_Resource_Conflict_DetailsA [SETUPAPI.@]
5407  */
5408 CONFIGRET
5409 WINAPI
5410 CM_Get_Resource_Conflict_DetailsA(
5411     _In_ CONFLICT_LIST clConflictList,
5412     _In_ ULONG ulIndex,
5413     _Inout_ PCONFLICT_DETAILS_A pConflictDetails)
5414 {
5415     FIXME("CM_Get_Resource_Conflict_CountA(%p %lu %p)\n",
5416           clConflictList, ulIndex, pConflictDetails);
5417 
5418     return CR_CALL_NOT_IMPLEMENTED;
5419 }
5420 
5421 
5422 /***********************************************************************
5423  * CM_Get_Resource_Conflict_DetailsW [SETUPAPI.@]
5424  */
5425 CONFIGRET
5426 WINAPI
5427 CM_Get_Resource_Conflict_DetailsW(
5428     _In_ CONFLICT_LIST clConflictList,
5429     _In_ ULONG ulIndex,
5430     _Inout_ PCONFLICT_DETAILS_W pConflictDetails)
5431 {
5432     FIXME("CM_Get_Resource_Conflict_CountW(%p %lu %p)\n",
5433           clConflictList, ulIndex, pConflictDetails);
5434 
5435     return CR_CALL_NOT_IMPLEMENTED;
5436 }
5437 
5438 
5439 /***********************************************************************
5440  * CM_Get_Sibling [SETUPAPI.@]
5441  */
5442 CONFIGRET
5443 WINAPI
5444 CM_Get_Sibling(
5445     _Out_ PDEVINST pdnDevInst,
5446     _In_ DEVINST dnDevInst,
5447     _In_ ULONG ulFlags)
5448 {
5449     TRACE("CM_Get_Sibling(%p %p %lx)\n",
5450           pdnDevInst, dnDevInst, ulFlags);
5451 
5452     return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
5453 }
5454 
5455 
5456 /***********************************************************************
5457  * CM_Get_Sibling_Ex [SETUPAPI.@]
5458  */
5459 CONFIGRET
5460 WINAPI
5461 CM_Get_Sibling_Ex(
5462     _Out_ PDEVINST pdnDevInst,
5463     _In_ DEVINST dnDevInst,
5464     _In_ ULONG ulFlags,
5465     _In_opt_ HMACHINE hMachine)
5466 {
5467     WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
5468     RPC_BINDING_HANDLE BindingHandle = NULL;
5469     HSTRING_TABLE StringTable = NULL;
5470     LPWSTR lpDevInst;
5471     DWORD dwIndex, dwLength = MAX_DEVICE_ID_LEN;
5472     CONFIGRET ret;
5473 
5474     TRACE("CM_Get_Sibling_Ex(%p %lx %lx %p)\n",
5475           pdnDevInst, dnDevInst, ulFlags, hMachine);
5476 
5477     if (pdnDevInst == NULL)
5478         return CR_INVALID_POINTER;
5479 
5480     if (dnDevInst == 0)
5481         return CR_INVALID_DEVINST;
5482 
5483     if (ulFlags != 0)
5484         return CR_INVALID_FLAG;
5485 
5486     *pdnDevInst = -1;
5487 
5488     if (hMachine != NULL)
5489     {
5490         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5491         if (BindingHandle == NULL)
5492             return CR_FAILURE;
5493 
5494         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5495         if (StringTable == 0)
5496             return CR_FAILURE;
5497     }
5498     else
5499     {
5500         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5501             return CR_FAILURE;
5502     }
5503 
5504     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
5505     if (lpDevInst == NULL)
5506         return CR_INVALID_DEVNODE;
5507 
5508     RpcTryExcept
5509     {
5510         ret = PNP_GetRelatedDeviceInstance(BindingHandle,
5511                                            PNP_GET_SIBLING_DEVICE_INSTANCE,
5512                                            lpDevInst,
5513                                            szRelatedDevInst,
5514                                            &dwLength,
5515                                            0);
5516     }
5517     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5518     {
5519         ret = RpcStatusToCmStatus(RpcExceptionCode());
5520     }
5521     RpcEndExcept;
5522 
5523     if (ret != CR_SUCCESS)
5524         return ret;
5525 
5526     TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
5527 
5528     dwIndex = pSetupStringTableAddString(StringTable, szRelatedDevInst, 1);
5529     if (dwIndex == -1)
5530         return CR_FAILURE;
5531 
5532     *pdnDevInst = dwIndex;
5533 
5534     return CR_SUCCESS;
5535 }
5536 
5537 
5538 /***********************************************************************
5539  * CM_Get_Version [SETUPAPI.@]
5540  */
5541 WORD
5542 WINAPI
5543 CM_Get_Version(VOID)
5544 {
5545     TRACE("CM_Get_Version()\n");
5546 
5547     return CM_Get_Version_Ex(NULL);
5548 }
5549 
5550 
5551 /***********************************************************************
5552  * CM_Get_Version_Ex [SETUPAPI.@]
5553  */
5554 WORD
5555 WINAPI
5556 CM_Get_Version_Ex(
5557     _In_opt_ HMACHINE hMachine)
5558 {
5559     RPC_BINDING_HANDLE BindingHandle = NULL;
5560     WORD Version = 0;
5561     CONFIGRET ret;
5562 
5563     TRACE("CM_Get_Version_Ex(%p)\n", hMachine);
5564 
5565     if (hMachine != NULL)
5566     {
5567         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5568         if (BindingHandle == NULL)
5569             return 0;
5570     }
5571     else
5572     {
5573         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5574             return CR_FAILURE;
5575     }
5576 
5577     RpcTryExcept
5578     {
5579         ret = PNP_GetVersion(BindingHandle, &Version);
5580     }
5581     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5582     {
5583         ret = RpcStatusToCmStatus(RpcExceptionCode());
5584     }
5585     RpcEndExcept;
5586 
5587     if (ret != CR_SUCCESS)
5588         return 0;
5589 
5590     return Version;
5591 }
5592 
5593 
5594 /***********************************************************************
5595  * CM_Intersect_Range_List [SETUPAPI.@]
5596  */
5597 CONFIGRET
5598 WINAPI
5599 CM_Intersect_Range_List(
5600     _In_ RANGE_LIST rlhOld1,
5601     _In_ RANGE_LIST rlhOld2,
5602     _In_ RANGE_LIST rlhNew,
5603     _In_ ULONG ulFlags)
5604 {
5605     FIXME("CM_Intersect_Range_List(%p %p %p %lx)\n",
5606           rlhOld1, rlhOld2, rlhNew, ulFlags);
5607 
5608     return CR_CALL_NOT_IMPLEMENTED;
5609 }
5610 
5611 
5612 /***********************************************************************
5613  * CM_Invert_Range_List [SETUPAPI.@]
5614  */
5615 CONFIGRET
5616 WINAPI
5617 CM_Invert_Range_List(
5618     _In_ RANGE_LIST rlhOld,
5619     _In_ RANGE_LIST rlhNew,
5620     _In_ DWORDLONG ullMaxValue,
5621     _In_ ULONG ulFlags)
5622 {
5623     FIXME("CM_Invert_Range_List(%p %p %I64u %lx)\n",
5624           rlhOld, rlhNew, ullMaxValue, ulFlags);
5625 
5626     return CR_CALL_NOT_IMPLEMENTED;
5627 }
5628 
5629 
5630 /***********************************************************************
5631  * CM_Is_Dock_Station_Present [SETUPAPI.@]
5632  */
5633 CONFIGRET
5634 WINAPI
5635 CM_Is_Dock_Station_Present(
5636     _Out_ PBOOL pbPresent)
5637 {
5638     TRACE("CM_Is_Dock_Station_Present(%p)\n",
5639           pbPresent);
5640 
5641     return CM_Is_Dock_Station_Present_Ex(pbPresent, NULL);
5642 }
5643 
5644 
5645 /***********************************************************************
5646  * CM_Is_Dock_Station_Present_Ex [SETUPAPI.@]
5647  */
5648 CONFIGRET
5649 WINAPI
5650 CM_Is_Dock_Station_Present_Ex(
5651     _Out_ PBOOL pbPresent,
5652     _In_opt_ HMACHINE hMachine)
5653 {
5654     RPC_BINDING_HANDLE BindingHandle = NULL;
5655     CONFIGRET ret;
5656 
5657     TRACE("CM_Is_Dock_Station_Present_Ex(%p %p)\n",
5658           pbPresent, hMachine);
5659 
5660     if (pbPresent == NULL)
5661         return CR_INVALID_POINTER;
5662 
5663     *pbPresent = FALSE;
5664 
5665     if (hMachine != NULL)
5666     {
5667         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5668         if (BindingHandle == NULL)
5669             return CR_FAILURE;
5670     }
5671     else
5672     {
5673         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5674             return CR_FAILURE;
5675     }
5676 
5677     RpcTryExcept
5678     {
5679         ret = PNP_IsDockStationPresent(BindingHandle,
5680                                        pbPresent);
5681     }
5682     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5683     {
5684         ret = RpcStatusToCmStatus(RpcExceptionCode());
5685     }
5686     RpcEndExcept;
5687 
5688     return ret;
5689 }
5690 
5691 
5692 /***********************************************************************
5693  * CM_Is_Version_Available_Ex [SETUPAPI.@]
5694  */
5695 BOOL
5696 WINAPI
5697 CM_Is_Version_Available(
5698      _In_ WORD wVersion)
5699 {
5700     TRACE("CM_Is_Version_Available(%hu)\n",
5701           wVersion);
5702 
5703     return CM_Is_Version_Available_Ex(wVersion, NULL);
5704 }
5705 
5706 
5707 /***********************************************************************
5708  * CM_Is_Version_Available_Ex [SETUPAPI.@]
5709  */
5710 BOOL
5711 WINAPI
5712 CM_Is_Version_Available_Ex(
5713     _In_ WORD wVersion,
5714     _In_opt_ HMACHINE hMachine)
5715 {
5716     RPC_BINDING_HANDLE BindingHandle = NULL;
5717     WORD wServerVersion;
5718     CONFIGRET ret;
5719 
5720     TRACE("CM_Is_Version_Available_Ex(%hu %p)\n",
5721           wVersion, hMachine);
5722 
5723     if (wVersion <= 0x400)
5724         return TRUE;
5725 
5726     if (hMachine != NULL)
5727     {
5728         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5729         if (BindingHandle == NULL)
5730             return FALSE;
5731     }
5732     else
5733     {
5734         if (!PnpGetLocalHandles(&BindingHandle, NULL))
5735             return FALSE;
5736     }
5737 
5738     RpcTryExcept
5739     {
5740         ret = PNP_GetVersion(BindingHandle, &wServerVersion);
5741     }
5742     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5743     {
5744         ret = RpcStatusToCmStatus(RpcExceptionCode());
5745     }
5746     RpcEndExcept;
5747 
5748     if (ret != CR_SUCCESS)
5749         return FALSE;
5750 
5751     return (wServerVersion >= wVersion);
5752 }
5753 
5754 
5755 /***********************************************************************
5756  * CM_Locate_DevNodeA [SETUPAPI.@]
5757  */
5758 CONFIGRET
5759 WINAPI
5760 CM_Locate_DevNodeA(
5761     _Out_ PDEVINST pdnDevInst,
5762     _In_opt_ DEVINSTID_A pDeviceID,
5763     _In_ ULONG ulFlags)
5764 {
5765     TRACE("CM_Locate_DevNodeA(%p %s %lx)\n",
5766           pdnDevInst, debugstr_a(pDeviceID), ulFlags);
5767 
5768     return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
5769 }
5770 
5771 
5772 /***********************************************************************
5773  * CM_Locate_DevNodeW [SETUPAPI.@]
5774  */
5775 CONFIGRET
5776 WINAPI
5777 CM_Locate_DevNodeW(
5778     _Out_ PDEVINST pdnDevInst,
5779     _In_opt_ DEVINSTID_W pDeviceID,
5780     _In_ ULONG ulFlags)
5781 {
5782     TRACE("CM_Locate_DevNodeW(%p %s %lx)\n",
5783           pdnDevInst, debugstr_w(pDeviceID), ulFlags);
5784 
5785     return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
5786 }
5787 
5788 
5789 /***********************************************************************
5790  * CM_Locate_DevNode_ExA [SETUPAPI.@]
5791  */
5792 CONFIGRET
5793 WINAPI
5794 CM_Locate_DevNode_ExA(
5795     _Out_ PDEVINST pdnDevInst,
5796     _In_opt_ DEVINSTID_A pDeviceID,
5797     _In_ ULONG ulFlags,
5798     _In_opt_ HMACHINE hMachine)
5799 {
5800     DEVINSTID_W pDevIdW = NULL;
5801     CONFIGRET ret = CR_SUCCESS;
5802 
5803     TRACE("CM_Locate_DevNode_ExA(%p %s %lx %p)\n",
5804           pdnDevInst, debugstr_a(pDeviceID), ulFlags, hMachine);
5805 
5806     if (pDeviceID != NULL)
5807     {
5808        if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pDevIdW))
5809          return CR_INVALID_DEVICE_ID;
5810     }
5811 
5812     ret = CM_Locate_DevNode_ExW(pdnDevInst, pDevIdW, ulFlags, hMachine);
5813 
5814     if (pDevIdW != NULL)
5815         MyFree(pDevIdW);
5816 
5817     return ret;
5818 }
5819 
5820 
5821 /***********************************************************************
5822  * CM_Locate_DevNode_ExW [SETUPAPI.@]
5823  */
5824 CONFIGRET
5825 WINAPI
5826 CM_Locate_DevNode_ExW(
5827     _Out_ PDEVINST pdnDevInst,
5828     _In_opt_ DEVINSTID_W pDeviceID,
5829     _In_ ULONG ulFlags,
5830     _In_opt_ HMACHINE hMachine)
5831 {
5832     WCHAR DeviceIdBuffer[MAX_DEVICE_ID_LEN];
5833     RPC_BINDING_HANDLE BindingHandle = NULL;
5834     HSTRING_TABLE StringTable = NULL;
5835     CONFIGRET ret = CR_SUCCESS;
5836 
5837     TRACE("CM_Locate_DevNode_ExW(%p %s %lx %p)\n",
5838           pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
5839 
5840     if (pdnDevInst == NULL)
5841         return CR_INVALID_POINTER;
5842 
5843     if (ulFlags & ~CM_LOCATE_DEVNODE_BITS)
5844         return CR_INVALID_FLAG;
5845 
5846     if (hMachine != NULL)
5847     {
5848         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
5849         if (BindingHandle == NULL)
5850             return CR_FAILURE;
5851 
5852         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
5853         if (StringTable == 0)
5854             return CR_FAILURE;
5855     }
5856     else
5857     {
5858         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
5859             return CR_FAILURE;
5860     }
5861 
5862     if (pDeviceID != NULL && lstrlenW(pDeviceID) != 0)
5863     {
5864         lstrcpyW(DeviceIdBuffer, pDeviceID);
5865     }
5866     else
5867     {
5868         RpcTryExcept
5869         {
5870             /* Get the root device ID */
5871             ret = PNP_GetRootDeviceInstance(BindingHandle,
5872                                             DeviceIdBuffer,
5873                                             MAX_DEVICE_ID_LEN);
5874         }
5875         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5876         {
5877             ret = RpcStatusToCmStatus(RpcExceptionCode());
5878         }
5879         RpcEndExcept;
5880 
5881         if (ret != CR_SUCCESS)
5882             return CR_FAILURE;
5883     }
5884     TRACE("DeviceIdBuffer: %s\n", debugstr_w(DeviceIdBuffer));
5885 
5886     RpcTryExcept
5887     {
5888         /* Validate the device ID */
5889         ret = PNP_ValidateDeviceInstance(BindingHandle,
5890                                          DeviceIdBuffer,
5891                                          ulFlags);
5892     }
5893     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
5894     {
5895         ret = RpcStatusToCmStatus(RpcExceptionCode());
5896     }
5897     RpcEndExcept;
5898 
5899     if (ret == CR_SUCCESS)
5900     {
5901         *pdnDevInst = pSetupStringTableAddString(StringTable, DeviceIdBuffer, 1);
5902         if (*pdnDevInst == -1)
5903             ret = CR_FAILURE;
5904     }
5905 
5906     return ret;
5907 }
5908 
5909 
5910 /***********************************************************************
5911  * CM_Merge_Range_List [SETUPAPI.@]
5912  */
5913 CONFIGRET
5914 WINAPI
5915 CM_Merge_Range_List(
5916     _In_ RANGE_LIST rlhOld1,
5917     _In_ RANGE_LIST rlhOld2,
5918     _In_ RANGE_LIST rlhNew,
5919     _In_ ULONG ulFlags)
5920 {
5921     FIXME("CM_Merge_Range_List(%p %p %p %lx)\n",
5922           rlhOld1, rlhOld2, rlhNew, ulFlags);
5923 
5924     return CR_CALL_NOT_IMPLEMENTED;
5925 }
5926 
5927 
5928 /***********************************************************************
5929  * CM_Modify_Res_Des [SETUPAPI.@]
5930  */
5931 CONFIGRET
5932 WINAPI
5933 CM_Modify_Res_Des(
5934     _Out_ PRES_DES prdResDes,
5935     _In_ RES_DES rdResDes,
5936     _In_ RESOURCEID ResourceID,
5937     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
5938     _In_ ULONG ResourceLen,
5939     _In_ ULONG ulFlags)
5940 {
5941     TRACE("CM_Modify_Res_Des(%p %p %lx %p %lu %lx)\n",
5942           prdResDes, rdResDes, ResourceID, ResourceData,
5943           ResourceLen, ulFlags);
5944 
5945     return CM_Modify_Res_Des_Ex(prdResDes, rdResDes, ResourceID, ResourceData,
5946                                 ResourceLen, ulFlags, NULL);
5947 }
5948 
5949 
5950 /***********************************************************************
5951  * CM_Modify_Res_Des_Ex [SETUPAPI.@]
5952  */
5953 CONFIGRET
5954 WINAPI
5955 CM_Modify_Res_Des_Ex(
5956     _Out_ PRES_DES prdResDes,
5957     _In_ RES_DES rdResDes,
5958     _In_ RESOURCEID ResourceID,
5959     _In_reads_bytes_(ResourceLen) PCVOID ResourceData,
5960     _In_ ULONG ResourceLen,
5961     _In_ ULONG ulFlags,
5962     _In_opt_ HMACHINE hMachine)
5963 {
5964     FIXME("CM_Modify_Res_Des_Ex(%p %p %lx %p %lu %lx %p)\n",
5965           prdResDes, rdResDes, ResourceID, ResourceData,
5966           ResourceLen, ulFlags, hMachine);
5967 
5968     return CR_CALL_NOT_IMPLEMENTED;
5969 }
5970 
5971 
5972 /***********************************************************************
5973  * CM_Move_DevNode [SETUPAPI.@]
5974  */
5975 CONFIGRET
5976 WINAPI
5977 CM_Move_DevNode(
5978     _In_ DEVINST dnFromDevInst,
5979     _In_ DEVINST dnToDevInst,
5980     _In_ ULONG ulFlags)
5981 {
5982     TRACE("CM_Move_DevNode(%lx %lx %lx)\n",
5983           dnFromDevInst, dnToDevInst, ulFlags);
5984 
5985     return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
5986 }
5987 
5988 
5989 /***********************************************************************
5990  * CM_Move_DevNode_Ex [SETUPAPI.@]
5991  */
5992 CONFIGRET
5993 WINAPI
5994 CM_Move_DevNode_Ex(
5995     _In_ DEVINST dnFromDevInst,
5996     _In_ DEVINST dnToDevInst,
5997     _In_ ULONG ulFlags,
5998     _In_opt_ HMACHINE hMachine)
5999 {
6000     RPC_BINDING_HANDLE BindingHandle = NULL;
6001     HSTRING_TABLE StringTable = NULL;
6002     LPWSTR lpFromDevInst;
6003     LPWSTR lpToDevInst;
6004     CONFIGRET ret;
6005 
6006     FIXME("CM_Move_DevNode_Ex(%lx %lx %lx %p)\n",
6007           dnFromDevInst, dnToDevInst, ulFlags, hMachine);
6008 
6009     if (!pSetupIsUserAdmin())
6010         return CR_ACCESS_DENIED;
6011 
6012     if (dnFromDevInst == 0 || dnToDevInst == 0)
6013         return CR_INVALID_DEVNODE;
6014 
6015     if (ulFlags != 0)
6016         return CR_INVALID_FLAG;
6017 
6018     if (hMachine != NULL)
6019     {
6020         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6021         if (BindingHandle == NULL)
6022             return CR_FAILURE;
6023 
6024         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6025         if (StringTable == 0)
6026             return CR_FAILURE;
6027     }
6028     else
6029     {
6030         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6031             return CR_FAILURE;
6032     }
6033 
6034     lpFromDevInst = pSetupStringTableStringFromId(StringTable, dnFromDevInst);
6035     if (lpFromDevInst == NULL)
6036         return CR_INVALID_DEVNODE;
6037 
6038     lpToDevInst = pSetupStringTableStringFromId(StringTable, dnToDevInst);
6039     if (lpToDevInst == NULL)
6040         return CR_INVALID_DEVNODE;
6041 
6042     RpcTryExcept
6043     {
6044         ret = PNP_DeviceInstanceAction(BindingHandle,
6045                                        PNP_DEVINST_MOVE,
6046                                        ulFlags,
6047                                        lpFromDevInst,
6048                                        lpToDevInst);
6049     }
6050     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6051     {
6052         ret = RpcStatusToCmStatus(RpcExceptionCode());
6053     }
6054     RpcEndExcept;
6055 
6056     return ret;
6057 }
6058 
6059 
6060 /***********************************************************************
6061  * CM_Next_Range [SETUPAPI.@]
6062  */
6063 CONFIGRET
6064 WINAPI
6065 CM_Next_Range(
6066     _Inout_ PRANGE_ELEMENT preElement,
6067     _Out_ PDWORDLONG pullStart,
6068     _Out_ PDWORDLONG pullEnd,
6069     _In_ ULONG ulFlags)
6070 {
6071     PINTERNAL_RANGE_LIST pRangeList;
6072     PINTERNAL_RANGE pRange;
6073     PLIST_ENTRY ListEntry;
6074     CONFIGRET ret = CR_SUCCESS;
6075 
6076     FIXME("CM_Next_Range(%p %p %p %lx)\n",
6077           preElement, pullStart, pullEnd, ulFlags);
6078 
6079     pRange = (PINTERNAL_RANGE)preElement;
6080 
6081     if (pRange == NULL || pRange->pRangeList == NULL)
6082         return CR_FAILURE;
6083 
6084     if (pullStart == NULL || pullEnd == NULL)
6085         return CR_INVALID_POINTER;
6086 
6087     if (ulFlags != 0)
6088         return CR_INVALID_FLAG;
6089 
6090     pRangeList = pRange->pRangeList;
6091 
6092     /* Lock the range list */
6093     WaitForSingleObject(pRangeList->hMutex, INFINITE);
6094 
6095     /* Fail, if we reached the end of the list */
6096     if (pRange->ListEntry.Flink == &pRangeList->ListHead)
6097     {
6098         ret = CR_FAILURE;
6099         goto done;
6100     }
6101 
6102     /* Get the next range */
6103     ListEntry = pRangeList->ListHead.Flink;
6104     pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry);
6105 
6106     /* Return the range data */
6107     *pullStart = pRange->ullStart;
6108     *pullEnd = pRange->ullEnd;
6109     *preElement = (RANGE_ELEMENT)pRange;
6110 
6111 done:
6112     /* Unlock the range list */
6113     ReleaseMutex(pRangeList->hMutex);
6114 
6115     return ret;
6116 }
6117 
6118 
6119 /***********************************************************************
6120  * CM_Open_Class_KeyA [SETUPAPI.@]
6121  */
6122 CONFIGRET
6123 WINAPI
6124 CM_Open_Class_KeyA(
6125     _In_opt_ LPGUID pClassGuid,
6126     _In_opt_ LPCSTR pszClassName,
6127     _In_ REGSAM samDesired,
6128     _In_ REGDISPOSITION Disposition,
6129     _Out_ PHKEY phkClass,
6130     _In_ ULONG ulFlags)
6131 {
6132     TRACE("CM_Open_Class_KeyA(%p %s %lx %lx %p %lx)\n",
6133           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
6134           samDesired, Disposition, phkClass, ulFlags);
6135 
6136     return CM_Open_Class_Key_ExA(pClassGuid, pszClassName, samDesired,
6137                                  Disposition, phkClass, ulFlags, NULL);
6138 }
6139 
6140 
6141 /***********************************************************************
6142  * CM_Open_Class_KeyW [SETUPAPI.@]
6143  */
6144 CONFIGRET
6145 WINAPI
6146 CM_Open_Class_KeyW(
6147     _In_opt_ LPGUID pClassGuid,
6148     _In_opt_ LPCWSTR pszClassName,
6149     _In_ REGSAM samDesired,
6150     _In_ REGDISPOSITION Disposition,
6151     _Out_ PHKEY phkClass,
6152     _In_ ULONG ulFlags)
6153 {
6154     TRACE("CM_Open_Class_KeyW%p %s %lx %lx %p %lx)\n",
6155           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
6156           samDesired, Disposition, phkClass, ulFlags);
6157 
6158     return CM_Open_Class_Key_ExW(pClassGuid, pszClassName, samDesired,
6159                                  Disposition, phkClass, ulFlags, NULL);
6160 }
6161 
6162 
6163 /***********************************************************************
6164  * CM_Open_Class_Key_ExA [SETUPAPI.@]
6165  */
6166 CONFIGRET
6167 WINAPI
6168 CM_Open_Class_Key_ExA(
6169     _In_opt_ LPGUID pClassGuid,
6170     _In_opt_ LPCSTR pszClassName,
6171     _In_ REGSAM samDesired,
6172     _In_ REGDISPOSITION Disposition,
6173     _Out_ PHKEY phkClass,
6174     _In_ ULONG ulFlags,
6175     _In_opt_ HMACHINE hMachine)
6176 {
6177     LPWSTR pszClassNameW = NULL;
6178     CONFIGRET ret;
6179 
6180     TRACE("CM_Open_Class_Key_ExA(%p %s %lx %lx %p %lx %p)\n",
6181           debugstr_guid(pClassGuid), debugstr_a(pszClassName),
6182           samDesired, Disposition, phkClass, ulFlags, hMachine);
6183 
6184     if (pszClassName != NULL)
6185     {
6186        if (pSetupCaptureAndConvertAnsiArg(pszClassName, &pszClassNameW))
6187          return CR_INVALID_DATA;
6188     }
6189 
6190     ret = CM_Open_Class_Key_ExW(pClassGuid, pszClassNameW, samDesired,
6191                                 Disposition, phkClass, ulFlags, hMachine);
6192 
6193     if (pszClassNameW != NULL)
6194         MyFree(pszClassNameW);
6195 
6196     return ret;
6197 }
6198 
6199 
6200 /***********************************************************************
6201  * CM_Open_Class_Key_ExW [SETUPAPI.@]
6202  */
6203 CONFIGRET
6204 WINAPI
6205 CM_Open_Class_Key_ExW(
6206     _In_opt_ LPGUID pClassGuid,
6207     _In_opt_ LPCWSTR pszClassName,
6208     _In_ REGSAM samDesired,
6209     _In_ REGDISPOSITION Disposition,
6210     _Out_ PHKEY phkClass,
6211     _In_ ULONG ulFlags,
6212     _In_opt_ HMACHINE hMachine)
6213 {
6214     WCHAR szKeyName[MAX_PATH];
6215     LPWSTR lpGuidString;
6216     DWORD dwDisposition;
6217     DWORD dwError;
6218     HKEY hKey;
6219 
6220     TRACE("CM_Open_Class_Key_ExW(%p %s %lx %lx %p %lx %p)\n",
6221           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
6222           samDesired, Disposition, phkClass, ulFlags, hMachine);
6223 
6224     /* Check Disposition and ulFlags */
6225     if ((Disposition & ~RegDisposition_Bits) ||
6226         (ulFlags & ~CM_OPEN_CLASS_KEY_BITS))
6227         return CR_INVALID_FLAG;
6228 
6229     /* Check phkClass */
6230     if (phkClass == NULL)
6231         return CR_INVALID_POINTER;
6232 
6233     *phkClass = NULL;
6234 
6235     if (ulFlags == CM_OPEN_CLASS_KEY_INTERFACE &&
6236         pszClassName != NULL)
6237         return CR_INVALID_DATA;
6238 
6239     if (hMachine == NULL)
6240     {
6241         hKey = HKEY_LOCAL_MACHINE;
6242     }
6243     else
6244     {
6245         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6246                                 HKEY_LOCAL_MACHINE,
6247                                 &hKey))
6248             return CR_REGISTRY_ERROR;
6249     }
6250 
6251     if (ulFlags & CM_OPEN_CLASS_KEY_INTERFACE)
6252     {
6253         lstrcpyW(szKeyName, DeviceClasses);
6254     }
6255     else
6256     {
6257         lstrcpyW(szKeyName, ControlClass);
6258     }
6259 
6260     if (pClassGuid != NULL)
6261     {
6262         if (UuidToStringW((UUID*)pClassGuid, &lpGuidString) != RPC_S_OK)
6263         {
6264             RegCloseKey(hKey);
6265             return CR_INVALID_DATA;
6266         }
6267 
6268         lstrcatW(szKeyName, Backslash);
6269         lstrcatW(szKeyName, lpGuidString);
6270     }
6271 
6272     if (Disposition == RegDisposition_OpenAlways)
6273     {
6274         dwError = RegCreateKeyExW(hKey, szKeyName, 0, NULL, 0, samDesired,
6275                                   NULL, phkClass, &dwDisposition);
6276     }
6277     else
6278     {
6279         dwError = RegOpenKeyExW(hKey, szKeyName, 0, samDesired, phkClass);
6280     }
6281 
6282     RegCloseKey(hKey);
6283 
6284     if (pClassGuid != NULL)
6285         RpcStringFreeW(&lpGuidString);
6286 
6287     if (dwError != ERROR_SUCCESS)
6288     {
6289         *phkClass = NULL;
6290         return CR_NO_SUCH_REGISTRY_KEY;
6291     }
6292 
6293     if (pszClassName != NULL)
6294     {
6295         RegSetValueExW(*phkClass, Class, 0, REG_SZ, (LPBYTE)pszClassName,
6296                        (lstrlenW(pszClassName) + 1) * sizeof(WCHAR));
6297     }
6298 
6299     return CR_SUCCESS;
6300 }
6301 
6302 
6303 /***********************************************************************
6304  * CM_Open_DevNode_Key [SETUPAPI.@]
6305  */
6306 CONFIGRET
6307 WINAPI
6308 CM_Open_DevNode_Key(
6309     _In_ DEVINST dnDevNode,
6310     _In_ REGSAM samDesired,
6311     _In_ ULONG ulHardwareProfile,
6312     _In_ REGDISPOSITION Disposition,
6313     _Out_ PHKEY phkDevice,
6314     _In_ ULONG ulFlags)
6315 {
6316     TRACE("CM_Open_DevNode_Key(%lx %lx %lu %lx %p %lx)\n",
6317           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags);
6318 
6319     return CM_Open_DevNode_Key_Ex(dnDevNode, samDesired, ulHardwareProfile,
6320                                   Disposition, phkDevice, ulFlags, NULL);
6321 }
6322 
6323 
6324 /***********************************************************************
6325  * CM_Open_DevNode_Key_Ex [SETUPAPI.@]
6326  */
6327 CONFIGRET
6328 WINAPI
6329 CM_Open_DevNode_Key_Ex(
6330     _In_ DEVINST dnDevNode,
6331     _In_ REGSAM samDesired,
6332     _In_ ULONG ulHardwareProfile,
6333     _In_ REGDISPOSITION Disposition,
6334     _Out_ PHKEY phkDevice,
6335     _In_ ULONG ulFlags,
6336     _In_opt_ HMACHINE hMachine)
6337 {
6338     RPC_BINDING_HANDLE BindingHandle = NULL;
6339     HSTRING_TABLE StringTable = NULL;
6340     LPWSTR pszDevInst, pszKeyPath = NULL, pszInstancePath = NULL;
6341     LONG lError;
6342     DWORD dwDisposition;
6343     HKEY hRootKey = NULL;
6344     CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
6345 
6346     TRACE("CM_Open_DevNode_Key_Ex(%lx %lx %lu %lx %p %lx %p)\n",
6347           dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags, hMachine);
6348 
6349     if (phkDevice == NULL)
6350         return CR_INVALID_POINTER;
6351 
6352     *phkDevice = NULL;
6353 
6354     if (dnDevNode == 0)
6355         return CR_INVALID_DEVNODE;
6356 
6357     if (ulFlags & ~CM_REGISTRY_BITS)
6358         return CR_INVALID_FLAG;
6359 
6360     if (Disposition & ~RegDisposition_Bits)
6361         return CR_INVALID_DATA;
6362 
6363     if (hMachine != NULL)
6364     {
6365         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6366         if (BindingHandle == NULL)
6367             return CR_FAILURE;
6368 
6369         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6370         if (StringTable == 0)
6371             return CR_FAILURE;
6372     }
6373     else
6374     {
6375         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6376             return CR_FAILURE;
6377     }
6378 
6379     pszDevInst = pSetupStringTableStringFromId(StringTable, dnDevNode);
6380     if (pszDevInst == NULL)
6381         return CR_INVALID_DEVNODE;
6382 
6383     TRACE("pszDevInst: %S\n", pszDevInst);
6384 
6385     pszKeyPath = MyMalloc(512 * sizeof(WCHAR));
6386     if (pszKeyPath == NULL)
6387     {
6388         ret = CR_OUT_OF_MEMORY;
6389         goto done;
6390     }
6391 
6392     pszInstancePath = MyMalloc(512 * sizeof(WCHAR));
6393     if (pszInstancePath == NULL)
6394     {
6395         ret = CR_OUT_OF_MEMORY;
6396         goto done;
6397     }
6398 
6399     ret = GetDeviceInstanceKeyPath(BindingHandle,
6400                                    pszDevInst,
6401                                    pszKeyPath,
6402                                    pszInstancePath,
6403                                    ulHardwareProfile,
6404                                    ulFlags);
6405     if (ret != CR_SUCCESS)
6406         goto done;
6407 
6408     TRACE("pszKeyPath: %S\n", pszKeyPath);
6409     TRACE("pszInstancePath: %S\n", pszInstancePath);
6410 
6411     wcscat(pszKeyPath, L"\\");
6412     wcscat(pszKeyPath, pszInstancePath);
6413 
6414     TRACE("pszKeyPath: %S\n", pszKeyPath);
6415 
6416     if (hMachine == NULL)
6417     {
6418         hRootKey = HKEY_LOCAL_MACHINE;
6419     }
6420     else
6421     {
6422         if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
6423                                 HKEY_LOCAL_MACHINE,
6424                                 &hRootKey))
6425         {
6426             ret = CR_REGISTRY_ERROR;
6427             goto done;
6428         }
6429     }
6430 
6431     if (Disposition == RegDisposition_OpenAlways)
6432     {
6433         lError = RegCreateKeyExW(hRootKey,
6434                                  pszKeyPath,
6435                                  0,
6436                                  NULL,
6437                                  0,
6438                                  samDesired,
6439                                  NULL,
6440                                  phkDevice,
6441                                  &dwDisposition);
6442     }
6443     else
6444     {
6445         lError = RegOpenKeyExW(hRootKey,
6446                                pszKeyPath,
6447                                0,
6448                                samDesired,
6449                                phkDevice);
6450     }
6451 
6452     if (lError != ERROR_SUCCESS)
6453     {
6454         *phkDevice = NULL;
6455         ret = CR_NO_SUCH_REGISTRY_KEY;
6456     }
6457 
6458 done:
6459     if ((hRootKey != NULL) && (hRootKey != HKEY_LOCAL_MACHINE))
6460         RegCloseKey(hRootKey);
6461 
6462     if (pszInstancePath != NULL)
6463         MyFree(pszInstancePath);
6464 
6465     if (pszKeyPath != NULL)
6466         MyFree(pszKeyPath);
6467 
6468     return ret;
6469 }
6470 
6471 
6472 /***********************************************************************
6473  * CM_Query_And_Remove_SubTreeA [SETUPAPI.@]
6474  */
6475 CONFIGRET
6476 WINAPI
6477 CM_Query_And_Remove_SubTreeA(
6478     _In_ DEVINST dnAncestor,
6479     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6480     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6481     _In_ ULONG ulNameLength,
6482     _In_ ULONG ulFlags)
6483 {
6484     TRACE("CM_Query_And_Remove_SubTreeA(%lx %p %s %lu %lx)\n",
6485           dnAncestor, pVetoType, pszVetoName, ulNameLength, ulFlags);
6486 
6487     return CM_Query_And_Remove_SubTree_ExA(dnAncestor, pVetoType, pszVetoName,
6488                                            ulNameLength, ulFlags, NULL);
6489 }
6490 
6491 
6492 /***********************************************************************
6493  * CM_Query_And_Remove_SubTreeW [SETUPAPI.@]
6494  */
6495 CONFIGRET
6496 WINAPI
6497 CM_Query_And_Remove_SubTreeW(
6498     _In_ DEVINST dnAncestor,
6499     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6500     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6501     _In_ ULONG ulNameLength,
6502     _In_ ULONG ulFlags)
6503 {
6504     TRACE("CM_Query_And_Remove_SubTreeW(%lx %p %s %lu %lx)\n",
6505           dnAncestor, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags);
6506 
6507     return CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, pszVetoName,
6508                                            ulNameLength, ulFlags, NULL);
6509 }
6510 
6511 
6512 /***********************************************************************
6513  * CM_Query_And_Remove_SubTree_ExA [SETUPAPI.@]
6514  */
6515 CONFIGRET
6516 WINAPI
6517 CM_Query_And_Remove_SubTree_ExA(
6518     _In_ DEVINST dnAncestor,
6519     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6520     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
6521     _In_ ULONG ulNameLength,
6522     _In_ ULONG ulFlags,
6523     _In_opt_ HMACHINE hMachine)
6524 {
6525     LPWSTR lpLocalVetoName;
6526     CONFIGRET ret;
6527 
6528     TRACE("CM_Query_And_Remove_SubTree_ExA(%lx %p %s %lu %lx %p)\n",
6529           dnAncestor, pVetoType, debugstr_a(pszVetoName), ulNameLength,
6530           ulFlags, hMachine);
6531 
6532     if (pszVetoName == NULL && ulNameLength == 0)
6533         return CR_INVALID_POINTER;
6534 
6535     lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
6536     if (lpLocalVetoName == NULL)
6537         return CR_OUT_OF_MEMORY;
6538 
6539     ret = CM_Query_And_Remove_SubTree_ExW(dnAncestor, pVetoType, lpLocalVetoName,
6540                                           ulNameLength, ulFlags, hMachine);
6541     if (ret == CR_REMOVE_VETOED)
6542     {
6543         if (WideCharToMultiByte(CP_ACP,
6544                                 0,
6545                                 lpLocalVetoName,
6546                                 ulNameLength,
6547                                 pszVetoName,
6548                                 ulNameLength,
6549                                 NULL,
6550                                 NULL) == 0)
6551             ret = CR_FAILURE;
6552     }
6553 
6554     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
6555 
6556     return ret;
6557 }
6558 
6559 
6560 /***********************************************************************
6561  * CM_Query_And_Remove_SubTree_ExW [SETUPAPI.@]
6562  */
6563 CONFIGRET
6564 WINAPI
6565 CM_Query_And_Remove_SubTree_ExW(
6566     _In_ DEVINST dnAncestor,
6567     _Out_opt_ PPNP_VETO_TYPE pVetoType,
6568     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
6569     _In_ ULONG ulNameLength,
6570     _In_ ULONG ulFlags,
6571     _In_opt_ HMACHINE hMachine)
6572 {
6573     RPC_BINDING_HANDLE BindingHandle = NULL;
6574     HSTRING_TABLE StringTable = NULL;
6575     LPWSTR lpDevInst;
6576     CONFIGRET ret;
6577 
6578     TRACE("CM_Query_And_Remove_SubTree_ExW(%lx %p %s %lu %lx %p)\n",
6579           dnAncestor, pVetoType, debugstr_w(pszVetoName), ulNameLength,
6580           ulFlags, hMachine);
6581 
6582     if (dnAncestor == 0)
6583         return CR_INVALID_DEVNODE;
6584 
6585     if (ulFlags & ~CM_REMOVE_BITS)
6586         return CR_INVALID_FLAG;
6587 
6588     if (pszVetoName == NULL && ulNameLength == 0)
6589         return CR_INVALID_POINTER;
6590 
6591     if (hMachine != NULL)
6592     {
6593         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6594         if (BindingHandle == NULL)
6595             return CR_FAILURE;
6596 
6597         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6598         if (StringTable == 0)
6599             return CR_FAILURE;
6600     }
6601     else
6602     {
6603         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6604             return CR_FAILURE;
6605     }
6606 
6607     lpDevInst = pSetupStringTableStringFromId(StringTable, dnAncestor);
6608     if (lpDevInst == NULL)
6609         return CR_INVALID_DEVNODE;
6610 
6611     RpcTryExcept
6612     {
6613         ret = PNP_QueryRemove(BindingHandle,
6614                               lpDevInst,
6615                               pVetoType,
6616                               pszVetoName,
6617                               ulNameLength,
6618                               ulFlags);
6619     }
6620     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6621     {
6622         ret = RpcStatusToCmStatus(RpcExceptionCode());
6623     }
6624     RpcEndExcept;
6625 
6626     return ret;
6627 }
6628 
6629 
6630 /***********************************************************************
6631  * CM_Query_Arbitrator_Free_Data [SETUPAPI.@]
6632  */
6633 CONFIGRET
6634 WINAPI
6635 CM_Query_Arbitrator_Free_Data(
6636     _Out_writes_bytes_(DataLen) PVOID pData,
6637     _In_ ULONG DataLen,
6638     _In_ DEVINST dnDevInst,
6639     _In_ RESOURCEID ResourceID,
6640     _In_ ULONG ulFlags)
6641 {
6642     TRACE("CM_Query_Arbitrator_Free_Data(%p %lu %lx %lu 0x%08lx)\n",
6643           pData, DataLen, dnDevInst, ResourceID, ulFlags);
6644 
6645     return CM_Query_Arbitrator_Free_Data_Ex(pData, DataLen, dnDevInst,
6646                                             ResourceID, ulFlags, NULL);
6647 }
6648 
6649 
6650 /***********************************************************************
6651  * CM_Query_Arbitrator_Free_Data_Ex [SETUPAPI.@]
6652  */
6653 CONFIGRET
6654 WINAPI
6655 CM_Query_Arbitrator_Free_Data_Ex(
6656     _Out_writes_bytes_(DataLen) PVOID pData,
6657     _In_ ULONG DataLen,
6658     _In_ DEVINST dnDevInst,
6659     _In_ RESOURCEID ResourceID,
6660     _In_ ULONG ulFlags,
6661     _In_opt_ HMACHINE hMachine)
6662 {
6663     RPC_BINDING_HANDLE BindingHandle = NULL;
6664     HSTRING_TABLE StringTable = NULL;
6665     LPWSTR lpDevInst;
6666     CONFIGRET ret;
6667 
6668     TRACE("CM_Query_Arbitrator_Free_Data_Ex(%p %lu %lx %lu 0x%08lx %p)\n",
6669           pData, DataLen, dnDevInst, ResourceID, ulFlags, hMachine);
6670 
6671     if (pData == NULL || DataLen == 0)
6672         return CR_INVALID_POINTER;
6673 
6674     if (dnDevInst == 0)
6675         return CR_INVALID_DEVINST;
6676 
6677     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6678         return CR_INVALID_FLAG;
6679 
6680     if (hMachine != NULL)
6681     {
6682         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6683         if (BindingHandle == NULL)
6684             return CR_FAILURE;
6685 
6686         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6687         if (StringTable == 0)
6688             return CR_FAILURE;
6689     }
6690     else
6691     {
6692         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6693             return CR_FAILURE;
6694     }
6695 
6696     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6697     if (lpDevInst == NULL)
6698         return CR_INVALID_DEVNODE;
6699 
6700     RpcTryExcept
6701     {
6702         ret = PNP_QueryArbitratorFreeData(BindingHandle,
6703                                           pData,
6704                                           DataLen,
6705                                           lpDevInst,
6706                                           ResourceID,
6707                                           ulFlags);
6708     }
6709     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6710     {
6711         ret = RpcStatusToCmStatus(RpcExceptionCode());
6712     }
6713     RpcEndExcept;
6714 
6715     return ret;
6716 }
6717 
6718 
6719 /***********************************************************************
6720  * CM_Query_Arbitrator_Free_Size [SETUPAPI.@]
6721  */
6722 CONFIGRET
6723 WINAPI
6724 CM_Query_Arbitrator_Free_Size(
6725     _Out_ PULONG pulSize,
6726     _In_ DEVINST dnDevInst,
6727     _In_ RESOURCEID ResourceID,
6728     _In_ ULONG ulFlags)
6729 {
6730     TRACE("CM_Query_Arbitrator_Free_Size(%p %lu %lx 0x%08lx)\n",
6731           pulSize, dnDevInst,ResourceID, ulFlags);
6732 
6733     return CM_Query_Arbitrator_Free_Size_Ex(pulSize, dnDevInst, ResourceID,
6734                                             ulFlags, NULL);
6735 }
6736 
6737 
6738 /***********************************************************************
6739  * CM_Query_Arbitrator_Free_Size_Ex [SETUPAPI.@]
6740  */
6741 CONFIGRET
6742 WINAPI
6743 CM_Query_Arbitrator_Free_Size_Ex(
6744     _Out_ PULONG pulSize,
6745     _In_ DEVINST dnDevInst,
6746     _In_ RESOURCEID ResourceID,
6747     _In_ ULONG ulFlags,
6748     _In_opt_ HMACHINE hMachine)
6749 {
6750     RPC_BINDING_HANDLE BindingHandle = NULL;
6751     HSTRING_TABLE StringTable = NULL;
6752     LPWSTR lpDevInst;
6753     CONFIGRET ret;
6754 
6755     TRACE("CM_Query_Arbitrator_Free_Size_Ex(%p %lu %lx 0x%08lx %p)\n",
6756           pulSize, dnDevInst,ResourceID, ulFlags, hMachine);
6757 
6758     if (pulSize == NULL)
6759         return CR_INVALID_POINTER;
6760 
6761     if (dnDevInst == 0)
6762         return CR_INVALID_DEVINST;
6763 
6764     if (ulFlags & ~CM_QUERY_ARBITRATOR_BITS)
6765         return CR_INVALID_FLAG;
6766 
6767     if (hMachine != NULL)
6768     {
6769         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6770         if (BindingHandle == NULL)
6771             return CR_FAILURE;
6772 
6773         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6774         if (StringTable == 0)
6775             return CR_FAILURE;
6776     }
6777     else
6778     {
6779         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6780             return CR_FAILURE;
6781     }
6782 
6783     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6784     if (lpDevInst == NULL)
6785         return CR_INVALID_DEVNODE;
6786 
6787     RpcTryExcept
6788     {
6789         ret = PNP_QueryArbitratorFreeSize(BindingHandle,
6790                                           pulSize,
6791                                           lpDevInst,
6792                                           ResourceID,
6793                                           ulFlags);
6794     }
6795     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6796     {
6797         ret = RpcStatusToCmStatus(RpcExceptionCode());
6798     }
6799     RpcEndExcept;
6800 
6801     return ret;
6802 }
6803 
6804 
6805 /***********************************************************************
6806  * CM_Query_Remove_SubTree [SETUPAPI.@]
6807  *
6808  * This function is obsolete in Windows XP and above.
6809  */
6810 CONFIGRET
6811 WINAPI
6812 CM_Query_Remove_SubTree(
6813     _In_ DEVINST dnAncestor,
6814     _In_ ULONG ulFlags)
6815 {
6816     TRACE("CM_Query_Remove_SubTree(%lx %lx)\n",
6817           dnAncestor, ulFlags);
6818 
6819     return CR_CALL_NOT_IMPLEMENTED;
6820 }
6821 
6822 
6823 /***********************************************************************
6824  * CM_Query_Remove_SubTree_Ex [SETUPAPI.@]
6825  *
6826  * This function is obsolete in Windows XP and above.
6827  */
6828 CONFIGRET
6829 WINAPI
6830 CM_Query_Remove_SubTree_Ex(
6831     _In_ DEVINST dnAncestor,
6832     _In_ ULONG ulFlags,
6833     _In_opt_ HMACHINE hMachine)
6834 {
6835     TRACE("CM_Query_Remove_SubTree_Ex(%lx %lx %p)\n",
6836           dnAncestor, ulFlags, hMachine);
6837 
6838     return CR_CALL_NOT_IMPLEMENTED;
6839 }
6840 
6841 
6842 /***********************************************************************
6843  * CM_Query_Resource_Conflict_List [SETUPAPI.@]
6844  */
6845 CONFIGRET
6846 WINAPI
6847 CM_Query_Resource_Conflict_List(
6848     _Out_ PCONFLICT_LIST pclConflictList,
6849     _In_ DEVINST dnDevInst,
6850     _In_ RESOURCEID ResourceID,
6851     _In_ PCVOID ResourceData,
6852     _In_ ULONG ResourceLen,
6853     _In_ ULONG ulFlags,
6854     _In_opt_ HMACHINE hMachine)
6855 {
6856     RPC_BINDING_HANDLE BindingHandle = NULL;
6857     HSTRING_TABLE StringTable = NULL;
6858     PPNP_CONFLICT_LIST pConflictBuffer = NULL;
6859     PCONFLICT_DATA pConflictData = NULL;
6860     ULONG ulBufferLength;
6861     LPWSTR lpDevInst;
6862     CONFIGRET ret;
6863 
6864     FIXME("CM_Query_Resource_Conflict_List(%p %lx %lu %p %lu %lx %p)\n",
6865           pclConflictList, dnDevInst, ResourceID, ResourceData,
6866           ResourceLen, ulFlags, hMachine);
6867 
6868     if (dnDevInst == 0)
6869         return CR_INVALID_DEVNODE;
6870 
6871     if (ulFlags & ~CM_RESDES_WIDTH_BITS)
6872         return CR_INVALID_FLAG;
6873 
6874     if (pclConflictList == NULL ||
6875         ResourceData == NULL ||
6876         ResourceLen == 0)
6877         return CR_INVALID_POINTER;
6878 
6879     if (ResourceID == 0)
6880         return CR_INVALID_RESOURCEID;
6881 
6882     *pclConflictList = 0;
6883 
6884     if (hMachine != NULL)
6885     {
6886         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
6887         if (BindingHandle == NULL)
6888             return CR_FAILURE;
6889 
6890         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
6891         if (StringTable == 0)
6892             return CR_FAILURE;
6893     }
6894     else
6895     {
6896         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
6897             return CR_FAILURE;
6898     }
6899 
6900     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
6901     if (lpDevInst == NULL)
6902         return CR_INVALID_DEVNODE;
6903 
6904     pConflictData = MyMalloc(sizeof(CONFLICT_DATA));
6905     if (pConflictData == NULL)
6906     {
6907         ret = CR_OUT_OF_MEMORY;
6908         goto done;
6909     }
6910 
6911     ulBufferLength = sizeof(PNP_CONFLICT_LIST) +
6912                      sizeof(PNP_CONFLICT_STRINGS) +
6913                      (sizeof(wchar_t) * 200);
6914     pConflictBuffer = MyMalloc(ulBufferLength);
6915     if (pConflictBuffer == NULL)
6916     {
6917         ret = CR_OUT_OF_MEMORY;
6918         goto done;
6919     }
6920 
6921     RpcTryExcept
6922     {
6923         ret = PNP_QueryResConfList(BindingHandle,
6924                                    lpDevInst,
6925                                    ResourceID,
6926                                    (PBYTE)ResourceData,
6927                                    ResourceLen,
6928                                    (PBYTE)pConflictBuffer,
6929                                    ulBufferLength,
6930                                    ulFlags);
6931     }
6932     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
6933     {
6934         ret = RpcStatusToCmStatus(RpcExceptionCode());
6935     }
6936     RpcEndExcept;
6937 
6938     if (ret != CR_SUCCESS)
6939         goto done;
6940 
6941     pConflictData->ulMagic = CONFLICT_MAGIC;
6942     pConflictData->pConflictList = pConflictBuffer;
6943 
6944     *pclConflictList = (CONFLICT_LIST)pConflictData;
6945 
6946 done:
6947     if (ret != CR_SUCCESS)
6948     {
6949         if (pConflictBuffer != NULL)
6950             MyFree(pConflictBuffer);
6951 
6952         if (pConflictData != NULL)
6953             MyFree(pConflictData);
6954     }
6955 
6956     return ret;
6957 }
6958 
6959 
6960 /***********************************************************************
6961  * CM_Reenumerate_DevNode [SETUPAPI.@]
6962  */
6963 CONFIGRET
6964 WINAPI
6965 CM_Reenumerate_DevNode(
6966     _In_ DEVINST dnDevInst,
6967     _In_ ULONG ulFlags)
6968 {
6969     TRACE("CM_Reenumerate_DevNode(%lx %lx)\n",
6970           dnDevInst, ulFlags);
6971 
6972     return CM_Reenumerate_DevNode_Ex(dnDevInst, ulFlags, NULL);
6973 }
6974 
6975 
6976 /***********************************************************************
6977  * CM_Reenumerate_DevNode_Ex [SETUPAPI.@]
6978  */
6979 CONFIGRET WINAPI
6980 CM_Reenumerate_DevNode_Ex(
6981     _In_ DEVINST dnDevInst,
6982     _In_ ULONG ulFlags,
6983     _In_opt_ HMACHINE hMachine)
6984 {
6985     RPC_BINDING_HANDLE BindingHandle = NULL;
6986     HSTRING_TABLE StringTable = NULL;
6987     LPWSTR lpDevInst;
6988     CONFIGRET ret;
6989 
6990     FIXME("CM_Reenumerate_DevNode_Ex(%lx %lx %p)\n",
6991           dnDevInst, ulFlags, hMachine);
6992 
6993     if (dnDevInst == 0)
6994         return CR_INVALID_DEVNODE;
6995 
6996     if (ulFlags & ~CM_REENUMERATE_BITS)
6997         return CR_INVALID_FLAG;
6998 
6999     if (hMachine != NULL)
7000     {
7001         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7002         if (BindingHandle == NULL)
7003             return CR_FAILURE;
7004 
7005         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7006         if (StringTable == 0)
7007             return CR_FAILURE;
7008     }
7009     else
7010     {
7011         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7012             return CR_FAILURE;
7013     }
7014 
7015     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7016     if (lpDevInst == NULL)
7017         return CR_INVALID_DEVNODE;
7018 
7019     RpcTryExcept
7020     {
7021         ret = PNP_DeviceInstanceAction(BindingHandle,
7022                                        PNP_DEVINST_REENUMERATE,
7023                                        ulFlags,
7024                                        lpDevInst,
7025                                        NULL);
7026     }
7027     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7028     {
7029         ret = RpcStatusToCmStatus(RpcExceptionCode());
7030     }
7031     RpcEndExcept;
7032 
7033     return ret;
7034 }
7035 
7036 
7037 /***********************************************************************
7038  * CM_Register_Device_Driver [SETUPAPI.@]
7039  */
7040 CONFIGRET
7041 WINAPI
7042 CM_Register_Device_Driver(
7043     _In_ DEVINST dnDevInst,
7044     _In_ ULONG ulFlags)
7045 {
7046     TRACE("CM_Register_Device_Driver(%lx 0x%08lx)\n",
7047           dnDevInst, ulFlags);
7048 
7049     return CM_Register_Device_Driver_Ex(dnDevInst, ulFlags, NULL);
7050 }
7051 
7052 
7053 /***********************************************************************
7054  * CM_Register_Device_Driver_Ex [SETUPAPI.@]
7055  */
7056 CONFIGRET
7057 WINAPI
7058 CM_Register_Device_Driver_Ex(
7059     _In_ DEVINST dnDevInst,
7060     _In_ ULONG ulFlags,
7061     _In_opt_ HMACHINE hMachine)
7062 {
7063     RPC_BINDING_HANDLE BindingHandle = NULL;
7064     HSTRING_TABLE StringTable = NULL;
7065     LPWSTR lpDevInst;
7066     CONFIGRET ret;
7067 
7068     TRACE("CM_Register_Device_Driver_Ex(%lx 0x%08lx %p)\n",
7069           dnDevInst, ulFlags, hMachine);
7070 
7071     if (dnDevInst == 0)
7072         return CR_INVALID_DEVNODE;
7073 
7074     if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
7075         return CR_INVALID_FLAG;
7076 
7077     if (hMachine != NULL)
7078     {
7079         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7080         if (BindingHandle == NULL)
7081             return CR_FAILURE;
7082 
7083         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7084         if (StringTable == 0)
7085             return CR_FAILURE;
7086     }
7087     else
7088     {
7089         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7090             return CR_FAILURE;
7091     }
7092 
7093     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7094     if (lpDevInst == NULL)
7095         return CR_INVALID_DEVNODE;
7096 
7097     RpcTryExcept
7098     {
7099         ret = PNP_RegisterDriver(BindingHandle,
7100                                  lpDevInst,
7101                                  ulFlags);
7102     }
7103     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7104     {
7105         ret = RpcStatusToCmStatus(RpcExceptionCode());
7106     }
7107     RpcEndExcept;
7108 
7109     return ret;
7110 }
7111 
7112 
7113 /***********************************************************************
7114  * CM_Register_Device_InterfaceA [SETUPAPI.@]
7115  */
7116 CONFIGRET
7117 WINAPI
7118 CM_Register_Device_InterfaceA(
7119     _In_ DEVINST dnDevInst,
7120     _In_ LPGUID InterfaceClassGuid,
7121     _In_opt_ LPCSTR pszReference,
7122     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
7123     _Inout_ PULONG pulLength,
7124     _In_ ULONG ulFlags)
7125 {
7126     TRACE("CM_Register_Device_InterfaceA(%lx %s %s %p %p %lx)\n",
7127           dnDevInst, debugstr_guid(InterfaceClassGuid),
7128           pszReference, pszDeviceInterface, pulLength, ulFlags);
7129 
7130     return CM_Register_Device_Interface_ExA(dnDevInst, InterfaceClassGuid,
7131                                             pszReference, pszDeviceInterface,
7132                                             pulLength, ulFlags, NULL);
7133 }
7134 
7135 
7136 /***********************************************************************
7137  * CM_Register_Device_InterfaceW [SETUPAPI.@]
7138  */
7139 CONFIGRET
7140 WINAPI
7141 CM_Register_Device_InterfaceW(
7142     _In_ DEVINST dnDevInst,
7143     _In_ LPGUID InterfaceClassGuid,
7144     _In_opt_ LPCWSTR pszReference,
7145     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
7146     _Inout_ PULONG pulLength,
7147     _In_ ULONG ulFlags)
7148 {
7149     TRACE("CM_Register_Device_InterfaceW(%lx %s %s %p %p %lx)\n",
7150           dnDevInst, debugstr_guid(InterfaceClassGuid),
7151           debugstr_w(pszReference), pszDeviceInterface, pulLength, ulFlags);
7152 
7153     return CM_Register_Device_Interface_ExW(dnDevInst, InterfaceClassGuid,
7154                                             pszReference, pszDeviceInterface,
7155                                             pulLength, ulFlags, NULL);
7156 }
7157 
7158 
7159 /***********************************************************************
7160  * CM_Register_Device_Interface_ExA [SETUPAPI.@]
7161  */
7162 CONFIGRET
7163 WINAPI
7164 CM_Register_Device_Interface_ExA(
7165     _In_ DEVINST dnDevInst,
7166     _In_ LPGUID InterfaceClassGuid,
7167     _In_opt_ LPCSTR pszReference,
7168     _Out_writes_(*pulLength) LPSTR pszDeviceInterface,
7169     _Inout_ PULONG pulLength,
7170     _In_ ULONG ulFlags,
7171     _In_opt_ HMACHINE hMachine)
7172 {
7173     LPWSTR pszReferenceW = NULL;
7174     LPWSTR pszDeviceInterfaceW = NULL;
7175     ULONG ulLength;
7176     CONFIGRET ret;
7177 
7178     TRACE("CM_Register_Device_Interface_ExA(%lx %s %s %p %p %lx %p)\n",
7179           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_a(pszReference),
7180           pszDeviceInterface, pulLength, ulFlags, hMachine);
7181 
7182     if (pulLength == NULL || pszDeviceInterface == NULL)
7183         return CR_INVALID_POINTER;
7184 
7185     if (pszReference != NULL)
7186     {
7187         if (pSetupCaptureAndConvertAnsiArg(pszReference, &pszReferenceW))
7188             return CR_INVALID_DATA;
7189     }
7190 
7191     ulLength = *pulLength;
7192 
7193     pszDeviceInterfaceW = HeapAlloc(GetProcessHeap(), 0, ulLength * sizeof(WCHAR));
7194     if (pszDeviceInterfaceW == NULL)
7195     {
7196         ret = CR_OUT_OF_MEMORY;
7197         goto Done;
7198     }
7199 
7200     ret = CM_Register_Device_Interface_ExW(dnDevInst,
7201                                            InterfaceClassGuid,
7202                                            pszReferenceW,
7203                                            pszDeviceInterfaceW,
7204                                            &ulLength,
7205                                            ulFlags,
7206                                            hMachine);
7207     if (ret == CR_SUCCESS)
7208     {
7209         if (WideCharToMultiByte(CP_ACP,
7210                                 0,
7211                                 pszDeviceInterfaceW,
7212                                 ulLength,
7213                                 pszDeviceInterface,
7214                                 *pulLength,
7215                                 NULL,
7216                                 NULL) == 0)
7217             ret = CR_FAILURE;
7218     }
7219 
7220     *pulLength = ulLength;
7221 
7222 Done:
7223     if (pszDeviceInterfaceW != NULL)
7224         HeapFree(GetProcessHeap(), 0, pszDeviceInterfaceW);
7225 
7226     if (pszReferenceW != NULL)
7227         MyFree(pszReferenceW);
7228 
7229     return ret;
7230 }
7231 
7232 
7233 /***********************************************************************
7234  * CM_Register_Device_Interface_ExW [SETUPAPI.@]
7235  */
7236 CONFIGRET
7237 WINAPI
7238 CM_Register_Device_Interface_ExW(
7239     _In_ DEVINST dnDevInst,
7240     _In_ LPGUID InterfaceClassGuid,
7241     _In_opt_ LPCWSTR pszReference,
7242     _Out_writes_(*pulLength) LPWSTR pszDeviceInterface,
7243     _Inout_ PULONG pulLength,
7244     _In_ ULONG ulFlags,
7245     _In_opt_ HMACHINE hMachine)
7246 {
7247     RPC_BINDING_HANDLE BindingHandle = NULL;
7248     HSTRING_TABLE StringTable = NULL;
7249     LPWSTR lpDevInst;
7250     ULONG ulTransferLength;
7251     CONFIGRET ret;
7252 
7253     TRACE("CM_Register_Device_Interface_ExW(%lx %s %s %p %p %lx %p)\n",
7254           dnDevInst, debugstr_guid(InterfaceClassGuid), debugstr_w(pszReference),
7255           pszDeviceInterface, pulLength, ulFlags, hMachine);
7256 
7257     if (dnDevInst == 0)
7258         return CR_INVALID_DEVNODE;
7259 
7260     if (InterfaceClassGuid == NULL ||
7261         pszDeviceInterface == NULL ||
7262         pulLength == NULL)
7263         return CR_INVALID_POINTER;
7264 
7265     if (ulFlags != 0)
7266         return CR_INVALID_FLAG;
7267 
7268     if (hMachine != NULL)
7269     {
7270         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7271         if (BindingHandle == NULL)
7272             return CR_FAILURE;
7273 
7274         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7275         if (StringTable == 0)
7276             return CR_FAILURE;
7277     }
7278     else
7279     {
7280         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7281             return CR_FAILURE;
7282     }
7283 
7284     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7285     if (lpDevInst == NULL)
7286         return CR_INVALID_DEVNODE;
7287 
7288     ulTransferLength = *pulLength;
7289 
7290     RpcTryExcept
7291     {
7292         ret = PNP_RegisterDeviceClassAssociation(BindingHandle,
7293                                                  lpDevInst,
7294                                                  InterfaceClassGuid,
7295                                                  (LPWSTR)pszReference,
7296                                                  pszDeviceInterface,
7297                                                  pulLength,
7298                                                  &ulTransferLength,
7299                                                  0);
7300     }
7301     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7302     {
7303         ret = RpcStatusToCmStatus(RpcExceptionCode());
7304     }
7305     RpcEndExcept;
7306 
7307     return ret;
7308 }
7309 
7310 
7311 /***********************************************************************
7312  * CM_Remove_SubTree [SETUPAPI.@]
7313  *
7314  * This function is obsolete in Windows XP and above.
7315  */
7316 CONFIGRET
7317 WINAPI
7318 CM_Remove_SubTree(
7319     _In_ DEVINST dnAncestor,
7320     _In_ ULONG ulFlags)
7321 {
7322     TRACE("CM_Remove_SubTree(%lx %lx)\n",
7323           dnAncestor, ulFlags);
7324 
7325     return CR_CALL_NOT_IMPLEMENTED;
7326 }
7327 
7328 
7329 /***********************************************************************
7330  * CM_Remove_SubTree_Ex [SETUPAPI.@]
7331  *
7332  * This function is obsolete in Windows XP and above.
7333  */
7334 CONFIGRET
7335 WINAPI
7336 CM_Remove_SubTree_Ex(
7337     _In_ DEVINST dnAncestor,
7338     _In_ ULONG ulFlags,
7339     _In_opt_ HMACHINE hMachine)
7340 {
7341     TRACE("CM_Remove_SubTree_Ex(%lx %lx %p)\n",
7342           dnAncestor, ulFlags, hMachine);
7343 
7344     return CR_CALL_NOT_IMPLEMENTED;
7345 }
7346 
7347 
7348 /***********************************************************************
7349  * CM_Request_Device_EjectA [SETUPAPI.@]
7350  */
7351 CONFIGRET
7352 WINAPI
7353 CM_Request_Device_EjectA(
7354     _In_ DEVINST dnDevInst,
7355     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7356     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7357     _In_ ULONG ulNameLength,
7358     _In_ ULONG ulFlags)
7359 {
7360     TRACE("CM_Request_Device_EjectA(%lx %p %s %lu %lx)\n",
7361           dnDevInst, pVetoType, debugstr_a(pszVetoName), ulNameLength, ulFlags);
7362 
7363     return CM_Request_Device_Eject_ExA(dnDevInst, pVetoType, pszVetoName,
7364                                        ulNameLength, ulFlags, NULL);
7365 }
7366 
7367 
7368 /***********************************************************************
7369  * CM_Request_Device_EjectW [SETUPAPI.@]
7370  */
7371 CONFIGRET
7372 WINAPI
7373 CM_Request_Device_EjectW(
7374     _In_ DEVINST dnDevInst,
7375     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7376     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7377     _In_ ULONG ulNameLength,
7378     _In_ ULONG ulFlags)
7379 {
7380     TRACE("CM_Request_Device_EjectW(%lx %p %s %lu %lx)\n",
7381           dnDevInst, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags);
7382 
7383     return CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, pszVetoName,
7384                                        ulNameLength, ulFlags, NULL);
7385 }
7386 
7387 
7388 /***********************************************************************
7389  * CM_Request_Device_Eject_ExA [SETUPAPI.@]
7390  */
7391 CONFIGRET
7392 WINAPI
7393 CM_Request_Device_Eject_ExA(
7394     _In_ DEVINST dnDevInst,
7395     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7396     _Out_writes_opt_(ulNameLength) LPSTR pszVetoName,
7397     _In_ ULONG ulNameLength,
7398     _In_ ULONG ulFlags,
7399     _In_opt_ HMACHINE hMachine)
7400 {
7401     LPWSTR lpLocalVetoName;
7402     CONFIGRET ret;
7403 
7404     TRACE("CM_Request_Device_Eject_ExA(%lx %p %s %lu %lx %p)\n",
7405           dnDevInst, pVetoType, debugstr_a(pszVetoName), ulNameLength, ulFlags, hMachine);
7406 
7407     if (pszVetoName == NULL && ulNameLength == 0)
7408         return CR_INVALID_POINTER;
7409 
7410     lpLocalVetoName = HeapAlloc(GetProcessHeap(), 0, ulNameLength * sizeof(WCHAR));
7411     if (lpLocalVetoName == NULL)
7412         return CR_OUT_OF_MEMORY;
7413 
7414     ret = CM_Request_Device_Eject_ExW(dnDevInst, pVetoType, lpLocalVetoName,
7415                                       ulNameLength, ulFlags, hMachine);
7416     if (ret == CR_REMOVE_VETOED)
7417     {
7418         if (WideCharToMultiByte(CP_ACP,
7419                                 0,
7420                                 lpLocalVetoName,
7421                                 ulNameLength,
7422                                 pszVetoName,
7423                                 ulNameLength,
7424                                 NULL,
7425                                 NULL) == 0)
7426             ret = CR_FAILURE;
7427     }
7428 
7429     HeapFree(GetProcessHeap(), 0, lpLocalVetoName);
7430 
7431     return ret;
7432 }
7433 
7434 
7435 /***********************************************************************
7436  * CM_Request_Device_Eject_ExW [SETUPAPI.@]
7437  */
7438 CONFIGRET
7439 WINAPI
7440 CM_Request_Device_Eject_ExW(
7441     _In_ DEVINST dnDevInst,
7442     _Out_opt_ PPNP_VETO_TYPE pVetoType,
7443     _Out_writes_opt_(ulNameLength) LPWSTR pszVetoName,
7444     _In_ ULONG ulNameLength,
7445     _In_ ULONG ulFlags,
7446     _In_opt_ HMACHINE hMachine)
7447 {
7448     RPC_BINDING_HANDLE BindingHandle = NULL;
7449     HSTRING_TABLE StringTable = NULL;
7450     LPWSTR lpDevInst;
7451     CONFIGRET ret;
7452 
7453     TRACE("CM_Request_Device_Eject_ExW(%lx %p %s %lu %lx %p)\n",
7454           dnDevInst, pVetoType, debugstr_w(pszVetoName), ulNameLength, ulFlags, hMachine);
7455 
7456     if (dnDevInst == 0)
7457         return CR_INVALID_DEVNODE;
7458 
7459     if (ulFlags != 0)
7460         return CR_INVALID_FLAG;
7461 
7462     if (pszVetoName == NULL && ulNameLength == 0)
7463         return CR_INVALID_POINTER;
7464 
7465     if (hMachine != NULL)
7466     {
7467         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7468         if (BindingHandle == NULL)
7469             return CR_FAILURE;
7470 
7471         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7472         if (StringTable == 0)
7473             return CR_FAILURE;
7474     }
7475     else
7476     {
7477         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7478             return CR_FAILURE;
7479     }
7480 
7481     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7482     if (lpDevInst == NULL)
7483         return CR_INVALID_DEVNODE;
7484 
7485     RpcTryExcept
7486     {
7487         ret = PNP_RequestDeviceEject(BindingHandle,
7488                                      lpDevInst,
7489                                      pVetoType,
7490                                      pszVetoName,
7491                                      ulNameLength,
7492                                      ulFlags);
7493     }
7494     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7495     {
7496         ret = RpcStatusToCmStatus(RpcExceptionCode());
7497     }
7498     RpcEndExcept;
7499 
7500     return ret;
7501 }
7502 
7503 
7504 /***********************************************************************
7505  * CM_Request_Eject_PC [SETUPAPI.@]
7506  */
7507 CONFIGRET
7508 WINAPI
7509 CM_Request_Eject_PC(VOID)
7510 {
7511     TRACE("CM_Request_Eject_PC()\n");
7512 
7513     return CM_Request_Eject_PC_Ex(NULL);
7514 }
7515 
7516 
7517 /***********************************************************************
7518  * CM_Request_Eject_PC_Ex [SETUPAPI.@]
7519  */
7520 CONFIGRET
7521 WINAPI
7522 CM_Request_Eject_PC_Ex(
7523     _In_opt_ HMACHINE hMachine)
7524 {
7525     RPC_BINDING_HANDLE BindingHandle = NULL;
7526     CONFIGRET ret;
7527 
7528     TRACE("CM_Request_Eject_PC_Ex(%p)\n", hMachine);
7529 
7530     if (hMachine != NULL)
7531     {
7532         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7533         if (BindingHandle == NULL)
7534             return CR_FAILURE;
7535     }
7536     else
7537     {
7538         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7539             return CR_FAILURE;
7540     }
7541 
7542     RpcTryExcept
7543     {
7544         ret = PNP_RequestEjectPC(BindingHandle);
7545     }
7546     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7547     {
7548         ret = RpcStatusToCmStatus(RpcExceptionCode());
7549     }
7550     RpcEndExcept;
7551 
7552     return ret;
7553 }
7554 
7555 
7556 /***********************************************************************
7557  * CM_Run_Detection [SETUPAPI.@]
7558  */
7559 CONFIGRET
7560 WINAPI
7561 CM_Run_Detection(
7562     _In_ ULONG ulFlags)
7563 {
7564     TRACE("CM_Run_Detection(%lx)\n", ulFlags);
7565 
7566     return CM_Run_Detection_Ex(ulFlags, NULL);
7567 }
7568 
7569 
7570 /***********************************************************************
7571  * CM_Run_Detection_Ex [SETUPAPI.@]
7572  */
7573 CONFIGRET
7574 WINAPI
7575 CM_Run_Detection_Ex(
7576     _In_ ULONG ulFlags,
7577     _In_opt_ HMACHINE hMachine)
7578 {
7579     RPC_BINDING_HANDLE BindingHandle = NULL;
7580     CONFIGRET ret;
7581 
7582     TRACE("CM_Run_Detection_Ex(%lx %p)\n",
7583           ulFlags, hMachine);
7584 
7585     if (!pSetupIsUserAdmin())
7586         return CR_ACCESS_DENIED;
7587 
7588     if (ulFlags & ~CM_DETECT_BITS)
7589         return CR_INVALID_FLAG;
7590 
7591     if (hMachine != NULL)
7592     {
7593         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7594         if (BindingHandle == NULL)
7595             return CR_FAILURE;
7596     }
7597     else
7598     {
7599         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7600             return CR_FAILURE;
7601     }
7602 
7603     RpcTryExcept
7604     {
7605         ret = PNP_RunDetection(BindingHandle,
7606                                ulFlags);
7607     }
7608     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7609     {
7610         ret = RpcStatusToCmStatus(RpcExceptionCode());
7611     }
7612     RpcEndExcept;
7613 
7614     return ret;
7615 }
7616 
7617 
7618 /***********************************************************************
7619  * CM_Set_Class_Registry_PropertyA [SETUPAPI.@]
7620  */
7621 CONFIGRET
7622 WINAPI
7623 CM_Set_Class_Registry_PropertyA(
7624     _In_ LPGUID ClassGuid,
7625     _In_ ULONG ulProperty,
7626     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7627     _In_ ULONG ulLength,
7628     _In_ ULONG ulFlags,
7629     _In_opt_ HMACHINE hMachine)
7630 {
7631     FIXME("CM_Set_Class_Registry_PropertyA(%p %lx %p %lu %lx %p)\n",
7632           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7633 
7634     return CR_CALL_NOT_IMPLEMENTED;
7635 }
7636 
7637 
7638 /***********************************************************************
7639  * CM_Set_Class_Registry_PropertyW [SETUPAPI.@]
7640  */
7641 CONFIGRET
7642 WINAPI
7643 CM_Set_Class_Registry_PropertyW(
7644     _In_ LPGUID ClassGuid,
7645     _In_ ULONG ulProperty,
7646     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7647     _In_ ULONG ulLength,
7648     _In_ ULONG ulFlags,
7649     _In_opt_ HMACHINE hMachine)
7650 {
7651     FIXME("CM_Set_Class_Registry_PropertyW(%p %lx %p %lu %lx %p)\n",
7652           ClassGuid, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7653 
7654     return CR_CALL_NOT_IMPLEMENTED;
7655 }
7656 
7657 
7658 /***********************************************************************
7659  * CM_Set_DevNode_Problem [SETUPAPI.@]
7660  */
7661 CONFIGRET
7662 WINAPI
7663 CM_Set_DevNode_Problem(
7664     _In_ DEVINST dnDevInst,
7665     _In_ ULONG ulProblem,
7666     _In_ ULONG ulFlags)
7667 {
7668     TRACE("CM_Set_DevNode_Problem(%lx %lx %lx)\n",
7669           dnDevInst, ulProblem, ulFlags);
7670 
7671     return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
7672 }
7673 
7674 
7675 /***********************************************************************
7676  * CM_Set_DevNode_Problem_Ex [SETUPAPI.@]
7677  */
7678 CONFIGRET
7679 WINAPI
7680 CM_Set_DevNode_Problem_Ex(
7681     _In_ DEVINST dnDevInst,
7682     _In_ ULONG ulProblem,
7683     _In_ ULONG ulFlags,
7684     _In_opt_ HMACHINE hMachine)
7685 {
7686     RPC_BINDING_HANDLE BindingHandle = NULL;
7687     HSTRING_TABLE StringTable = NULL;
7688     LPWSTR lpDevInst;
7689     CONFIGRET ret;
7690 
7691     TRACE("CM_Set_DevNode_Problem_Ex(%lx %lx %lx %p)\n",
7692           dnDevInst, ulProblem, ulFlags, hMachine);
7693 
7694     if (dnDevInst == 0)
7695         return CR_INVALID_DEVNODE;
7696 
7697     if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
7698         return CR_INVALID_FLAG;
7699 
7700     if (hMachine != NULL)
7701     {
7702         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7703         if (BindingHandle == NULL)
7704             return CR_FAILURE;
7705 
7706         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7707         if (StringTable == 0)
7708             return CR_FAILURE;
7709     }
7710     else
7711     {
7712         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7713             return CR_FAILURE;
7714     }
7715 
7716     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7717     if (lpDevInst == NULL)
7718         return CR_INVALID_DEVNODE;
7719 
7720     RpcTryExcept
7721     {
7722         ret = PNP_SetDeviceProblem(BindingHandle,
7723                                    lpDevInst,
7724                                    ulProblem,
7725                                    ulFlags);
7726     }
7727     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7728     {
7729         ret = RpcStatusToCmStatus(RpcExceptionCode());
7730     }
7731     RpcEndExcept;
7732 
7733     return ret;
7734 }
7735 
7736 
7737 /***********************************************************************
7738  * CM_Set_DevNode_Registry_PropertyA [SETUPAPI.@]
7739  */
7740 CONFIGRET
7741 WINAPI
7742 CM_Set_DevNode_Registry_PropertyA(
7743   _In_ DEVINST dnDevInst,
7744   _In_ ULONG ulProperty,
7745   _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7746   _In_ ULONG ulLength,
7747   _In_ ULONG ulFlags)
7748 {
7749     TRACE("CM_Set_DevNode_Registry_PropertyA(%lx %lu %p %lx %lx)\n",
7750           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7751 
7752     return CM_Set_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
7753                                                 Buffer, ulLength,
7754                                                 ulFlags, NULL);
7755 }
7756 
7757 
7758 /***********************************************************************
7759  * CM_Set_DevNode_Registry_PropertyW [SETUPAPI.@]
7760  */
7761 CONFIGRET
7762 WINAPI
7763 CM_Set_DevNode_Registry_PropertyW(
7764     _In_ DEVINST dnDevInst,
7765     _In_ ULONG ulProperty,
7766     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7767     _In_ ULONG ulLength,
7768     _In_ ULONG ulFlags)
7769 {
7770     TRACE("CM_Set_DevNode_Registry_PropertyW(%lx %lu %p %lx %lx)\n",
7771           dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
7772 
7773     return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
7774                                                 Buffer, ulLength,
7775                                                 ulFlags, NULL);
7776 }
7777 
7778 
7779 /***********************************************************************
7780  * CM_Set_DevNode_Registry_Property_ExA [SETUPAPI.@]
7781  */
7782 CONFIGRET
7783 WINAPI
7784 CM_Set_DevNode_Registry_Property_ExA(
7785     _In_ DEVINST dnDevInst,
7786     _In_ ULONG ulProperty,
7787     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7788     _In_ ULONG ulLength,
7789     _In_ ULONG ulFlags,
7790     _In_opt_ HMACHINE hMachine)
7791 {
7792     CONFIGRET ret = CR_SUCCESS;
7793     LPWSTR lpBuffer;
7794     ULONG ulType;
7795 
7796     FIXME("CM_Set_DevNode_Registry_Property_ExA(%lx %lu %p %lx %lx %p)\n",
7797           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7798 
7799     if (Buffer == NULL && ulLength != 0)
7800         return CR_INVALID_POINTER;
7801 
7802     if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7803         return CR_INVALID_PROPERTY;
7804 
7805     if (Buffer == NULL)
7806     {
7807         ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7808                                                    ulProperty,
7809                                                    NULL,
7810                                                    0,
7811                                                    ulFlags,
7812                                                    hMachine);
7813     }
7814     else
7815     {
7816         /* Get property type */
7817         ulType = GetRegistryPropertyType(ulProperty);
7818 
7819         /* Allocate buffer if needed */
7820         if (ulType == REG_SZ ||
7821             ulType == REG_MULTI_SZ)
7822         {
7823             lpBuffer = MyMalloc(ulLength * sizeof(WCHAR));
7824             if (lpBuffer == NULL)
7825             {
7826                 ret = CR_OUT_OF_MEMORY;
7827             }
7828             else
7829             {
7830                 if (!MultiByteToWideChar(CP_ACP, 0, Buffer,
7831                                          ulLength, lpBuffer, ulLength))
7832                 {
7833                     MyFree(lpBuffer);
7834                     ret = CR_FAILURE;
7835                 }
7836                 else
7837                 {
7838                     ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7839                                                                ulProperty,
7840                                                                lpBuffer,
7841                                                                ulLength * sizeof(WCHAR),
7842                                                                ulFlags,
7843                                                                hMachine);
7844                     MyFree(lpBuffer);
7845                 }
7846             }
7847         }
7848         else
7849         {
7850             ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
7851                                                        ulProperty,
7852                                                        Buffer,
7853                                                        ulLength,
7854                                                        ulFlags,
7855                                                        hMachine);
7856         }
7857 
7858         ret = CR_CALL_NOT_IMPLEMENTED;
7859     }
7860 
7861     return ret;
7862 }
7863 
7864 
7865 /***********************************************************************
7866  * CM_Set_DevNode_Registry_Property_ExW [SETUPAPI.@]
7867  */
7868 CONFIGRET
7869 WINAPI
7870 CM_Set_DevNode_Registry_Property_ExW(
7871     _In_ DEVINST dnDevInst,
7872     _In_ ULONG ulProperty,
7873     _In_reads_bytes_opt_(ulLength) PCVOID Buffer,
7874     _In_ ULONG ulLength,
7875     _In_ ULONG ulFlags,
7876     _In_opt_ HMACHINE hMachine)
7877 {
7878     RPC_BINDING_HANDLE BindingHandle = NULL;
7879     HSTRING_TABLE StringTable = NULL;
7880     LPWSTR lpDevInst;
7881     ULONG ulType;
7882     CONFIGRET ret;
7883 
7884     TRACE("CM_Set_DevNode_Registry_Property_ExW(%lx %lu %p %lx %lx %p)\n",
7885           dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
7886 
7887     if (dnDevInst == 0)
7888         return CR_INVALID_DEVNODE;
7889 
7890     if (ulProperty <  CM_DRP_MIN || ulProperty > CM_DRP_MAX)
7891         return CR_INVALID_PROPERTY;
7892 
7893     if (Buffer != NULL && ulLength == 0)
7894         return CR_INVALID_POINTER;
7895 
7896     if (ulFlags != 0)
7897         return CR_INVALID_FLAG;
7898 
7899     if (hMachine != NULL)
7900     {
7901         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7902         if (BindingHandle == NULL)
7903             return CR_FAILURE;
7904 
7905         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
7906         if (StringTable == 0)
7907             return CR_FAILURE;
7908     }
7909     else
7910     {
7911         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
7912             return CR_FAILURE;
7913     }
7914 
7915     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
7916     if (lpDevInst == NULL)
7917         return CR_INVALID_DEVNODE;
7918 
7919     /* Get property type */
7920     ulType = GetRegistryPropertyType(ulProperty);
7921 
7922     RpcTryExcept
7923     {
7924         ret = PNP_SetDeviceRegProp(BindingHandle,
7925                                    lpDevInst,
7926                                    ulProperty,
7927                                    ulType,
7928                                    (BYTE *)Buffer,
7929                                    ulLength,
7930                                    ulFlags);
7931     }
7932     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7933     {
7934         ret = RpcStatusToCmStatus(RpcExceptionCode());
7935     }
7936     RpcEndExcept;
7937 
7938     return ret;
7939 }
7940 
7941 
7942 /***********************************************************************
7943  * CM_Set_HW_Prof [SETUPAPI.@]
7944  */
7945 CONFIGRET
7946 WINAPI
7947 CM_Set_HW_Prof(
7948     _In_ ULONG ulHardwareProfile,
7949     _In_ ULONG ulFlags)
7950 {
7951     TRACE("CM_Set_HW_Prof(%lu %lx)\n",
7952           ulHardwareProfile, ulFlags);
7953 
7954     return CM_Set_HW_Prof_Ex(ulHardwareProfile, ulFlags, NULL);
7955 }
7956 
7957 
7958 /***********************************************************************
7959  * CM_Set_HW_Prof_Ex [SETUPAPI.@]
7960  */
7961 CONFIGRET
7962 WINAPI
7963 CM_Set_HW_Prof_Ex(
7964     _In_ ULONG ulHardwareProfile,
7965     _In_ ULONG ulFlags,
7966     _In_opt_ HMACHINE hMachine)
7967 {
7968     RPC_BINDING_HANDLE BindingHandle = NULL;
7969     CONFIGRET ret;
7970 
7971     TRACE("CM_Set_HW_Prof_Ex(%lu %lx %p)\n",
7972           ulHardwareProfile, ulFlags, hMachine);
7973 
7974     if (!pSetupIsUserAdmin())
7975         return CR_ACCESS_DENIED;
7976 
7977     if (ulFlags != 0)
7978         return CR_INVALID_FLAG;
7979 
7980     if (hMachine != NULL)
7981     {
7982         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
7983         if (BindingHandle == NULL)
7984             return CR_FAILURE;
7985     }
7986     else
7987     {
7988         if (!PnpGetLocalHandles(&BindingHandle, NULL))
7989             return CR_FAILURE;
7990     }
7991 
7992     RpcTryExcept
7993     {
7994         ret = PNP_SetHwProf(BindingHandle, ulHardwareProfile, ulFlags);
7995     }
7996     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
7997     {
7998         ret = RpcStatusToCmStatus(RpcExceptionCode());
7999     }
8000     RpcEndExcept;
8001 
8002     return ret;
8003 }
8004 
8005 
8006 /***********************************************************************
8007  * CM_Set_HW_Prof_FlagsA [SETUPAPI.@]
8008  */
8009 CONFIGRET
8010 WINAPI
8011 CM_Set_HW_Prof_FlagsA(
8012     _In_ DEVINSTID_A szDevInstName,
8013     _In_ ULONG ulConfig,
8014     _In_ ULONG ulValue,
8015     _In_ ULONG ulFlags)
8016 {
8017     TRACE("CM_Set_HW_Prof_FlagsA(%s %lu %lu %lx)\n",
8018           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags);
8019 
8020     return CM_Set_HW_Prof_Flags_ExA(szDevInstName, ulConfig, ulValue,
8021                                     ulFlags, NULL);
8022 }
8023 
8024 
8025 /***********************************************************************
8026  * CM_Set_HW_Prof_FlagsW [SETUPAPI.@]
8027  */
8028 CONFIGRET
8029 WINAPI
8030 CM_Set_HW_Prof_FlagsW(
8031     _In_ DEVINSTID_W szDevInstName,
8032     _In_ ULONG ulConfig,
8033     _In_ ULONG ulValue,
8034     _In_ ULONG ulFlags)
8035 {
8036     TRACE("CM_Set_HW_Prof_FlagsW(%s %lu %lu %lx)\n",
8037           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags);
8038 
8039     return CM_Set_HW_Prof_Flags_ExW(szDevInstName, ulConfig, ulValue,
8040                                     ulFlags, NULL);
8041 }
8042 
8043 
8044 /***********************************************************************
8045  * CM_Set_HW_Prof_Flags_ExA [SETUPAPI.@]
8046  */
8047 CONFIGRET
8048 WINAPI
8049 CM_Set_HW_Prof_Flags_ExA(
8050     _In_ DEVINSTID_A szDevInstName,
8051     _In_ ULONG ulConfig,
8052     _In_ ULONG ulValue,
8053     _In_ ULONG ulFlags,
8054     _In_opt_ HMACHINE hMachine)
8055 {
8056     DEVINSTID_W pszDevIdW = NULL;
8057     CONFIGRET ret = CR_SUCCESS;
8058 
8059     TRACE("CM_Set_HW_Prof_Flags_ExA(%s %lu %lu %lx %p)\n",
8060           debugstr_a(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
8061 
8062     if (szDevInstName != NULL)
8063     {
8064        if (pSetupCaptureAndConvertAnsiArg(szDevInstName, &pszDevIdW))
8065          return CR_INVALID_DEVICE_ID;
8066     }
8067 
8068     ret = CM_Set_HW_Prof_Flags_ExW(pszDevIdW, ulConfig, ulValue,
8069                                    ulFlags, hMachine);
8070 
8071     if (pszDevIdW != NULL)
8072         MyFree(pszDevIdW);
8073 
8074     return ret;
8075 }
8076 
8077 
8078 /***********************************************************************
8079  * CM_Set_HW_Prof_Flags_ExW [SETUPAPI.@]
8080  */
8081 CONFIGRET
8082 WINAPI
8083 CM_Set_HW_Prof_Flags_ExW(
8084     _In_ DEVINSTID_W szDevInstName,
8085     _In_ ULONG ulConfig,
8086     _In_ ULONG ulValue,
8087     _In_ ULONG ulFlags,
8088     _In_opt_ HMACHINE hMachine)
8089 {
8090     RPC_BINDING_HANDLE BindingHandle = NULL;
8091     CONFIGRET ret;
8092 
8093     FIXME("CM_Set_HW_Prof_Flags_ExW(%s %lu %lu %lx %p)\n",
8094           debugstr_w(szDevInstName), ulConfig, ulValue, ulFlags, hMachine);
8095 
8096     if (szDevInstName == NULL)
8097         return CR_INVALID_POINTER;
8098 
8099     if (ulFlags & ~ CM_SET_HW_PROF_FLAGS_BITS)
8100         return CR_INVALID_FLAG;
8101 
8102     /* FIXME: Check whether szDevInstName is valid */
8103 
8104     if (hMachine != NULL)
8105     {
8106         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8107         if (BindingHandle == NULL)
8108             return CR_FAILURE;
8109     }
8110     else
8111     {
8112         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8113             return CR_FAILURE;
8114     }
8115 
8116     RpcTryExcept
8117     {
8118         ret = PNP_HwProfFlags(BindingHandle, PNP_SET_HWPROFFLAGS, szDevInstName,
8119                               ulConfig, &ulValue, NULL, NULL, 0, 0);
8120     }
8121     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8122     {
8123         ret = RpcStatusToCmStatus(RpcExceptionCode());
8124     }
8125     RpcEndExcept;
8126 
8127     return ret;
8128 }
8129 
8130 
8131 /***********************************************************************
8132  * CM_Setup_DevNode [SETUPAPI.@]
8133  */
8134 CONFIGRET
8135 WINAPI
8136 CM_Setup_DevNode(
8137     _In_ DEVINST dnDevInst,
8138     _In_ ULONG ulFlags)
8139 {
8140     TRACE("CM_Setup_DevNode(%lx %lx)\n",
8141           dnDevInst, ulFlags);
8142 
8143     return CM_Setup_DevNode_Ex(dnDevInst, ulFlags, NULL);
8144 }
8145 
8146 
8147 /***********************************************************************
8148  * CM_Setup_DevNode_Ex [SETUPAPI.@]
8149  */
8150 CONFIGRET
8151 WINAPI
8152 CM_Setup_DevNode_Ex(
8153     _In_ DEVINST dnDevInst,
8154     _In_ ULONG ulFlags,
8155     _In_opt_ HMACHINE hMachine)
8156 {
8157     RPC_BINDING_HANDLE BindingHandle = NULL;
8158     HSTRING_TABLE StringTable = NULL;
8159     LPWSTR lpDevInst;
8160     CONFIGRET ret;
8161 
8162     FIXME("CM_Setup_DevNode_Ex(%lx %lx %p)\n",
8163           dnDevInst, ulFlags, hMachine);
8164 
8165     if (!pSetupIsUserAdmin())
8166         return CR_ACCESS_DENIED;
8167 
8168     if (dnDevInst == 0)
8169         return CR_INVALID_DEVNODE;
8170 
8171     if (ulFlags & ~CM_SETUP_BITS)
8172         return CR_INVALID_FLAG;
8173 
8174     if (hMachine != NULL)
8175     {
8176         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8177         if (BindingHandle == NULL)
8178             return CR_FAILURE;
8179 
8180         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
8181         if (StringTable == 0)
8182             return CR_FAILURE;
8183     }
8184     else
8185     {
8186         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8187             return CR_FAILURE;
8188     }
8189 
8190     lpDevInst = pSetupStringTableStringFromId(StringTable, dnDevInst);
8191     if (lpDevInst == NULL)
8192         return CR_INVALID_DEVNODE;
8193 
8194     RpcTryExcept
8195     {
8196         ret = PNP_DeviceInstanceAction(BindingHandle,
8197                                        PNP_DEVINST_SETUP,
8198                                        ulFlags,
8199                                        lpDevInst,
8200                                        NULL);
8201     }
8202     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8203     {
8204         ret = RpcStatusToCmStatus(RpcExceptionCode());
8205     }
8206     RpcEndExcept;
8207 
8208     return ret;
8209 }
8210 
8211 
8212 /***********************************************************************
8213  * CM_Test_Range_Available [SETUPAPI.@]
8214  */
8215 CONFIGRET
8216 WINAPI
8217 CM_Test_Range_Available(
8218     _In_ DWORDLONG ullStartValue,
8219     _In_ DWORDLONG ullEndValue,
8220     _In_ RANGE_LIST rlh,
8221     _In_ ULONG ulFlags)
8222 {
8223     FIXME("CM_Test_Range_Available(%I64u %I64u %p %lx)\n",
8224           ullStartValue, ullEndValue, rlh, ulFlags);
8225     return CR_CALL_NOT_IMPLEMENTED;
8226 }
8227 
8228 
8229 /***********************************************************************
8230  * CM_Uninstall_DevNode [SETUPAPI.@]
8231  */
8232 CONFIGRET
8233 WINAPI
8234 CM_Uninstall_DevNode(
8235     _In_ DEVINST dnPhantom,
8236     _In_ ULONG ulFlags)
8237 {
8238     TRACE("CM_Uninstall_DevNode(%lx %lx)\n",
8239           dnPhantom, ulFlags);
8240 
8241     return CM_Uninstall_DevNode_Ex(dnPhantom, ulFlags, NULL);
8242 }
8243 
8244 
8245 /***********************************************************************
8246  * CM_Uninstall_DevNode_Ex [SETUPAPI.@]
8247  */
8248 CONFIGRET
8249 WINAPI
8250 CM_Uninstall_DevNode_Ex(
8251     _In_ DEVINST dnPhantom,
8252     _In_ ULONG ulFlags,
8253     _In_opt_ HMACHINE hMachine)
8254 {
8255     RPC_BINDING_HANDLE BindingHandle = NULL;
8256     HSTRING_TABLE StringTable = NULL;
8257     LPWSTR lpDevInst;
8258     CONFIGRET ret;
8259 
8260     TRACE("CM_Uninstall_DevNode_Ex(%lx %lx %p)\n",
8261           dnPhantom, ulFlags, hMachine);
8262 
8263     if (dnPhantom == 0)
8264         return CR_INVALID_DEVNODE;
8265 
8266     if (ulFlags != 0)
8267         return CR_INVALID_FLAG;
8268 
8269     if (hMachine != NULL)
8270     {
8271         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8272         if (BindingHandle == NULL)
8273             return CR_FAILURE;
8274 
8275         StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
8276         if (StringTable == 0)
8277             return CR_FAILURE;
8278     }
8279     else
8280     {
8281         if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
8282             return CR_FAILURE;
8283     }
8284 
8285     lpDevInst = pSetupStringTableStringFromId(StringTable, dnPhantom);
8286     if (lpDevInst == NULL)
8287         return CR_INVALID_DEVNODE;
8288 
8289     RpcTryExcept
8290     {
8291         ret = PNP_UninstallDevInst(BindingHandle,
8292                                    lpDevInst,
8293                                    ulFlags);
8294     }
8295     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8296     {
8297         ret = RpcStatusToCmStatus(RpcExceptionCode());
8298     }
8299     RpcEndExcept;
8300 
8301     return ret;
8302 }
8303 
8304 
8305 /***********************************************************************
8306  * CM_Unregister_Device_InterfaceA [SETUPAPI.@]
8307  */
8308 CONFIGRET
8309 WINAPI
8310 CM_Unregister_Device_InterfaceA(
8311     _In_ LPCSTR pszDeviceInterface,
8312     _In_ ULONG ulFlags)
8313 {
8314     TRACE("CM_Unregister_Device_InterfaceA(%s %lx)\n",
8315           debugstr_a(pszDeviceInterface), ulFlags);
8316 
8317     return CM_Unregister_Device_Interface_ExA(pszDeviceInterface,
8318                                               ulFlags, NULL);
8319 }
8320 
8321 
8322 /***********************************************************************
8323  * CM_Unregister_Device_InterfaceW [SETUPAPI.@]
8324  */
8325 CONFIGRET
8326 WINAPI
8327 CM_Unregister_Device_InterfaceW(
8328     _In_ LPCWSTR pszDeviceInterface,
8329     _In_ ULONG ulFlags)
8330 {
8331     TRACE("CM_Unregister_Device_InterfaceW(%s %lx)\n",
8332           debugstr_w(pszDeviceInterface), ulFlags);
8333 
8334     return CM_Unregister_Device_Interface_ExW(pszDeviceInterface,
8335                                               ulFlags, NULL);
8336 }
8337 
8338 
8339 /***********************************************************************
8340  * CM_Unregister_Device_Interface_ExA [SETUPAPI.@]
8341  */
8342 CONFIGRET
8343 WINAPI
8344 CM_Unregister_Device_Interface_ExA(
8345     _In_ LPCSTR pszDeviceInterface,
8346     _In_ ULONG ulFlags,
8347     _In_opt_ HMACHINE hMachine)
8348 {
8349     LPWSTR pszDeviceInterfaceW = NULL;
8350     CONFIGRET ret;
8351 
8352     TRACE("CM_Unregister_Device_Interface_ExA(%s %lx %p)\n",
8353           debugstr_a(pszDeviceInterface), ulFlags, hMachine);
8354 
8355     if (pszDeviceInterface == NULL)
8356         return CR_INVALID_POINTER;
8357 
8358     if (pSetupCaptureAndConvertAnsiArg(pszDeviceInterface, &pszDeviceInterfaceW))
8359         return CR_INVALID_DATA;
8360 
8361     ret = CM_Unregister_Device_Interface_ExW(pszDeviceInterfaceW,
8362                                              ulFlags, hMachine);
8363 
8364     if (pszDeviceInterfaceW != NULL)
8365         MyFree(pszDeviceInterfaceW);
8366 
8367     return ret;
8368 }
8369 
8370 
8371 /***********************************************************************
8372  * CM_Unregister_Device_Interface_ExW [SETUPAPI.@]
8373  */
8374 CONFIGRET
8375 WINAPI
8376 CM_Unregister_Device_Interface_ExW(
8377     _In_ LPCWSTR pszDeviceInterface,
8378     _In_ ULONG ulFlags,
8379     _In_opt_ HMACHINE hMachine)
8380 {
8381     RPC_BINDING_HANDLE BindingHandle = NULL;
8382     CONFIGRET ret;
8383 
8384     TRACE("CM_Unregister_Device_Interface_ExW(%s %lx %p)\n",
8385           debugstr_w(pszDeviceInterface), ulFlags, hMachine);
8386 
8387     if (pszDeviceInterface == NULL)
8388         return CR_INVALID_POINTER;
8389 
8390     if (ulFlags != 0)
8391         return CR_INVALID_FLAG;
8392 
8393     if (hMachine != NULL)
8394     {
8395         BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
8396         if (BindingHandle == NULL)
8397             return CR_FAILURE;
8398     }
8399     else
8400     {
8401         if (!PnpGetLocalHandles(&BindingHandle, NULL))
8402             return CR_FAILURE;
8403     }
8404 
8405     RpcTryExcept
8406     {
8407         ret = PNP_UnregisterDeviceClassAssociation(BindingHandle,
8408                                                    (LPWSTR)pszDeviceInterface,
8409                                                    ulFlags);
8410     }
8411     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
8412     {
8413         ret = RpcStatusToCmStatus(RpcExceptionCode());
8414     }
8415     RpcEndExcept;
8416 
8417     return ret;
8418 }
8419