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