cc8ae37fcfa3498023e39e3597203703b48677c6
[reactos.git] / reactos / lib / setupapi / cfgmgr.c
1 /*
2 * Configuration manager functions
3 *
4 * Copyright 2000 James Hatheway
5 * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
29 #include "winreg.h"
30 #include "setupapi.h"
31 #include "cfgmgr32.h"
32 #include "setupapi_private.h"
33
34 #include "rpc.h"
35 #include "rpc_private.h"
36
37 #include "pnp_c.h"
38
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
42
43 /* Registry key and value names */
44 static const WCHAR Backslash[] = {'\\', 0};
45 static const WCHAR Class[] = {'C','l','a','s','s',0};
46
47 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
48 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
49 'C','o','n','t','r','o','l','\\',
50 'C','l','a','s','s',0};
51
52 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
53 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
54 'C','o','n','t','r','o','l','\\',
55 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
56
57 typedef struct _MACHINE_INFO
58 {
59 WCHAR szMachineName[MAX_PATH];
60 RPC_BINDING_HANDLE BindingHandle;
61 HSTRING_TABLE StringTable;
62 } MACHINE_INFO, *PMACHINE_INFO;
63
64
65 /***********************************************************************
66 * CM_Connect_MachineA [SETUPAPI.@]
67 */
68 CONFIGRET WINAPI CM_Connect_MachineA(PCSTR UNCServerName, PHMACHINE phMachine)
69 {
70 PWSTR pServerNameW;
71 CONFIGRET ret;
72
73 TRACE("%s %p\n", UNCServerName, phMachine);
74
75 if (UNCServerName == NULL || *UNCServerName == 0)
76 return CM_Connect_MachineW(NULL, phMachine);
77
78 if (CaptureAndConvertAnsiArg(UNCServerName, &pServerNameW))
79 return CR_INVALID_DATA;
80
81 ret = CM_Connect_MachineW(pServerNameW, phMachine);
82
83 MyFree(pServerNameW);
84
85 return ret;
86 }
87
88
89 /***********************************************************************
90 * CM_Connect_MachineW [SETUPAPI.@]
91 */
92 CONFIGRET WINAPI CM_Connect_MachineW(PCWSTR UNCServerName, PHMACHINE phMachine)
93 {
94 PMACHINE_INFO pMachine;
95
96 TRACE("%s %p\n", debugstr_w(UNCServerName), phMachine);
97
98 pMachine = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MACHINE_INFO));
99 if (pMachine == NULL)
100 return CR_OUT_OF_MEMORY;
101
102 lstrcpyW(pMachine->szMachineName, UNCServerName);
103
104 pMachine->StringTable = StringTableInitialize();
105 if (pMachine->StringTable == NULL)
106 {
107 HeapFree(GetProcessHeap(), 0, pMachine);
108 return CR_FAILURE;
109 }
110
111 StringTableAddString(pMachine->StringTable, L"PLT", 1);
112
113 if (!PnpBindRpc(UNCServerName, &pMachine->BindingHandle))
114 {
115 StringTableDestroy(pMachine->StringTable);
116 HeapFree(GetProcessHeap(), 0, pMachine);
117 return CR_INVALID_MACHINENAME;
118 }
119
120 phMachine = (PHMACHINE)pMachine;
121
122 return CR_SUCCESS;
123 }
124
125
126 /***********************************************************************
127 * CM_Disconnect_Machine [SETUPAPI.@]
128 */
129 CONFIGRET WINAPI CM_Disconnect_Machine(HMACHINE hMachine)
130 {
131 PMACHINE_INFO pMachine;
132
133 TRACE("%lx\n", hMachine);
134
135 pMachine = (PMACHINE_INFO)hMachine;
136 if (pMachine == NULL)
137 return CR_SUCCESS;
138
139 if (pMachine->StringTable != NULL)
140 StringTableDestroy(pMachine->StringTable);
141
142 if (!PnpUnbindRpc(pMachine->BindingHandle))
143 return CR_ACCESS_DENIED;
144
145 HeapFree(GetProcessHeap(), 0, pMachine);
146
147 return CR_SUCCESS;
148 }
149
150
151 /***********************************************************************
152 * CM_Enumerate_Classes [SETUPAPI.@]
153 */
154 CONFIGRET WINAPI CM_Enumerate_Classes(
155 ULONG ulClassIndex, LPGUID ClassGuid, ULONG ulFlags)
156 {
157 TRACE("%lx %p %lx\n", ulClassIndex, ClassGuid, ulFlags);
158 return CM_Enumerate_Classes_Ex(ulClassIndex, ClassGuid, ulFlags, NULL);
159 }
160
161
162 static CONFIGRET GetCmCodeFromErrorCode(DWORD ErrorCode)
163 {
164 switch (ErrorCode)
165 {
166 case ERROR_SUCCESS:
167 return CR_SUCCESS;
168
169 case ERROR_ACCESS_DENIED:
170 return CR_ACCESS_DENIED;
171
172 case ERROR_INSUFFICIENT_BUFFER:
173 return CR_BUFFER_SMALL;
174
175 case ERROR_INVALID_DATA:
176 return CR_INVALID_DATA;
177
178 case ERROR_INVALID_PARAMETER:
179 return CR_INVALID_DATA;
180
181 case ERROR_NO_MORE_ITEMS:
182 return CR_NO_SUCH_VALUE;
183
184 case ERROR_NO_SYSTEM_RESOURCES:
185 return CR_OUT_OF_MEMORY;
186
187 default:
188 return CR_FAILURE;
189 }
190 }
191
192
193 /***********************************************************************
194 * CM_Enumerate_Classes_Ex [SETUPAPI.@]
195 */
196 CONFIGRET WINAPI CM_Enumerate_Classes_Ex(
197 ULONG ulClassIndex, LPGUID ClassGuid, ULONG ulFlags, HMACHINE hMachine)
198 {
199 HKEY hRelativeKey, hKey;
200 DWORD rc;
201 WCHAR Buffer[MAX_GUID_STRING_LEN];
202
203 TRACE("%lx %p %lx %p\n", ulClassIndex, ClassGuid, ulFlags, hMachine);
204
205 if (ClassGuid == NULL)
206 return CR_INVALID_POINTER;
207
208 if (ulFlags != 0)
209 return CR_INVALID_FLAG;
210
211 if (hMachine != NULL)
212 {
213 FIXME("hMachine argument ignored\n");
214 hRelativeKey = HKEY_LOCAL_MACHINE; /* FIXME: use here a field in hMachine */
215 }
216 else
217 hRelativeKey = HKEY_LOCAL_MACHINE;
218
219 rc = RegOpenKeyExW(
220 hRelativeKey,
221 ControlClass,
222 0, /* options */
223 KEY_ENUMERATE_SUB_KEYS,
224 &hKey);
225 if (rc != ERROR_SUCCESS)
226 return GetCmCodeFromErrorCode(rc);
227
228 rc = RegEnumKeyW(
229 hKey,
230 ulClassIndex,
231 Buffer,
232 sizeof(Buffer) / sizeof(WCHAR));
233
234 RegCloseKey(hKey);
235
236 if (rc == ERROR_SUCCESS)
237 {
238 /* Remove the {} */
239 Buffer[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
240 /* Convert the buffer to a GUID */
241 if (UuidFromStringW(&Buffer[1], ClassGuid) != RPC_S_OK)
242 return CR_FAILURE;
243 }
244
245 return GetCmCodeFromErrorCode(rc);
246 }
247
248
249 /***********************************************************************
250 * CM_Get_Child [SETUPAPI.@]
251 */
252 CONFIGRET WINAPI CM_Get_Child(
253 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
254 {
255 TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
256 return CM_Get_Child_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
257 }
258
259
260 /***********************************************************************
261 * CM_Get_Child_Ex [SETUPAPI.@]
262 */
263 CONFIGRET WINAPI CM_Get_Child_Ex(
264 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
265 {
266 WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
267 RPC_BINDING_HANDLE BindingHandle = NULL;
268 HSTRING_TABLE StringTable = NULL;
269 LPWSTR lpDevInst;
270 DWORD dwIndex;
271 CONFIGRET ret;
272
273 TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
274
275 if (pdnDevInst == NULL)
276 return CR_INVALID_POINTER;
277
278 if (dnDevInst == 0)
279 return CR_INVALID_DEVINST;
280
281 if (ulFlags != 0)
282 return CR_INVALID_FLAG;
283
284 *pdnDevInst = -1;
285
286 if (hMachine != NULL)
287 {
288 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
289 if (BindingHandle == NULL)
290 return CR_FAILURE;
291
292 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
293 if (StringTable == 0)
294 return CR_FAILURE;
295 }
296 else
297 {
298 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
299 return CR_FAILURE;
300 }
301
302 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
303 if (lpDevInst == NULL)
304 return CR_INVALID_DEVNODE;
305
306 ret = PNP_GetRelatedDeviceInstance(BindingHandle,
307 PNP_DEVICE_CHILD,
308 lpDevInst,
309 szRelatedDevInst,
310 MAX_DEVICE_ID_LEN,
311 0);
312 if (ret != CR_SUCCESS)
313 return ret;
314
315 TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
316
317 dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
318 if (dwIndex == -1)
319 return CR_FAILURE;
320
321 *pdnDevInst = dwIndex;
322
323 return CR_SUCCESS;
324 }
325
326
327 /***********************************************************************
328 * CM_Get_Class_Key_NameA [SETUPAPI.@]
329 */
330 CONFIGRET WINAPI CM_Get_Class_Key_NameA(
331 LPGUID ClassGuid, LPSTR pszKeyName, PULONG pulLength, ULONG ulFlags)
332 {
333 TRACE("%p %p %p %lx\n",
334 ClassGuid, pszKeyName, pulLength, ulFlags);
335 return CM_Get_Class_Key_Name_ExA(ClassGuid, pszKeyName, pulLength,
336 ulFlags, NULL);
337 }
338
339
340 /***********************************************************************
341 * CM_Get_Class_Key_NameW [SETUPAPI.@]
342 */
343 CONFIGRET WINAPI CM_Get_Class_Key_NameW(
344 LPGUID ClassGuid, LPWSTR pszKeyName, PULONG pulLength, ULONG ulFlags)
345 {
346 TRACE("%p %p %p %lx\n",
347 ClassGuid, pszKeyName, pulLength, ulFlags);
348 return CM_Get_Class_Key_Name_ExW(ClassGuid, pszKeyName, pulLength,
349 ulFlags, NULL);
350 }
351
352
353 /***********************************************************************
354 * CM_Get_Class_Key_Name_ExA [SETUPAPI.@]
355 */
356 CONFIGRET WINAPI CM_Get_Class_Key_Name_ExA(
357 LPGUID ClassGuid, LPSTR pszKeyName, PULONG pulLength, ULONG ulFlags,
358 HMACHINE hMachine)
359 {
360 WCHAR szBuffer[MAX_GUID_STRING_LEN];
361 CONFIGRET ret = CR_SUCCESS;
362 ULONG ulLength;
363 ULONG ulOrigLength;
364
365 TRACE("%p %p %p %lx %lx\n",
366 ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
367
368 if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
369 return CR_INVALID_POINTER;
370
371 ulOrigLength = *pulLength;
372 *pulLength = 0;
373
374 ulLength = MAX_GUID_STRING_LEN;
375 ret = CM_Get_Class_Key_Name_ExW(ClassGuid, szBuffer, &ulLength,
376 ulFlags, hMachine);
377 if (ret == CR_SUCCESS)
378 {
379 if (WideCharToMultiByte(CP_ACP,
380 0,
381 szBuffer,
382 ulLength,
383 pszKeyName,
384 ulOrigLength,
385 NULL,
386 NULL) == 0)
387 ret = CR_FAILURE;
388 else
389 *pulLength = lstrlenA(pszKeyName) + 1;
390 }
391
392 return CR_SUCCESS;
393 }
394
395
396 static BOOL GuidToString(LPGUID Guid, LPWSTR String)
397 {
398 LPWSTR lpString;
399
400 if (UuidToStringW(Guid, &lpString) != RPC_S_OK)
401 return FALSE;
402
403 lstrcpyW(&String[1], lpString);
404
405 String[0] = L'{';
406 String[MAX_GUID_STRING_LEN - 2] = L'}';
407 String[MAX_GUID_STRING_LEN - 1] = 0;
408
409 RpcStringFree(&lpString);
410
411 return TRUE;
412 }
413
414
415 /***********************************************************************
416 * CM_Get_Class_Key_Name_ExW [SETUPAPI.@]
417 */
418 CONFIGRET WINAPI CM_Get_Class_Key_Name_ExW(
419 LPGUID ClassGuid, LPWSTR pszKeyName, PULONG pulLength, ULONG ulFlags,
420 HMACHINE hMachine)
421 {
422 TRACE("%p %p %p %lx %lx\n",
423 ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
424
425 if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
426 return CR_INVALID_POINTER;
427
428 if (ulFlags != 0)
429 return CR_INVALID_FLAG;
430
431 if (*pulLength < MAX_GUID_STRING_LEN)
432 {
433 *pulLength = 0;
434 return CR_BUFFER_SMALL;
435 }
436
437 if (!GuidToString(ClassGuid, pszKeyName))
438 return CR_INVALID_DATA;
439
440 *pulLength = MAX_GUID_STRING_LEN;
441
442 return CR_SUCCESS;
443 }
444
445
446 /***********************************************************************
447 * CM_Get_Class_NameA [SETUPAPI.@]
448 */
449 CONFIGRET WINAPI CM_Get_Class_NameA(
450 LPGUID ClassGuid, PCHAR Buffer, PULONG pulLength, ULONG ulFlags)
451 {
452 TRACE("%p %p %p %lx\n", ClassGuid, Buffer, pulLength, ulFlags);
453 return CM_Get_Class_Name_ExA(ClassGuid, Buffer, pulLength, ulFlags,
454 NULL);
455 }
456
457
458 /***********************************************************************
459 * CM_Get_Class_NameW [SETUPAPI.@]
460 */
461 CONFIGRET WINAPI CM_Get_Class_NameW(
462 LPGUID ClassGuid, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags)
463 {
464 TRACE("%p %p %p %lx\n", ClassGuid, Buffer, pulLength, ulFlags);
465 return CM_Get_Class_Name_ExW(ClassGuid, Buffer, pulLength, ulFlags,
466 NULL);
467 }
468
469
470 /***********************************************************************
471 * CM_Get_Class_Name_ExA [SETUPAPI.@]
472 */
473 CONFIGRET WINAPI CM_Get_Class_Name_ExA(
474 LPGUID ClassGuid, PCHAR Buffer, PULONG pulLength, ULONG ulFlags,
475 HMACHINE hMachine)
476 {
477 WCHAR szBuffer[MAX_CLASS_NAME_LEN];
478 CONFIGRET ret = CR_SUCCESS;
479 ULONG ulLength;
480 ULONG ulOrigLength;
481
482 TRACE("%p %p %p %lx %lx\n",
483 ClassGuid, Buffer, pulLength, ulFlags, hMachine);
484
485 if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
486 return CR_INVALID_POINTER;
487
488 ulOrigLength = *pulLength;
489 *pulLength = 0;
490
491 ulLength = MAX_CLASS_NAME_LEN;
492 ret = CM_Get_Class_Name_ExW(ClassGuid, szBuffer, &ulLength,
493 ulFlags, hMachine);
494 if (ret == CR_SUCCESS)
495 {
496 if (WideCharToMultiByte(CP_ACP,
497 0,
498 szBuffer,
499 ulLength,
500 Buffer,
501 ulOrigLength,
502 NULL,
503 NULL) == 0)
504 ret = CR_FAILURE;
505 else
506 *pulLength = lstrlenA(Buffer) + 1;
507 }
508
509 return ret;
510 }
511
512
513 /***********************************************************************
514 * CM_Get_Class_Name_ExW [SETUPAPI.@]
515 */
516 CONFIGRET WINAPI
517 CM_Get_Class_Name_ExW(
518 LPGUID ClassGuid, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags,
519 HMACHINE hMachine)
520 {
521 WCHAR szGuidString[MAX_GUID_STRING_LEN];
522 RPC_BINDING_HANDLE BindingHandle = NULL;
523
524 TRACE("%p %p %p %lx %lx\n",
525 ClassGuid, Buffer, pulLength, ulFlags, hMachine);
526
527 if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
528 return CR_INVALID_POINTER;
529
530 if (ulFlags != 0)
531 return CR_INVALID_FLAG;
532
533 if (!GuidToString(ClassGuid, szGuidString))
534 return CR_INVALID_DATA;
535
536 TRACE("Guid %s\n", debugstr_w(szGuidString));
537
538 if (hMachine != NULL)
539 {
540 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
541 if (BindingHandle == NULL)
542 return CR_FAILURE;
543 }
544 else
545 {
546 if (!PnpGetLocalHandles(&BindingHandle, NULL))
547 return CR_FAILURE;
548 }
549
550 return PNP_GetClassName(BindingHandle,
551 szGuidString,
552 Buffer,
553 pulLength,
554 ulFlags);
555 }
556
557
558 /***********************************************************************
559 * CM_Get_Depth [SETUPAPI.@]
560 */
561 CONFIGRET WINAPI CM_Get_Depth(
562 PULONG pulDepth, DEVINST dnDevInst, ULONG ulFlags)
563 {
564 TRACE("%p %lx %lx\n", pulDepth, dnDevInst, ulFlags);
565 return CM_Get_Depth_Ex(pulDepth, dnDevInst, ulFlags, NULL);
566 }
567
568
569 /***********************************************************************
570 * CM_Get_Depth_Ex [SETUPAPI.@]
571 */
572 CONFIGRET WINAPI CM_Get_Depth_Ex(
573 PULONG pulDepth, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
574 {
575 RPC_BINDING_HANDLE BindingHandle = NULL;
576 HSTRING_TABLE StringTable = NULL;
577 LPWSTR lpDevInst;
578
579 TRACE("%p %lx %lx %lx\n",
580 pulDepth, dnDevInst, ulFlags, hMachine);
581
582 if (pulDepth == NULL)
583 return CR_INVALID_POINTER;
584
585 if (dnDevInst == 0)
586 return CR_INVALID_DEVINST;
587
588 if (ulFlags != 0)
589 return CR_INVALID_FLAG;
590
591 if (hMachine != NULL)
592 {
593 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
594 if (BindingHandle == NULL)
595 return CR_FAILURE;
596
597 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
598 if (StringTable == 0)
599 return CR_FAILURE;
600 }
601 else
602 {
603 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
604 return CR_FAILURE;
605 }
606
607 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
608 if (lpDevInst == NULL)
609 return CR_INVALID_DEVNODE;
610
611 return PNP_GetDepth(BindingHandle,
612 lpDevInst,
613 pulDepth,
614 ulFlags);
615 }
616
617
618 /***********************************************************************
619 * CM_Get_DevNode_Registry_PropertyA [SETUPAPI.@]
620 */
621 CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyA(
622 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
623 PVOID Buffer, PULONG pulLength, ULONG ulFlags)
624 {
625 TRACE("%lx %lu %p %p %p %lx\n",
626 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
627
628 return CM_Get_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
629 pulRegDataType, Buffer,
630 pulLength, ulFlags, NULL);
631 }
632
633
634 /***********************************************************************
635 * CM_Get_DevNode_Registry_PropertyW [SETUPAPI.@]
636 */
637 CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyW(
638 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
639 PVOID Buffer, PULONG pulLength, ULONG ulFlags)
640 {
641 TRACE("%lx %lu %p %p %p %lx\n",
642 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
643
644 return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
645 pulRegDataType, Buffer,
646 pulLength, ulFlags, NULL);
647 }
648
649
650 /***********************************************************************
651 * CM_Get_DevNode_Registry_Property_ExA [SETUPAPI.@]
652 */
653 CONFIGRET WINAPI CM_Get_DevNode_Registry_Property_ExA(
654 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
655 PVOID Buffer, PULONG pulLength, ULONG ulFlags, HMACHINE hMachine)
656 {
657 FIXME("%lx %lu %p %p %p %lx %lx\n",
658 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
659 ulFlags, hMachine);
660
661 return CR_CALL_NOT_IMPLEMENTED;
662 }
663
664
665 /***********************************************************************
666 * CM_Get_DevNode_Registry_Property_ExW [SETUPAPI.@]
667 */
668 CONFIGRET WINAPI CM_Get_DevNode_Registry_Property_ExW(
669 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
670 PVOID Buffer, PULONG pulLength, ULONG ulFlags, HMACHINE hMachine)
671 {
672 RPC_BINDING_HANDLE BindingHandle = NULL;
673 HSTRING_TABLE StringTable = NULL;
674 CONFIGRET ret = CR_SUCCESS;
675 LPWSTR lpDevInst;
676 ULONG ulDataType = 0;
677 ULONG ulTransferLength = 0;
678
679 FIXME("%lx %lu %p %p %p %lx %lx\n",
680 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
681 ulFlags, hMachine);
682
683 if (dnDevInst == 0)
684 return CR_INVALID_DEVNODE;
685
686 if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
687 return CR_INVALID_PROPERTY;
688
689 /* pulRegDataType is optional */
690
691 /* Buffer is optional */
692
693 if (pulLength == NULL)
694 return CR_INVALID_POINTER;
695
696 if (*pulLength == 0)
697 return CR_INVALID_POINTER;
698
699 if (ulFlags != 0)
700 return CR_INVALID_FLAG;
701
702 if (hMachine != NULL)
703 {
704 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
705 if (BindingHandle == NULL)
706 return CR_FAILURE;
707
708 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
709 if (StringTable == 0)
710 return CR_FAILURE;
711 }
712 else
713 {
714 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
715 return CR_FAILURE;
716 }
717
718 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
719 if (lpDevInst == NULL)
720 return CR_INVALID_DEVNODE;
721
722 ulTransferLength = *pulLength;
723 ret = PNP_GetDeviceRegProp(BindingHandle,
724 lpDevInst,
725 ulProperty,
726 &ulDataType,
727 Buffer,
728 &ulTransferLength,
729 pulLength,
730 ulFlags);
731 if (ret == CR_SUCCESS)
732 {
733 if (pulRegDataType != NULL)
734 *pulRegDataType = ulDataType;
735 }
736
737 return ret;
738 }
739
740
741 /***********************************************************************
742 * CM_Get_DevNode_Status [SETUPAPI.@]
743 */
744 CONFIGRET WINAPI CM_Get_DevNode_Status(
745 PULONG pulStatus, PULONG pulProblemNumber, DEVINST dnDevInst,
746 ULONG ulFlags)
747 {
748 TRACE("%p %p %lx %lx\n",
749 pulStatus, pulProblemNumber, dnDevInst, ulFlags);
750 return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber, dnDevInst,
751 ulFlags, NULL);
752 }
753
754
755 /***********************************************************************
756 * CM_Get_DevNode_Status_Ex [SETUPAPI.@]
757 */
758 CONFIGRET WINAPI
759 CM_Get_DevNode_Status_Ex(
760 PULONG pulStatus, PULONG pulProblemNumber, DEVINST dnDevInst,
761 ULONG ulFlags, HMACHINE hMachine)
762 {
763 RPC_BINDING_HANDLE BindingHandle = NULL;
764 HSTRING_TABLE StringTable = NULL;
765 LPWSTR lpDevInst;
766
767 TRACE("%p %p %lx %lx %lx\n",
768 pulStatus, pulProblemNumber, dnDevInst, ulFlags, hMachine);
769
770 if (pulStatus == NULL || pulProblemNumber == NULL)
771 return CR_INVALID_POINTER;
772
773 if (dnDevInst == 0)
774 return CR_INVALID_DEVINST;
775
776 if (ulFlags != 0)
777 return CR_INVALID_FLAG;
778
779 if (hMachine != NULL)
780 {
781 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
782 if (BindingHandle == NULL)
783 return CR_FAILURE;
784
785 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
786 if (StringTable == 0)
787 return CR_FAILURE;
788 }
789 else
790 {
791 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
792 return CR_FAILURE;
793 }
794
795 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
796 if (lpDevInst == NULL)
797 return CR_INVALID_DEVNODE;
798
799 return PNP_GetDeviceStatus(BindingHandle,
800 lpDevInst,
801 pulStatus,
802 pulProblemNumber,
803 ulFlags);
804 }
805
806
807 /***********************************************************************
808 * CM_Get_Device_IDA [SETUPAPI.@]
809 */
810 CONFIGRET WINAPI CM_Get_Device_IDA(
811 DEVINST dnDevInst, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
812 {
813 TRACE("%lx %p %ld %ld\n",
814 dnDevInst, Buffer, BufferLen, ulFlags);
815 return CM_Get_Device_ID_ExA(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
816 }
817
818
819 /***********************************************************************
820 * CM_Get_Device_IDW [SETUPAPI.@]
821 */
822 CONFIGRET WINAPI CM_Get_Device_IDW(
823 DEVINST dnDevInst, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
824 {
825 TRACE("%lx %p %ld %ld\n",
826 dnDevInst, Buffer, BufferLen, ulFlags);
827 return CM_Get_Device_ID_ExW(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
828 }
829
830
831 /***********************************************************************
832 * CM_Get_Device_ID_ExA [SETUPAPI.@]
833 */
834 CONFIGRET WINAPI CM_Get_Device_ID_ExA(
835 DEVINST dnDevInst, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
836 HMACHINE hMachine)
837 {
838 WCHAR szBufferW[MAX_DEVICE_ID_LEN];
839 CONFIGRET ret = CR_SUCCESS;
840
841 FIXME("%lx %p %ld %ld %lx\n",
842 dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
843
844 if (Buffer == NULL)
845 return CR_INVALID_POINTER;
846
847 ret = CM_Get_Device_ID_ExW(dnDevInst,
848 szBufferW,
849 MAX_DEVICE_ID_LEN,
850 ulFlags,
851 hMachine);
852 if (ret == CR_SUCCESS)
853 {
854 if (WideCharToMultiByte(CP_ACP,
855 0,
856 szBufferW,
857 lstrlenW(szBufferW) + 1,
858 Buffer,
859 BufferLen,
860 NULL,
861 NULL) == 0)
862 ret = CR_FAILURE;
863 }
864
865 return ret;
866 }
867
868
869 /***********************************************************************
870 * CM_Get_Device_ID_ExW [SETUPAPI.@]
871 */
872 CONFIGRET WINAPI CM_Get_Device_ID_ExW(
873 DEVINST dnDevInst, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
874 HMACHINE hMachine)
875 {
876 HSTRING_TABLE StringTable = NULL;
877
878 TRACE("%lx %p %ld %ld %lx\n",
879 dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
880
881 if (dnDevInst == 0)
882 return CR_INVALID_DEVINST;
883
884 if (Buffer == NULL)
885 return CR_INVALID_POINTER;
886
887 if (ulFlags != 0)
888 return CR_INVALID_FLAG;
889
890 if (hMachine != NULL)
891 {
892 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
893 if (StringTable == NULL)
894 return CR_FAILURE;
895 }
896 else
897 {
898 if (!PnpGetLocalHandles(NULL, &StringTable))
899 return CR_FAILURE;
900 }
901
902 if (!StringTableStringFromIdEx(StringTable,
903 dnDevInst,
904 Buffer,
905 &BufferLen))
906 return CR_FAILURE;
907
908 return CR_SUCCESS;
909 }
910
911
912 /***********************************************************************
913 * CM_Get_Device_ID_ListA [SETUPAPI.@]
914 */
915 CONFIGRET WINAPI CM_Get_Device_ID_ListA(
916 PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
917 {
918 TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags);
919 return CM_Get_Device_ID_List_ExA(pszFilter, Buffer, BufferLen,
920 ulFlags, NULL);
921 }
922
923
924 /***********************************************************************
925 * CM_Get_Device_ID_ListW [SETUPAPI.@]
926 */
927 CONFIGRET WINAPI CM_Get_Device_ID_ListW(
928 PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
929 {
930 TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags);
931 return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen,
932 ulFlags, NULL);
933 }
934
935
936 /***********************************************************************
937 * CM_Get_Device_ID_List_ExA [SETUPAPI.@]
938 */
939 CONFIGRET WINAPI CM_Get_Device_ID_List_ExA(
940 PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
941 HMACHINE hMachine)
942 {
943 LPWSTR BufferW = NULL;
944 LPWSTR pszFilterW = NULL;
945 CONFIGRET ret = CR_SUCCESS;
946
947 FIXME("%p %p %ld %ld %lx\n",
948 pszFilter, Buffer, BufferLen, ulFlags, hMachine);
949
950 BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
951 if (BufferW == NULL)
952 return CR_OUT_OF_MEMORY;
953
954 if (pszFilter == NULL)
955 {
956 ret = CM_Get_Device_ID_List_ExW(NULL,
957 BufferW,
958 BufferLen,
959 ulFlags,
960 hMachine);
961 }
962 else
963 {
964 if (CaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
965 {
966 ret = CR_INVALID_DEVICE_ID;
967 goto Done;
968 }
969
970 ret = CM_Get_Device_ID_List_ExW(pszFilterW,
971 BufferW,
972 BufferLen,
973 ulFlags,
974 hMachine);
975
976 MyFree(pszFilterW);
977 }
978
979 if (WideCharToMultiByte(CP_ACP,
980 0,
981 BufferW,
982 lstrlenW(BufferW) + 1,
983 Buffer,
984 BufferLen,
985 NULL,
986 NULL) == 0)
987 ret = CR_FAILURE;
988
989 Done:
990 MyFree(BufferW);
991
992 return ret;
993 }
994
995
996 /***********************************************************************
997 * CM_Get_Device_ID_List_ExW [SETUPAPI.@]
998 */
999 CONFIGRET WINAPI CM_Get_Device_ID_List_ExW(
1000 PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
1001 HMACHINE hMachine)
1002 {
1003 FIXME("%p %p %ld %ld %lx\n",
1004 pszFilter, Buffer, BufferLen, ulFlags, hMachine);
1005 memset(Buffer,0,2);
1006 return CR_SUCCESS;
1007 }
1008
1009
1010 /***********************************************************************
1011 * CM_Get_Device_ID_List_SizeA [SETUPAPI.@]
1012 */
1013 CONFIGRET WINAPI CM_Get_Device_ID_List_SizeA(
1014 PULONG pulLen, PCSTR pszFilter, ULONG ulFlags)
1015 {
1016 TRACE("%p %s %ld\n", pulLen, pszFilter, ulFlags);
1017 return CM_Get_Device_ID_List_Size_ExA(pulLen, pszFilter, ulFlags, NULL);
1018 }
1019
1020
1021 /***********************************************************************
1022 * CM_Get_Device_ID_List_SizeW [SETUPAPI.@]
1023 */
1024 CONFIGRET WINAPI CM_Get_Device_ID_List_SizeW(
1025 PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags)
1026 {
1027 TRACE("%p %s %ld\n", pulLen, debugstr_w(pszFilter), ulFlags);
1028 return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL);
1029 }
1030
1031
1032 /***********************************************************************
1033 * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@]
1034 */
1035 CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExA(
1036 PULONG pulLen, PCSTR pszFilter, ULONG ulFlags, HMACHINE hMachine)
1037 {
1038 LPWSTR pszFilterW = NULL;
1039 CONFIGRET ret = CR_SUCCESS;
1040
1041 FIXME("%p %s %lx %lx\n", pulLen, pszFilter, ulFlags, hMachine);
1042
1043 if (pszFilter == NULL)
1044 {
1045 ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
1046 NULL,
1047 ulFlags,
1048 hMachine);
1049 }
1050 else
1051 {
1052 if (CaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
1053 return CR_INVALID_DEVICE_ID;
1054
1055 ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
1056 pszFilterW,
1057 ulFlags,
1058 hMachine);
1059
1060 MyFree(pszFilterW);
1061 }
1062
1063 return ret;
1064 }
1065
1066
1067 /***********************************************************************
1068 * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@]
1069 */
1070 CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExW(
1071 PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags, HMACHINE hMachine)
1072 {
1073 FIXME("%p %s %ld %lx\n", pulLen, debugstr_w(pszFilter), ulFlags, hMachine);
1074 *pulLen = 2;
1075 return CR_SUCCESS;
1076 }
1077
1078
1079 /***********************************************************************
1080 * CM_Get_Device_ID_Size [SETUPAPI.@]
1081 */
1082 CONFIGRET WINAPI CM_Get_Device_ID_Size(
1083 PULONG pulLen, DEVINST dnDevInst, ULONG ulFlags)
1084 {
1085 TRACE("%p %lx %lx\n", pulLen, dnDevInst, ulFlags);
1086 return CM_Get_Device_ID_Size_Ex(pulLen, dnDevInst, ulFlags, NULL);
1087 }
1088
1089
1090 /***********************************************************************
1091 * CM_Get_Device_ID_Size_Ex [SETUPAPI.@]
1092 */
1093 CONFIGRET WINAPI CM_Get_Device_ID_Size_Ex(
1094 PULONG pulLen, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
1095 {
1096 HSTRING_TABLE StringTable = NULL;
1097 LPWSTR DeviceId;
1098
1099 TRACE("%p %lx %lx %lx\n", pulLen, dnDevInst, ulFlags, hMachine);
1100
1101 if (pulLen == NULL)
1102 return CR_INVALID_POINTER;
1103
1104 if (dnDevInst == 0)
1105 return CR_INVALID_DEVINST;
1106
1107 if (ulFlags != 0)
1108 return CR_INVALID_FLAG;
1109
1110 if (hMachine != NULL)
1111 {
1112 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1113 if (StringTable == NULL)
1114 return CR_FAILURE;
1115 }
1116 else
1117 {
1118 if (!PnpGetLocalHandles(NULL, &StringTable))
1119 return CR_FAILURE;
1120 }
1121
1122 DeviceId = StringTableStringFromId(StringTable, dnDevInst);
1123 if (DeviceId == NULL)
1124 {
1125 *pulLen = 0;
1126 return CR_SUCCESS;
1127 }
1128
1129 *pulLen = lstrlenW(DeviceId);
1130
1131 return CR_SUCCESS;
1132 }
1133
1134
1135 /***********************************************************************
1136 * CM_Get_Global_State [SETUPAPI.@]
1137 */
1138 CONFIGRET WINAPI CM_Get_Global_State(
1139 PULONG pulState, ULONG ulFlags)
1140 {
1141 TRACE("%p %lx\n", pulState, ulFlags);
1142 return CM_Get_Global_State_Ex(pulState, ulFlags, NULL);
1143 }
1144
1145
1146 /***********************************************************************
1147 * CM_Get_Global_State_Ex [SETUPAPI.@]
1148 */
1149 CONFIGRET WINAPI CM_Get_Global_State_Ex(
1150 PULONG pulState, ULONG ulFlags, HMACHINE hMachine)
1151 {
1152 RPC_BINDING_HANDLE BindingHandle = NULL;
1153
1154 TRACE("%p %lx %lx\n", pulState, ulFlags, hMachine);
1155
1156 if (pulState == NULL)
1157 return CR_INVALID_POINTER;
1158
1159 if (ulFlags != 0)
1160 return CR_INVALID_FLAG;
1161
1162 if (hMachine != NULL)
1163 {
1164 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1165 if (BindingHandle == NULL)
1166 return CR_FAILURE;
1167 }
1168 else
1169 {
1170 if (!PnpGetLocalHandles(&BindingHandle, NULL))
1171 return CR_FAILURE;
1172 }
1173
1174 return PNP_GetGlobalState(BindingHandle, pulState, ulFlags);
1175 }
1176
1177
1178 /***********************************************************************
1179 * CM_Get_Parent [SETUPAPI.@]
1180 */
1181 CONFIGRET WINAPI CM_Get_Parent(
1182 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
1183 {
1184 TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
1185 return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
1186 }
1187
1188
1189 /***********************************************************************
1190 * CM_Get_Parent_Ex [SETUPAPI.@]
1191 */
1192 CONFIGRET WINAPI CM_Get_Parent_Ex(
1193 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
1194 {
1195 WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
1196 RPC_BINDING_HANDLE BindingHandle = NULL;
1197 HSTRING_TABLE StringTable = NULL;
1198 LPWSTR lpDevInst;
1199 DWORD dwIndex;
1200 CONFIGRET ret;
1201
1202 TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
1203
1204 if (pdnDevInst == NULL)
1205 return CR_INVALID_POINTER;
1206
1207 if (dnDevInst == 0)
1208 return CR_INVALID_DEVINST;
1209
1210 if (ulFlags != 0)
1211 return CR_INVALID_FLAG;
1212
1213 *pdnDevInst = -1;
1214
1215 if (hMachine != NULL)
1216 {
1217 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1218 if (BindingHandle == NULL)
1219 return CR_FAILURE;
1220
1221 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1222 if (StringTable == 0)
1223 return CR_FAILURE;
1224 }
1225 else
1226 {
1227 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1228 return CR_FAILURE;
1229 }
1230
1231 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1232 if (lpDevInst == NULL)
1233 return CR_INVALID_DEVNODE;
1234
1235 ret = PNP_GetRelatedDeviceInstance(BindingHandle,
1236 PNP_DEVICE_PARENT,
1237 lpDevInst,
1238 szRelatedDevInst,
1239 MAX_DEVICE_ID_LEN,
1240 0);
1241 if (ret != CR_SUCCESS)
1242 return ret;
1243
1244 TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
1245
1246 dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
1247 if (dwIndex == -1)
1248 return CR_FAILURE;
1249
1250 *pdnDevInst = dwIndex;
1251
1252 return CR_SUCCESS;
1253 }
1254
1255
1256 /***********************************************************************
1257 * CM_Get_Sibling [SETUPAPI.@]
1258 */
1259 CONFIGRET WINAPI CM_Get_Sibling(
1260 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
1261 {
1262 TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
1263 return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
1264 }
1265
1266
1267 /***********************************************************************
1268 * CM_Get_Sibling_Ex [SETUPAPI.@]
1269 */
1270 CONFIGRET WINAPI CM_Get_Sibling_Ex(
1271 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
1272 {
1273 WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
1274 RPC_BINDING_HANDLE BindingHandle = NULL;
1275 HSTRING_TABLE StringTable = NULL;
1276 LPWSTR lpDevInst;
1277 DWORD dwIndex;
1278 CONFIGRET ret;
1279
1280 TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
1281
1282 if (pdnDevInst == NULL)
1283 return CR_INVALID_POINTER;
1284
1285 if (dnDevInst == 0)
1286 return CR_INVALID_DEVINST;
1287
1288 if (ulFlags != 0)
1289 return CR_INVALID_FLAG;
1290
1291 *pdnDevInst = -1;
1292
1293 if (hMachine != NULL)
1294 {
1295 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1296 if (BindingHandle == NULL)
1297 return CR_FAILURE;
1298
1299 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1300 if (StringTable == 0)
1301 return CR_FAILURE;
1302 }
1303 else
1304 {
1305 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1306 return CR_FAILURE;
1307 }
1308
1309 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1310 if (lpDevInst == NULL)
1311 return CR_INVALID_DEVNODE;
1312
1313 ret = PNP_GetRelatedDeviceInstance(BindingHandle,
1314 PNP_DEVICE_SIBLING,
1315 lpDevInst,
1316 szRelatedDevInst,
1317 MAX_DEVICE_ID_LEN,
1318 0);
1319 if (ret != CR_SUCCESS)
1320 return ret;
1321
1322 TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
1323
1324 dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
1325 if (dwIndex == -1)
1326 return CR_FAILURE;
1327
1328 *pdnDevInst = dwIndex;
1329
1330 return CR_SUCCESS;
1331 }
1332
1333
1334 /***********************************************************************
1335 * CM_Get_Version [SETUPAPI.@]
1336 */
1337 WORD WINAPI CM_Get_Version(VOID)
1338 {
1339 TRACE("\n");
1340 return CM_Get_Version_Ex(NULL);
1341 }
1342
1343
1344 /***********************************************************************
1345 * CM_Get_Version_Ex [SETUPAPI.@]
1346 */
1347 WORD WINAPI CM_Get_Version_Ex(HMACHINE hMachine)
1348 {
1349 RPC_BINDING_HANDLE BindingHandle = NULL;
1350 WORD Version = 0;
1351
1352 TRACE("%lx\n", hMachine);
1353
1354 if (hMachine != NULL)
1355 {
1356 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1357 if (BindingHandle == NULL)
1358 return 0;
1359 }
1360 else
1361 {
1362 if (!PnpGetLocalHandles(&BindingHandle, NULL))
1363 return CR_FAILURE;
1364 }
1365
1366 if (PNP_GetVersion(BindingHandle, &Version) != CR_SUCCESS)
1367 return 0;
1368
1369 return Version;
1370 }
1371
1372
1373 /***********************************************************************
1374 * CM_Locate_DevNodeA [SETUPAPI.@]
1375 */
1376 CONFIGRET WINAPI CM_Locate_DevNodeA(
1377 PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags)
1378 {
1379 TRACE("%p %s %lu\n", pdnDevInst, pDeviceID, ulFlags);
1380 return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
1381 }
1382
1383
1384 /***********************************************************************
1385 * CM_Locate_DevNodeW [SETUPAPI.@]
1386 */
1387 CONFIGRET WINAPI CM_Locate_DevNodeW(
1388 PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags)
1389 {
1390 TRACE("%p %s %lu\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags);
1391 return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
1392 }
1393
1394
1395 /***********************************************************************
1396 * CM_Locate_DevNode_ExA [SETUPAPI.@]
1397 */
1398 CONFIGRET WINAPI CM_Locate_DevNode_ExA(
1399 PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags, HMACHINE hMachine)
1400 {
1401 DEVINSTID_W pDevIdW = NULL;
1402 CONFIGRET ret = CR_SUCCESS;
1403
1404 TRACE("%p %s %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine);
1405
1406 if (pDeviceID != NULL)
1407 {
1408 if (CaptureAndConvertAnsiArg(pDeviceID, &pDevIdW))
1409 return CR_INVALID_DEVICE_ID;
1410 }
1411
1412 ret = CM_Locate_DevNode_ExW(pdnDevInst, pDevIdW, ulFlags, hMachine);
1413
1414 if (pDevIdW != NULL)
1415 MyFree(pDevIdW);
1416
1417 return ret;
1418 }
1419
1420
1421 /***********************************************************************
1422 * CM_Locate_DevNode_ExW [SETUPAPI.@]
1423 */
1424 CONFIGRET WINAPI CM_Locate_DevNode_ExW(
1425 PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags, HMACHINE hMachine)
1426 {
1427 WCHAR DeviceIdBuffer[MAX_DEVICE_ID_LEN];
1428 RPC_BINDING_HANDLE BindingHandle = NULL;
1429 HSTRING_TABLE StringTable = NULL;
1430 CONFIGRET ret = CR_SUCCESS;
1431
1432 TRACE("%p %s %lu %lx\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
1433
1434 if (pdnDevInst == NULL)
1435 return CR_INVALID_POINTER;
1436
1437 if (ulFlags & ~CM_LOCATE_DEVNODE_BITS)
1438 return CR_INVALID_FLAG;
1439
1440 if (hMachine != NULL)
1441 {
1442 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1443 if (BindingHandle == NULL)
1444 return CR_FAILURE;
1445
1446 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1447 if (StringTable == 0)
1448 return CR_FAILURE;
1449 }
1450 else
1451 {
1452 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1453 return CR_FAILURE;
1454 }
1455
1456 if (pDeviceID != NULL && lstrlenW(pDeviceID) != 0)
1457 {
1458 lstrcpyW(DeviceIdBuffer, pDeviceID);
1459 }
1460 else
1461 {
1462 /* Get the root device ID */
1463 ret = PNP_GetRootDeviceInstance(BindingHandle,
1464 DeviceIdBuffer,
1465 MAX_DEVICE_ID_LEN);
1466 if (ret != CR_SUCCESS)
1467 return CR_FAILURE;
1468 }
1469 TRACE("DeviceIdBuffer: %s\n", debugstr_w(DeviceIdBuffer));
1470
1471 /* Validate the device ID */
1472 ret = PNP_ValidateDeviceInstance(BindingHandle,
1473 DeviceIdBuffer,
1474 ulFlags);
1475 if (ret == CR_SUCCESS)
1476 {
1477 *pdnDevInst = StringTableAddString(StringTable, DeviceIdBuffer, 1);
1478 if (*pdnDevInst == -1)
1479 ret = CR_FAILURE;
1480 }
1481
1482 return ret;
1483 }
1484
1485
1486 /***********************************************************************
1487 * CM_Open_Class_KeyA [SETUPAPI.@]
1488 */
1489 CONFIGRET WINAPI CM_Open_Class_KeyA(
1490 LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
1491 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
1492 {
1493 TRACE("%p %s %lx %lx %p %lx\n",
1494 debugstr_guid(pClassGuid), pszClassName,
1495 samDesired, Disposition, phkClass, ulFlags);
1496
1497 return CM_Open_Class_Key_ExA(pClassGuid, pszClassName, samDesired,
1498 Disposition, phkClass, ulFlags, NULL);
1499 }
1500
1501
1502 /***********************************************************************
1503 * CM_Open_Class_KeyW [SETUPAPI.@]
1504 */
1505 CONFIGRET WINAPI CM_Open_Class_KeyW(
1506 LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
1507 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
1508 {
1509 TRACE("%p %s %lx %lx %p %lx\n",
1510 debugstr_guid(pClassGuid), debugstr_w(pszClassName),
1511 samDesired, Disposition, phkClass, ulFlags);
1512
1513 return CM_Open_Class_Key_ExW(pClassGuid, pszClassName, samDesired,
1514 Disposition, phkClass, ulFlags, NULL);
1515 }
1516
1517
1518 /***********************************************************************
1519 * CM_Open_Class_Key_ExA [SETUPAPI.@]
1520 */
1521 CONFIGRET WINAPI CM_Open_Class_Key_ExA(
1522 LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
1523 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
1524 HMACHINE hMachine)
1525 {
1526 CONFIGRET rc = CR_SUCCESS;
1527 LPWSTR pszClassNameW = NULL;
1528
1529 TRACE("%p %s %lx %lx %p %lx %lx\n",
1530 debugstr_guid(pClassGuid), pszClassName,
1531 samDesired, Disposition, phkClass, ulFlags, hMachine);
1532
1533 if (pszClassName != NULL)
1534 {
1535 if (CaptureAndConvertAnsiArg(pszClassName, &pszClassNameW))
1536 return CR_INVALID_DATA;
1537 }
1538
1539 rc = CM_Open_Class_Key_ExW(pClassGuid, pszClassNameW, samDesired,
1540 Disposition, phkClass, ulFlags, hMachine);
1541
1542 if (pszClassNameW != NULL)
1543 MyFree(pszClassNameW);
1544
1545 return CR_SUCCESS;
1546 }
1547
1548
1549 /***********************************************************************
1550 * CM_Open_Class_Key_ExW [SETUPAPI.@]
1551 */
1552 CONFIGRET WINAPI CM_Open_Class_Key_ExW(
1553 LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
1554 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
1555 HMACHINE hMachine)
1556 {
1557 WCHAR szKeyName[MAX_PATH];
1558 LPWSTR lpGuidString;
1559 DWORD dwDisposition;
1560 DWORD dwError;
1561 HKEY hKey;
1562
1563 TRACE("%p %s %lx %lx %p %lx %lx\n",
1564 debugstr_guid(pClassGuid), debugstr_w(pszClassName),
1565 samDesired, Disposition, phkClass, ulFlags, hMachine);
1566
1567 /* Check Disposition and ulFlags */
1568 if ((Disposition & ~RegDisposition_Bits) ||
1569 (ulFlags & ~CM_OPEN_CLASS_KEY_BITS))
1570 return CR_INVALID_FLAG;
1571
1572 /* Check phkClass */
1573 if (phkClass == NULL)
1574 return CR_INVALID_POINTER;
1575
1576 *phkClass = NULL;
1577
1578 if (ulFlags == CM_OPEN_CLASS_KEY_INTERFACE &&
1579 pszClassName != NULL)
1580 return CR_INVALID_DATA;
1581
1582 if (hMachine == NULL)
1583 {
1584 hKey = HKEY_LOCAL_MACHINE;
1585 }
1586 else
1587 {
1588 if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
1589 HKEY_LOCAL_MACHINE, &hKey))
1590 return CR_REGISTRY_ERROR;
1591 }
1592
1593 if (ulFlags & CM_OPEN_CLASS_KEY_INTERFACE)
1594 {
1595 lstrcpyW(szKeyName, DeviceClasses);
1596 }
1597 else
1598 {
1599 lstrcpyW(szKeyName, ControlClass);
1600 }
1601
1602 if (pClassGuid != NULL)
1603 {
1604 if (UuidToStringW((UUID*)pClassGuid, &lpGuidString) != RPC_S_OK)
1605 {
1606 RegCloseKey(hKey);
1607 return CR_INVALID_DATA;
1608 }
1609
1610 lstrcatW(szKeyName, Backslash);
1611 lstrcatW(szKeyName, lpGuidString);
1612 }
1613
1614 if (Disposition == RegDisposition_OpenAlways)
1615 {
1616 dwError = RegCreateKeyExW(hKey, szKeyName, 0, NULL, 0, samDesired,
1617 NULL, phkClass, &dwDisposition);
1618 }
1619 else
1620 {
1621 dwError = RegOpenKeyExW(hKey, szKeyName, 0, samDesired, phkClass);
1622 }
1623
1624 RegCloseKey(hKey);
1625
1626 if (pClassGuid != NULL)
1627 RpcStringFreeW(&lpGuidString);
1628
1629 if (dwError != ERROR_SUCCESS)
1630 {
1631 *phkClass = NULL;
1632 return CR_NO_SUCH_REGISTRY_KEY;
1633 }
1634
1635 if (pszClassName != NULL)
1636 {
1637 RegSetValueExW(*phkClass, Class, 0, REG_SZ, (LPBYTE)pszClassName,
1638 (lstrlenW(pszClassName) + 1) * sizeof(WCHAR));
1639 }
1640
1641 return CR_SUCCESS;
1642 }
1643
1644
1645 /***********************************************************************
1646 * CM_Set_DevNode_Problem [SETUPAPI.@]
1647 */
1648 CONFIGRET WINAPI CM_Set_DevNode_Problem(
1649 DEVINST dnDevInst, ULONG ulProblem, ULONG ulFlags)
1650 {
1651 TRACE("%lx %lx %lx\n", dnDevInst, ulProblem, ulFlags);
1652 return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
1653 }
1654
1655
1656 /***********************************************************************
1657 * CM_Set_DevNode_Problem_Ex [SETUPAPI.@]
1658 */
1659 CONFIGRET WINAPI CM_Set_DevNode_Problem_Ex(
1660 DEVINST dnDevInst, ULONG ulProblem, ULONG ulFlags, HMACHINE hMachine)
1661 {
1662 RPC_BINDING_HANDLE BindingHandle = NULL;
1663 HSTRING_TABLE StringTable = NULL;
1664 LPWSTR lpDevInst;
1665
1666 TRACE("%lx %lx %lx %lx\n", dnDevInst, ulProblem, ulFlags, hMachine);
1667
1668 if (dnDevInst == 0)
1669 return CR_INVALID_DEVNODE;
1670
1671 if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
1672 return CR_INVALID_FLAG;
1673
1674 if (hMachine != NULL)
1675 {
1676 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1677 if (BindingHandle == NULL)
1678 return CR_FAILURE;
1679
1680 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1681 if (StringTable == 0)
1682 return CR_FAILURE;
1683 }
1684 else
1685 {
1686 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1687 return CR_FAILURE;
1688 }
1689
1690 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1691 if (lpDevInst == NULL)
1692 return CR_INVALID_DEVNODE;
1693
1694 return PNP_SetDeviceProblem(BindingHandle,
1695 lpDevInst,
1696 ulProblem,
1697 ulFlags);
1698 }
1699
1700
1701 /***********************************************************************
1702 * CM_Set_DevNode_Registry_PropertyA [SETUPAPI.@]
1703 */
1704 CONFIGRET WINAPI CM_Set_DevNode_Registry_PropertyA(
1705 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1706 ULONG ulFlags)
1707 {
1708 TRACE("%lx %lu %p %lx %lx\n",
1709 dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
1710 return CM_Set_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
1711 Buffer, ulLength,
1712 ulFlags, NULL);
1713 }
1714
1715
1716 /***********************************************************************
1717 * CM_Set_DevNode_Registry_PropertyW [SETUPAPI.@]
1718 */
1719 CONFIGRET WINAPI CM_Set_DevNode_Registry_PropertyW(
1720 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1721 ULONG ulFlags)
1722 {
1723 TRACE("%lx %lu %p %lx %lx\n",
1724 dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
1725 return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
1726 Buffer, ulLength,
1727 ulFlags, NULL);
1728 }
1729
1730
1731 /***********************************************************************
1732 * CM_Set_DevNode_Registry_Property_ExA [SETUPAPI.@]
1733 */
1734 CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExA(
1735 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1736 ULONG ulFlags, HMACHINE hMachine)
1737 {
1738 CONFIGRET ret = CR_SUCCESS;
1739 LPWSTR lpBuffer;
1740 ULONG ulType;
1741
1742 FIXME("%lx %lu %p %lx %lx %lx\n",
1743 dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
1744
1745 if (Buffer == NULL && ulLength != 0)
1746 return CR_INVALID_POINTER;
1747
1748 if (Buffer == NULL)
1749 {
1750 ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
1751 ulProperty,
1752 NULL,
1753 0,
1754 ulFlags,
1755 hMachine);
1756 }
1757 else
1758 {
1759 /* Get property type */
1760 switch (ulProperty)
1761 {
1762 case CM_DRP_DEVICEDESC:
1763 ulType = REG_SZ;
1764 break;
1765
1766 case CM_DRP_HARDWAREID:
1767 ulType = REG_MULTI_SZ;
1768 break;
1769
1770 case CM_DRP_COMPATIBLEIDS:
1771 ulType = REG_MULTI_SZ;
1772 break;
1773
1774 case CM_DRP_SERVICE:
1775 ulType = REG_SZ;
1776 break;
1777
1778 case CM_DRP_CLASS:
1779 ulType = REG_SZ;
1780 break;
1781
1782 case CM_DRP_CLASSGUID:
1783 ulType = REG_SZ;
1784 break;
1785
1786 case CM_DRP_DRIVER:
1787 ulType = REG_SZ;
1788 break;
1789
1790 case CM_DRP_CONFIGFLAGS:
1791 ulType = REG_DWORD;
1792 break;
1793
1794 case CM_DRP_MFG:
1795 ulType = REG_SZ;
1796 break;
1797
1798 case CM_DRP_FRIENDLYNAME:
1799 ulType = REG_SZ;
1800 break;
1801
1802 case CM_DRP_LOCATION_INFORMATION:
1803 ulType = REG_SZ;
1804 break;
1805
1806 case CM_DRP_UPPERFILTERS:
1807 ulType = REG_MULTI_SZ;
1808 break;
1809
1810 case CM_DRP_LOWERFILTERS:
1811 ulType = REG_MULTI_SZ;
1812 break;
1813
1814 default:
1815 return CR_INVALID_PROPERTY;
1816 }
1817
1818 /* Allocate buffer if needed */
1819 if (ulType == REG_SZ ||
1820 ulType == REG_MULTI_SZ)
1821 {
1822 lpBuffer = MyMalloc(ulLength * sizeof(WCHAR));
1823 if (lpBuffer == NULL)
1824 {
1825 ret = CR_OUT_OF_MEMORY;
1826 }
1827 else
1828 {
1829 if (!MultiByteToWideChar(CP_ACP, 0, Buffer,
1830 ulLength, lpBuffer, ulLength))
1831 {
1832 MyFree(lpBuffer);
1833 ret = CR_FAILURE;
1834 }
1835 else
1836 {
1837 ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
1838 ulProperty,
1839 lpBuffer,
1840 ulLength * sizeof(WCHAR),
1841 ulFlags,
1842 hMachine);
1843 MyFree(lpBuffer);
1844 }
1845 }
1846 }
1847 else
1848 {
1849 ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
1850 ulProperty,
1851 Buffer,
1852 ulLength,
1853 ulFlags,
1854 hMachine);
1855 }
1856
1857 ret = CR_CALL_NOT_IMPLEMENTED;
1858 }
1859
1860 return ret;
1861 }
1862
1863
1864 /***********************************************************************
1865 * CM_Set_DevNode_Registry_Property_ExW [SETUPAPI.@]
1866 */
1867 CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExW(
1868 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1869 ULONG ulFlags, HMACHINE hMachine)
1870 {
1871 RPC_BINDING_HANDLE BindingHandle = NULL;
1872 HSTRING_TABLE StringTable = NULL;
1873 LPWSTR lpDevInst;
1874 ULONG ulType;
1875
1876 TRACE("%lx %lu %p %lx %lx %lx\n",
1877 dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
1878
1879 if (dnDevInst == 0)
1880 return CR_INVALID_DEVNODE;
1881
1882 if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
1883 return CR_INVALID_PROPERTY;
1884
1885 if (Buffer != NULL && ulLength == 0)
1886 return CR_INVALID_POINTER;
1887
1888 if (ulFlags != 0)
1889 return CR_INVALID_FLAG;
1890
1891 if (hMachine != NULL)
1892 {
1893 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1894 if (BindingHandle == NULL)
1895 return CR_FAILURE;
1896
1897 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1898 if (StringTable == 0)
1899 return CR_FAILURE;
1900 }
1901 else
1902 {
1903 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1904 return CR_FAILURE;
1905 }
1906
1907 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1908 if (lpDevInst == NULL)
1909 return CR_INVALID_DEVNODE;
1910
1911 switch (ulProperty)
1912 {
1913 case CM_DRP_DEVICEDESC:
1914 ulType = REG_SZ;
1915 break;
1916
1917 case CM_DRP_HARDWAREID:
1918 ulType = REG_MULTI_SZ;
1919 break;
1920
1921 case CM_DRP_COMPATIBLEIDS:
1922 ulType = REG_MULTI_SZ;
1923 break;
1924
1925 case CM_DRP_SERVICE:
1926 ulType = REG_SZ;
1927 break;
1928
1929 case CM_DRP_CLASS:
1930 ulType = REG_SZ;
1931 break;
1932
1933 case CM_DRP_CLASSGUID:
1934 ulType = REG_SZ;
1935 break;
1936
1937 case CM_DRP_DRIVER:
1938 ulType = REG_SZ;
1939 break;
1940
1941 case CM_DRP_CONFIGFLAGS:
1942 ulType = REG_DWORD;
1943 break;
1944
1945 case CM_DRP_MFG:
1946 ulType = REG_SZ;
1947 break;
1948
1949 case CM_DRP_FRIENDLYNAME:
1950 ulType = REG_SZ;
1951 break;
1952
1953 case CM_DRP_LOCATION_INFORMATION:
1954 ulType = REG_SZ;
1955 break;
1956
1957 case CM_DRP_UPPERFILTERS:
1958 ulType = REG_MULTI_SZ;
1959 break;
1960
1961 case CM_DRP_LOWERFILTERS:
1962 ulType = REG_MULTI_SZ;
1963 break;
1964
1965 default:
1966 return CR_INVALID_PROPERTY;
1967 }
1968
1969 return PNP_SetDeviceRegProp(BindingHandle,
1970 lpDevInst,
1971 ulProperty,
1972 ulType,
1973 (char *)Buffer,
1974 ulLength,
1975 ulFlags);
1976 }