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