Fix GUID->String conversion.
[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 FIXME("%p %p %p %lx %lx\n",
361 ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
362 return CR_FAILURE;
363 }
364
365
366 static BOOL GuidToString(LPGUID Guid, LPWSTR String)
367 {
368 LPWSTR lpString;
369
370 if (UuidToStringW(Guid, &lpString) != RPC_S_OK)
371 return FALSE;
372
373 lstrcpyW(String, lpString);
374
375 RpcStringFree(&lpString);
376
377 return TRUE;
378 }
379
380
381 /***********************************************************************
382 * CM_Get_Class_Key_Name_ExW [SETUPAPI.@]
383 */
384 CONFIGRET WINAPI CM_Get_Class_Key_Name_ExW(
385 LPGUID ClassGuid, LPWSTR pszKeyName, PULONG pulLength, ULONG ulFlags,
386 HMACHINE hMachine)
387 {
388 TRACE("%p %p %p %lx %lx\n",
389 ClassGuid, pszKeyName, pulLength, ulFlags, hMachine);
390
391 if (ClassGuid == NULL || pszKeyName == NULL || pulLength == NULL)
392 return CR_INVALID_POINTER;
393
394 if (ulFlags != 0)
395 return CR_INVALID_FLAG;
396
397 if (*pulLength < MAX_GUID_STRING_LEN)
398 {
399 *pulLength = 0;
400 return CR_BUFFER_SMALL;
401 }
402
403 if (!GuidToString(ClassGuid, pszKeyName))
404 return CR_INVALID_DATA;
405
406 *pulLength = MAX_GUID_STRING_LEN;
407
408 return CR_SUCCESS;
409 }
410
411
412 /***********************************************************************
413 * CM_Get_Class_NameA [SETUPAPI.@]
414 */
415 CONFIGRET WINAPI CM_Get_Class_NameA(
416 LPGUID ClassGuid, PCHAR Buffer, PULONG pulLength, ULONG ulFlags)
417 {
418 TRACE("%p %p %p %lx\n", ClassGuid, Buffer, pulLength, ulFlags);
419 return CM_Get_Class_Name_ExA(ClassGuid, Buffer, pulLength, ulFlags,
420 NULL);
421 }
422
423
424 /***********************************************************************
425 * CM_Get_Class_NameW [SETUPAPI.@]
426 */
427 CONFIGRET WINAPI CM_Get_Class_NameW(
428 LPGUID ClassGuid, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags)
429 {
430 TRACE("%p %p %p %lx\n", ClassGuid, Buffer, pulLength, ulFlags);
431 return CM_Get_Class_Name_ExW(ClassGuid, Buffer, pulLength, ulFlags,
432 NULL);
433 }
434
435
436 /***********************************************************************
437 * CM_Get_Class_Name_ExA [SETUPAPI.@]
438 */
439 CONFIGRET WINAPI CM_Get_Class_Name_ExA(
440 LPGUID ClassGuid, PCHAR Buffer, PULONG pulLength, ULONG ulFlags,
441 HMACHINE hMachine)
442 {
443 FIXME("%p %p %p %lx %lx\n",
444 ClassGuid, Buffer, pulLength, ulFlags, hMachine);
445 return CR_FAILURE;
446 }
447
448
449 /***********************************************************************
450 * CM_Get_Class_Name_ExW [SETUPAPI.@]
451 */
452 CONFIGRET WINAPI
453 CM_Get_Class_Name_ExW(
454 LPGUID ClassGuid, PWCHAR Buffer, PULONG pulLength, ULONG ulFlags,
455 HMACHINE hMachine)
456 {
457 WCHAR szGuidString[MAX_GUID_STRING_LEN];
458 RPC_BINDING_HANDLE BindingHandle = NULL;
459
460 TRACE("%p %p %p %lx %lx\n",
461 ClassGuid, Buffer, pulLength, ulFlags, hMachine);
462
463 if (ClassGuid == NULL || Buffer == NULL || pulLength == NULL)
464 return CR_INVALID_POINTER;
465
466 if (ulFlags != 0)
467 return CR_INVALID_FLAG;
468
469 if (!GuidToString(ClassGuid, szGuidString))
470 return CR_INVALID_DATA;
471
472 TRACE("Guid %s\n", debugstr_w(szGuidString));
473
474 if (hMachine != NULL)
475 {
476 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
477 if (BindingHandle == NULL)
478 return CR_FAILURE;
479 }
480 else
481 {
482 if (!PnpGetLocalHandles(&BindingHandle, NULL))
483 return CR_FAILURE;
484 }
485
486 return PNP_GetClassName(BindingHandle,
487 szGuidString,
488 Buffer,
489 pulLength,
490 ulFlags);
491 }
492
493
494 /***********************************************************************
495 * CM_Get_Depth [SETUPAPI.@]
496 */
497 CONFIGRET WINAPI CM_Get_Depth(
498 PULONG pulDepth, DEVINST dnDevInst, ULONG ulFlags)
499 {
500 TRACE("%p %lx %lx\n", pulDepth, dnDevInst, ulFlags);
501 return CM_Get_Depth_Ex(pulDepth, dnDevInst, ulFlags, NULL);
502 }
503
504
505 /***********************************************************************
506 * CM_Get_Depth_Ex [SETUPAPI.@]
507 */
508 CONFIGRET WINAPI CM_Get_Depth_Ex(
509 PULONG pulDepth, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
510 {
511 RPC_BINDING_HANDLE BindingHandle = NULL;
512 HSTRING_TABLE StringTable = NULL;
513 LPWSTR lpDevInst;
514
515 TRACE("%p %lx %lx %lx\n",
516 pulDepth, dnDevInst, ulFlags, hMachine);
517
518 if (pulDepth == NULL)
519 return CR_INVALID_POINTER;
520
521 if (dnDevInst == 0)
522 return CR_INVALID_DEVINST;
523
524 if (ulFlags != 0)
525 return CR_INVALID_FLAG;
526
527 if (hMachine != NULL)
528 {
529 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
530 if (BindingHandle == NULL)
531 return CR_FAILURE;
532
533 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
534 if (StringTable == 0)
535 return CR_FAILURE;
536 }
537 else
538 {
539 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
540 return CR_FAILURE;
541 }
542
543 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
544 if (lpDevInst == NULL)
545 return CR_INVALID_DEVNODE;
546
547 return PNP_GetDepth(BindingHandle,
548 lpDevInst,
549 pulDepth,
550 ulFlags);
551 }
552
553
554 /***********************************************************************
555 * CM_Get_DevNode_Registry_PropertyA [SETUPAPI.@]
556 */
557 CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyA(
558 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
559 PVOID Buffer, PULONG pulLength, ULONG ulFlags)
560 {
561 TRACE("%lx %lu %p %p %p %lx\n",
562 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
563
564 return CM_Get_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
565 pulRegDataType, Buffer,
566 pulLength, ulFlags, NULL);
567 }
568
569
570 /***********************************************************************
571 * CM_Get_DevNode_Registry_PropertyW [SETUPAPI.@]
572 */
573 CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyW(
574 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
575 PVOID Buffer, PULONG pulLength, ULONG ulFlags)
576 {
577 TRACE("%lx %lu %p %p %p %lx\n",
578 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength, ulFlags);
579
580 return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
581 pulRegDataType, Buffer,
582 pulLength, ulFlags, NULL);
583 }
584
585
586 /***********************************************************************
587 * CM_Get_DevNode_Registry_Property_ExA [SETUPAPI.@]
588 */
589 CONFIGRET WINAPI CM_Get_DevNode_Registry_Property_ExA(
590 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
591 PVOID Buffer, PULONG pulLength, ULONG ulFlags, HMACHINE hMachine)
592 {
593 FIXME("%lx %lu %p %p %p %lx %lx\n",
594 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
595 ulFlags, hMachine);
596
597 return CR_CALL_NOT_IMPLEMENTED;
598 }
599
600
601 /***********************************************************************
602 * CM_Get_DevNode_Registry_Property_ExW [SETUPAPI.@]
603 */
604 CONFIGRET WINAPI CM_Get_DevNode_Registry_Property_ExW(
605 DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType,
606 PVOID Buffer, PULONG pulLength, ULONG ulFlags, HMACHINE hMachine)
607 {
608 RPC_BINDING_HANDLE BindingHandle = NULL;
609 HSTRING_TABLE StringTable = NULL;
610 CONFIGRET ret = CR_SUCCESS;
611 LPWSTR lpDevInst;
612 ULONG ulDataType = 0;
613 ULONG ulTransferLength = 0;
614
615 FIXME("%lx %lu %p %p %p %lx %lx\n",
616 dnDevInst, ulProperty, pulRegDataType, Buffer, pulLength,
617 ulFlags, hMachine);
618
619 if (dnDevInst == 0)
620 return CR_INVALID_DEVNODE;
621
622 if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
623 return CR_INVALID_PROPERTY;
624
625 /* pulRegDataType is optional */
626
627 /* Buffer is optional */
628
629 if (pulLength == NULL)
630 return CR_INVALID_POINTER;
631
632 if (*pulLength == 0)
633 return CR_INVALID_POINTER;
634
635 if (ulFlags != 0)
636 return CR_INVALID_FLAG;
637
638 if (hMachine != NULL)
639 {
640 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
641 if (BindingHandle == NULL)
642 return CR_FAILURE;
643
644 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
645 if (StringTable == 0)
646 return CR_FAILURE;
647 }
648 else
649 {
650 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
651 return CR_FAILURE;
652 }
653
654 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
655 if (lpDevInst == NULL)
656 return CR_INVALID_DEVNODE;
657
658 ulTransferLength = *pulLength;
659 ret = PNP_GetDeviceRegProp(BindingHandle,
660 lpDevInst,
661 ulProperty,
662 &ulDataType,
663 Buffer,
664 &ulTransferLength,
665 pulLength,
666 ulFlags);
667 if (ret == CR_SUCCESS)
668 {
669 if (pulRegDataType != NULL)
670 *pulRegDataType = ulDataType;
671 }
672
673 return ret;
674 }
675
676
677 /***********************************************************************
678 * CM_Get_DevNode_Status [SETUPAPI.@]
679 */
680 CONFIGRET WINAPI CM_Get_DevNode_Status(
681 PULONG pulStatus, PULONG pulProblemNumber, DEVINST dnDevInst,
682 ULONG ulFlags)
683 {
684 TRACE("%p %p %lx %lx\n",
685 pulStatus, pulProblemNumber, dnDevInst, ulFlags);
686 return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber, dnDevInst,
687 ulFlags, NULL);
688 }
689
690
691 /***********************************************************************
692 * CM_Get_DevNode_Status_Ex [SETUPAPI.@]
693 */
694 CONFIGRET WINAPI
695 CM_Get_DevNode_Status_Ex(
696 PULONG pulStatus, PULONG pulProblemNumber, DEVINST dnDevInst,
697 ULONG ulFlags, HMACHINE hMachine)
698 {
699 RPC_BINDING_HANDLE BindingHandle = NULL;
700 HSTRING_TABLE StringTable = NULL;
701 LPWSTR lpDevInst;
702
703 TRACE("%p %p %lx %lx %lx\n",
704 pulStatus, pulProblemNumber, dnDevInst, ulFlags, hMachine);
705
706 if (pulStatus == NULL || pulProblemNumber == NULL)
707 return CR_INVALID_POINTER;
708
709 if (dnDevInst == 0)
710 return CR_INVALID_DEVINST;
711
712 if (ulFlags != 0)
713 return CR_INVALID_FLAG;
714
715 if (hMachine != NULL)
716 {
717 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
718 if (BindingHandle == NULL)
719 return CR_FAILURE;
720
721 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
722 if (StringTable == 0)
723 return CR_FAILURE;
724 }
725 else
726 {
727 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
728 return CR_FAILURE;
729 }
730
731 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
732 if (lpDevInst == NULL)
733 return CR_INVALID_DEVNODE;
734
735 return PNP_GetDeviceStatus(BindingHandle,
736 lpDevInst,
737 pulStatus,
738 pulProblemNumber,
739 ulFlags);
740 }
741
742
743 /***********************************************************************
744 * CM_Get_Device_IDA [SETUPAPI.@]
745 */
746 CONFIGRET WINAPI CM_Get_Device_IDA(
747 DEVINST dnDevInst, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
748 {
749 TRACE("%lx %p %ld %ld\n",
750 dnDevInst, Buffer, BufferLen, ulFlags);
751 return CM_Get_Device_ID_ExA(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
752 }
753
754
755 /***********************************************************************
756 * CM_Get_Device_IDW [SETUPAPI.@]
757 */
758 CONFIGRET WINAPI CM_Get_Device_IDW(
759 DEVINST dnDevInst, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
760 {
761 TRACE("%lx %p %ld %ld\n",
762 dnDevInst, Buffer, BufferLen, ulFlags);
763 return CM_Get_Device_ID_ExW(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
764 }
765
766
767 /***********************************************************************
768 * CM_Get_Device_ID_ExA [SETUPAPI.@]
769 */
770 CONFIGRET WINAPI CM_Get_Device_ID_ExA(
771 DEVINST dnDevInst, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
772 HMACHINE hMachine)
773 {
774 WCHAR szBufferW[MAX_DEVICE_ID_LEN];
775 CONFIGRET ret = CR_SUCCESS;
776
777 FIXME("%lx %p %ld %ld %lx\n",
778 dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
779
780 if (Buffer == NULL)
781 return CR_INVALID_POINTER;
782
783 ret = CM_Get_Device_ID_ExW(dnDevInst,
784 szBufferW,
785 MAX_DEVICE_ID_LEN,
786 ulFlags,
787 hMachine);
788 if (ret == CR_SUCCESS)
789 {
790 if (WideCharToMultiByte(CP_ACP,
791 0,
792 szBufferW,
793 lstrlenW(szBufferW) + 1,
794 Buffer,
795 BufferLen,
796 NULL,
797 NULL) == 0)
798 ret = CR_FAILURE;
799 }
800
801 return ret;
802 }
803
804
805 /***********************************************************************
806 * CM_Get_Device_ID_ExW [SETUPAPI.@]
807 */
808 CONFIGRET WINAPI CM_Get_Device_ID_ExW(
809 DEVINST dnDevInst, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
810 HMACHINE hMachine)
811 {
812 HSTRING_TABLE StringTable = NULL;
813
814 TRACE("%lx %p %ld %ld %lx\n",
815 dnDevInst, Buffer, BufferLen, ulFlags, hMachine);
816
817 if (dnDevInst == 0)
818 return CR_INVALID_DEVINST;
819
820 if (Buffer == NULL)
821 return CR_INVALID_POINTER;
822
823 if (ulFlags != 0)
824 return CR_INVALID_FLAG;
825
826 if (hMachine != NULL)
827 {
828 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
829 if (StringTable == NULL)
830 return CR_FAILURE;
831 }
832 else
833 {
834 if (!PnpGetLocalHandles(NULL, &StringTable))
835 return CR_FAILURE;
836 }
837
838 if (!StringTableStringFromIdEx(StringTable,
839 dnDevInst,
840 Buffer,
841 &BufferLen))
842 return CR_FAILURE;
843
844 return CR_SUCCESS;
845 }
846
847
848 /***********************************************************************
849 * CM_Get_Device_ID_ListA [SETUPAPI.@]
850 */
851 CONFIGRET WINAPI CM_Get_Device_ID_ListA(
852 PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
853 {
854 TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags);
855 return CM_Get_Device_ID_List_ExA(pszFilter, Buffer, BufferLen,
856 ulFlags, NULL);
857 }
858
859
860 /***********************************************************************
861 * CM_Get_Device_ID_ListW [SETUPAPI.@]
862 */
863 CONFIGRET WINAPI CM_Get_Device_ID_ListW(
864 PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags)
865 {
866 TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags);
867 return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen,
868 ulFlags, NULL);
869 }
870
871
872 /***********************************************************************
873 * CM_Get_Device_ID_List_ExA [SETUPAPI.@]
874 */
875 CONFIGRET WINAPI CM_Get_Device_ID_List_ExA(
876 PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
877 HMACHINE hMachine)
878 {
879 LPWSTR BufferW = NULL;
880 LPWSTR pszFilterW = NULL;
881 CONFIGRET ret = CR_SUCCESS;
882
883 FIXME("%p %p %ld %ld %lx\n",
884 pszFilter, Buffer, BufferLen, ulFlags, hMachine);
885
886 BufferW = MyMalloc(BufferLen * sizeof(WCHAR));
887 if (BufferW == NULL)
888 return CR_OUT_OF_MEMORY;
889
890 if (pszFilter == NULL)
891 {
892 ret = CM_Get_Device_ID_List_ExW(NULL,
893 BufferW,
894 BufferLen,
895 ulFlags,
896 hMachine);
897 }
898 else
899 {
900 if (CaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
901 {
902 ret = CR_INVALID_DEVICE_ID;
903 goto Done;
904 }
905
906 ret = CM_Get_Device_ID_List_ExW(pszFilterW,
907 BufferW,
908 BufferLen,
909 ulFlags,
910 hMachine);
911
912 MyFree(pszFilterW);
913 }
914
915 if (WideCharToMultiByte(CP_ACP,
916 0,
917 BufferW,
918 lstrlenW(BufferW) + 1,
919 Buffer,
920 BufferLen,
921 NULL,
922 NULL) == 0)
923 ret = CR_FAILURE;
924
925 Done:
926 MyFree(BufferW);
927
928 return ret;
929 }
930
931
932 /***********************************************************************
933 * CM_Get_Device_ID_List_ExW [SETUPAPI.@]
934 */
935 CONFIGRET WINAPI CM_Get_Device_ID_List_ExW(
936 PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags,
937 HMACHINE hMachine)
938 {
939 FIXME("%p %p %ld %ld %lx\n",
940 pszFilter, Buffer, BufferLen, ulFlags, hMachine);
941 memset(Buffer,0,2);
942 return CR_SUCCESS;
943 }
944
945
946 /***********************************************************************
947 * CM_Get_Device_ID_List_SizeA [SETUPAPI.@]
948 */
949 CONFIGRET WINAPI CM_Get_Device_ID_List_SizeA(
950 PULONG pulLen, PCSTR pszFilter, ULONG ulFlags)
951 {
952 TRACE("%p %s %ld\n", pulLen, pszFilter, ulFlags);
953 return CM_Get_Device_ID_List_Size_ExA(pulLen, pszFilter, ulFlags, NULL);
954 }
955
956
957 /***********************************************************************
958 * CM_Get_Device_ID_List_SizeW [SETUPAPI.@]
959 */
960 CONFIGRET WINAPI CM_Get_Device_ID_List_SizeW(
961 PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags)
962 {
963 TRACE("%p %s %ld\n", pulLen, debugstr_w(pszFilter), ulFlags);
964 return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL);
965 }
966
967
968 /***********************************************************************
969 * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@]
970 */
971 CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExA(
972 PULONG pulLen, PCSTR pszFilter, ULONG ulFlags, HMACHINE hMachine)
973 {
974 LPWSTR pszFilterW = NULL;
975 CONFIGRET ret = CR_SUCCESS;
976
977 FIXME("%p %s %lx %lx\n", pulLen, pszFilter, ulFlags, hMachine);
978
979 if (pszFilter == NULL)
980 {
981 ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
982 NULL,
983 ulFlags,
984 hMachine);
985 }
986 else
987 {
988 if (CaptureAndConvertAnsiArg(pszFilter, &pszFilterW))
989 return CR_INVALID_DEVICE_ID;
990
991 ret = CM_Get_Device_ID_List_Size_ExW(pulLen,
992 pszFilterW,
993 ulFlags,
994 hMachine);
995
996 MyFree(pszFilterW);
997 }
998
999 return ret;
1000 }
1001
1002
1003 /***********************************************************************
1004 * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@]
1005 */
1006 CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExW(
1007 PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags, HMACHINE hMachine)
1008 {
1009 FIXME("%p %s %ld %lx\n", pulLen, debugstr_w(pszFilter), ulFlags, hMachine);
1010 *pulLen = 2;
1011 return CR_SUCCESS;
1012 }
1013
1014
1015 /***********************************************************************
1016 * CM_Get_Device_ID_Size [SETUPAPI.@]
1017 */
1018 CONFIGRET WINAPI CM_Get_Device_ID_Size(
1019 PULONG pulLen, DEVINST dnDevInst, ULONG ulFlags)
1020 {
1021 TRACE("%p %lx %lx\n", pulLen, dnDevInst, ulFlags);
1022 return CM_Get_Device_ID_Size_Ex(pulLen, dnDevInst, ulFlags, NULL);
1023 }
1024
1025
1026 /***********************************************************************
1027 * CM_Get_Device_ID_Size_Ex [SETUPAPI.@]
1028 */
1029 CONFIGRET WINAPI CM_Get_Device_ID_Size_Ex(
1030 PULONG pulLen, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
1031 {
1032 HSTRING_TABLE StringTable = NULL;
1033 LPWSTR DeviceId;
1034
1035 TRACE("%p %lx %lx %lx\n", pulLen, dnDevInst, ulFlags, hMachine);
1036
1037 if (pulLen == NULL)
1038 return CR_INVALID_POINTER;
1039
1040 if (dnDevInst == 0)
1041 return CR_INVALID_DEVINST;
1042
1043 if (ulFlags != 0)
1044 return CR_INVALID_FLAG;
1045
1046 if (hMachine != NULL)
1047 {
1048 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1049 if (StringTable == NULL)
1050 return CR_FAILURE;
1051 }
1052 else
1053 {
1054 if (!PnpGetLocalHandles(NULL, &StringTable))
1055 return CR_FAILURE;
1056 }
1057
1058 DeviceId = StringTableStringFromId(StringTable, dnDevInst);
1059 if (DeviceId == NULL)
1060 {
1061 *pulLen = 0;
1062 return CR_SUCCESS;
1063 }
1064
1065 *pulLen = lstrlenW(DeviceId);
1066
1067 return CR_SUCCESS;
1068 }
1069
1070
1071 /***********************************************************************
1072 * CM_Get_Global_State [SETUPAPI.@]
1073 */
1074 CONFIGRET WINAPI CM_Get_Global_State(
1075 PULONG pulState, ULONG ulFlags)
1076 {
1077 TRACE("%p %lx\n", pulState, ulFlags);
1078 return CM_Get_Global_State_Ex(pulState, ulFlags, NULL);
1079 }
1080
1081
1082 /***********************************************************************
1083 * CM_Get_Global_State_Ex [SETUPAPI.@]
1084 */
1085 CONFIGRET WINAPI CM_Get_Global_State_Ex(
1086 PULONG pulState, ULONG ulFlags, HMACHINE hMachine)
1087 {
1088 RPC_BINDING_HANDLE BindingHandle = NULL;
1089
1090 TRACE("%p %lx %lx\n", pulState, ulFlags, hMachine);
1091
1092 if (pulState == NULL)
1093 return CR_INVALID_POINTER;
1094
1095 if (ulFlags != 0)
1096 return CR_INVALID_FLAG;
1097
1098 if (hMachine != NULL)
1099 {
1100 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1101 if (BindingHandle == NULL)
1102 return CR_FAILURE;
1103 }
1104 else
1105 {
1106 if (!PnpGetLocalHandles(&BindingHandle, NULL))
1107 return CR_FAILURE;
1108 }
1109
1110 return PNP_GetGlobalState(BindingHandle, pulState, ulFlags);
1111 }
1112
1113
1114 /***********************************************************************
1115 * CM_Get_Parent [SETUPAPI.@]
1116 */
1117 CONFIGRET WINAPI CM_Get_Parent(
1118 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
1119 {
1120 TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
1121 return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
1122 }
1123
1124
1125 /***********************************************************************
1126 * CM_Get_Parent_Ex [SETUPAPI.@]
1127 */
1128 CONFIGRET WINAPI CM_Get_Parent_Ex(
1129 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
1130 {
1131 WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
1132 RPC_BINDING_HANDLE BindingHandle = NULL;
1133 HSTRING_TABLE StringTable = NULL;
1134 LPWSTR lpDevInst;
1135 DWORD dwIndex;
1136 CONFIGRET ret;
1137
1138 TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
1139
1140 if (pdnDevInst == NULL)
1141 return CR_INVALID_POINTER;
1142
1143 if (dnDevInst == 0)
1144 return CR_INVALID_DEVINST;
1145
1146 if (ulFlags != 0)
1147 return CR_INVALID_FLAG;
1148
1149 *pdnDevInst = -1;
1150
1151 if (hMachine != NULL)
1152 {
1153 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1154 if (BindingHandle == NULL)
1155 return CR_FAILURE;
1156
1157 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1158 if (StringTable == 0)
1159 return CR_FAILURE;
1160 }
1161 else
1162 {
1163 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1164 return CR_FAILURE;
1165 }
1166
1167 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1168 if (lpDevInst == NULL)
1169 return CR_INVALID_DEVNODE;
1170
1171 ret = PNP_GetRelatedDeviceInstance(BindingHandle,
1172 PNP_DEVICE_PARENT,
1173 lpDevInst,
1174 szRelatedDevInst,
1175 MAX_DEVICE_ID_LEN,
1176 0);
1177 if (ret != CR_SUCCESS)
1178 return ret;
1179
1180 TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
1181
1182 dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
1183 if (dwIndex == -1)
1184 return CR_FAILURE;
1185
1186 *pdnDevInst = dwIndex;
1187
1188 return CR_SUCCESS;
1189 }
1190
1191
1192 /***********************************************************************
1193 * CM_Get_Sibling [SETUPAPI.@]
1194 */
1195 CONFIGRET WINAPI CM_Get_Sibling(
1196 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
1197 {
1198 TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags);
1199 return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
1200 }
1201
1202
1203 /***********************************************************************
1204 * CM_Get_Sibling_Ex [SETUPAPI.@]
1205 */
1206 CONFIGRET WINAPI CM_Get_Sibling_Ex(
1207 PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine)
1208 {
1209 WCHAR szRelatedDevInst[MAX_DEVICE_ID_LEN];
1210 RPC_BINDING_HANDLE BindingHandle = NULL;
1211 HSTRING_TABLE StringTable = NULL;
1212 LPWSTR lpDevInst;
1213 DWORD dwIndex;
1214 CONFIGRET ret;
1215
1216 TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine);
1217
1218 if (pdnDevInst == NULL)
1219 return CR_INVALID_POINTER;
1220
1221 if (dnDevInst == 0)
1222 return CR_INVALID_DEVINST;
1223
1224 if (ulFlags != 0)
1225 return CR_INVALID_FLAG;
1226
1227 *pdnDevInst = -1;
1228
1229 if (hMachine != NULL)
1230 {
1231 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1232 if (BindingHandle == NULL)
1233 return CR_FAILURE;
1234
1235 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1236 if (StringTable == 0)
1237 return CR_FAILURE;
1238 }
1239 else
1240 {
1241 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1242 return CR_FAILURE;
1243 }
1244
1245 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1246 if (lpDevInst == NULL)
1247 return CR_INVALID_DEVNODE;
1248
1249 ret = PNP_GetRelatedDeviceInstance(BindingHandle,
1250 PNP_DEVICE_SIBLING,
1251 lpDevInst,
1252 szRelatedDevInst,
1253 MAX_DEVICE_ID_LEN,
1254 0);
1255 if (ret != CR_SUCCESS)
1256 return ret;
1257
1258 TRACE("szRelatedDevInst: %s\n", debugstr_w(szRelatedDevInst));
1259
1260 dwIndex = StringTableAddString(StringTable, szRelatedDevInst, 1);
1261 if (dwIndex == -1)
1262 return CR_FAILURE;
1263
1264 *pdnDevInst = dwIndex;
1265
1266 return CR_SUCCESS;
1267 }
1268
1269
1270 /***********************************************************************
1271 * CM_Get_Version [SETUPAPI.@]
1272 */
1273 WORD WINAPI CM_Get_Version(VOID)
1274 {
1275 TRACE("\n");
1276 return CM_Get_Version_Ex(NULL);
1277 }
1278
1279
1280 /***********************************************************************
1281 * CM_Get_Version_Ex [SETUPAPI.@]
1282 */
1283 WORD WINAPI CM_Get_Version_Ex(HMACHINE hMachine)
1284 {
1285 RPC_BINDING_HANDLE BindingHandle = NULL;
1286 WORD Version = 0;
1287
1288 TRACE("%lx\n", hMachine);
1289
1290 if (hMachine != NULL)
1291 {
1292 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1293 if (BindingHandle == NULL)
1294 return 0;
1295 }
1296 else
1297 {
1298 if (!PnpGetLocalHandles(&BindingHandle, NULL))
1299 return CR_FAILURE;
1300 }
1301
1302 if (PNP_GetVersion(BindingHandle, &Version) != CR_SUCCESS)
1303 return 0;
1304
1305 return Version;
1306 }
1307
1308
1309 /***********************************************************************
1310 * CM_Locate_DevNodeA [SETUPAPI.@]
1311 */
1312 CONFIGRET WINAPI CM_Locate_DevNodeA(
1313 PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags)
1314 {
1315 TRACE("%p %s %lu\n", pdnDevInst, pDeviceID, ulFlags);
1316 return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
1317 }
1318
1319
1320 /***********************************************************************
1321 * CM_Locate_DevNodeW [SETUPAPI.@]
1322 */
1323 CONFIGRET WINAPI CM_Locate_DevNodeW(
1324 PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags)
1325 {
1326 TRACE("%p %s %lu\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags);
1327 return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
1328 }
1329
1330
1331 /***********************************************************************
1332 * CM_Locate_DevNode_ExA [SETUPAPI.@]
1333 */
1334 CONFIGRET WINAPI CM_Locate_DevNode_ExA(
1335 PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags, HMACHINE hMachine)
1336 {
1337 DEVINSTID_W pDevIdW = NULL;
1338 CONFIGRET ret = CR_SUCCESS;
1339
1340 TRACE("%p %s %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine);
1341
1342 if (pDeviceID != NULL)
1343 {
1344 if (CaptureAndConvertAnsiArg(pDeviceID, &pDevIdW))
1345 return CR_INVALID_DEVICE_ID;
1346 }
1347
1348 ret = CM_Locate_DevNode_ExW(pdnDevInst, pDevIdW, ulFlags, hMachine);
1349
1350 if (pDevIdW != NULL)
1351 MyFree(pDevIdW);
1352
1353 return ret;
1354 }
1355
1356
1357 /***********************************************************************
1358 * CM_Locate_DevNode_ExW [SETUPAPI.@]
1359 */
1360 CONFIGRET WINAPI CM_Locate_DevNode_ExW(
1361 PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags, HMACHINE hMachine)
1362 {
1363 WCHAR DeviceIdBuffer[MAX_DEVICE_ID_LEN];
1364 RPC_BINDING_HANDLE BindingHandle = NULL;
1365 HSTRING_TABLE StringTable = NULL;
1366 CONFIGRET ret = CR_SUCCESS;
1367
1368 TRACE("%p %s %lu %lx\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
1369
1370 if (pdnDevInst == NULL)
1371 return CR_INVALID_POINTER;
1372
1373 if (ulFlags & ~CM_LOCATE_DEVNODE_BITS)
1374 return CR_INVALID_FLAG;
1375
1376 if (hMachine != NULL)
1377 {
1378 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1379 if (BindingHandle == NULL)
1380 return CR_FAILURE;
1381
1382 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1383 if (StringTable == 0)
1384 return CR_FAILURE;
1385 }
1386 else
1387 {
1388 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1389 return CR_FAILURE;
1390 }
1391
1392 if (pDeviceID != NULL && lstrlenW(pDeviceID) != 0)
1393 {
1394 lstrcpyW(DeviceIdBuffer, pDeviceID);
1395 }
1396 else
1397 {
1398 /* Get the root device ID */
1399 ret = PNP_GetRootDeviceInstance(BindingHandle,
1400 DeviceIdBuffer,
1401 MAX_DEVICE_ID_LEN);
1402 if (ret != CR_SUCCESS)
1403 return CR_FAILURE;
1404 }
1405 TRACE("DeviceIdBuffer: %s\n", debugstr_w(DeviceIdBuffer));
1406
1407 /* Validate the device ID */
1408 ret = PNP_ValidateDeviceInstance(BindingHandle,
1409 DeviceIdBuffer,
1410 ulFlags);
1411 if (ret == CR_SUCCESS)
1412 {
1413 *pdnDevInst = StringTableAddString(StringTable, DeviceIdBuffer, 1);
1414 if (*pdnDevInst == -1)
1415 ret = CR_FAILURE;
1416 }
1417
1418 return ret;
1419 }
1420
1421
1422 /***********************************************************************
1423 * CM_Open_Class_KeyA [SETUPAPI.@]
1424 */
1425 CONFIGRET WINAPI CM_Open_Class_KeyA(
1426 LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
1427 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
1428 {
1429 TRACE("%p %s %lx %lx %p %lx\n",
1430 debugstr_guid(pClassGuid), pszClassName,
1431 samDesired, Disposition, phkClass, ulFlags);
1432
1433 return CM_Open_Class_Key_ExA(pClassGuid, pszClassName, samDesired,
1434 Disposition, phkClass, ulFlags, NULL);
1435 }
1436
1437
1438 /***********************************************************************
1439 * CM_Open_Class_KeyW [SETUPAPI.@]
1440 */
1441 CONFIGRET WINAPI CM_Open_Class_KeyW(
1442 LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
1443 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
1444 {
1445 TRACE("%p %s %lx %lx %p %lx\n",
1446 debugstr_guid(pClassGuid), debugstr_w(pszClassName),
1447 samDesired, Disposition, phkClass, ulFlags);
1448
1449 return CM_Open_Class_Key_ExW(pClassGuid, pszClassName, samDesired,
1450 Disposition, phkClass, ulFlags, NULL);
1451 }
1452
1453
1454 /***********************************************************************
1455 * CM_Open_Class_Key_ExA [SETUPAPI.@]
1456 */
1457 CONFIGRET WINAPI CM_Open_Class_Key_ExA(
1458 LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
1459 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
1460 HMACHINE hMachine)
1461 {
1462 CONFIGRET rc = CR_SUCCESS;
1463 LPWSTR pszClassNameW = NULL;
1464
1465 TRACE("%p %s %lx %lx %p %lx %lx\n",
1466 debugstr_guid(pClassGuid), pszClassName,
1467 samDesired, Disposition, phkClass, ulFlags, hMachine);
1468
1469 if (pszClassName != NULL)
1470 {
1471 if (CaptureAndConvertAnsiArg(pszClassName, &pszClassNameW))
1472 return CR_INVALID_DATA;
1473 }
1474
1475 rc = CM_Open_Class_Key_ExW(pClassGuid, pszClassNameW, samDesired,
1476 Disposition, phkClass, ulFlags, hMachine);
1477
1478 if (pszClassNameW != NULL)
1479 MyFree(pszClassNameW);
1480
1481 return CR_SUCCESS;
1482 }
1483
1484
1485 /***********************************************************************
1486 * CM_Open_Class_Key_ExW [SETUPAPI.@]
1487 */
1488 CONFIGRET WINAPI CM_Open_Class_Key_ExW(
1489 LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
1490 REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
1491 HMACHINE hMachine)
1492 {
1493 WCHAR szKeyName[MAX_PATH];
1494 LPWSTR lpGuidString;
1495 DWORD dwDisposition;
1496 DWORD dwError;
1497 HKEY hKey;
1498
1499 TRACE("%p %s %lx %lx %p %lx %lx\n",
1500 debugstr_guid(pClassGuid), debugstr_w(pszClassName),
1501 samDesired, Disposition, phkClass, ulFlags, hMachine);
1502
1503 /* Check Disposition and ulFlags */
1504 if ((Disposition & ~RegDisposition_Bits) ||
1505 (ulFlags & ~CM_OPEN_CLASS_KEY_BITS))
1506 return CR_INVALID_FLAG;
1507
1508 /* Check phkClass */
1509 if (phkClass == NULL)
1510 return CR_INVALID_POINTER;
1511
1512 *phkClass = NULL;
1513
1514 if (ulFlags == CM_OPEN_CLASS_KEY_INTERFACE &&
1515 pszClassName != NULL)
1516 return CR_INVALID_DATA;
1517
1518 if (hMachine == NULL)
1519 {
1520 hKey = HKEY_LOCAL_MACHINE;
1521 }
1522 else
1523 {
1524 if (RegConnectRegistryW(((PMACHINE_INFO)hMachine)->szMachineName,
1525 HKEY_LOCAL_MACHINE, &hKey))
1526 return CR_REGISTRY_ERROR;
1527 }
1528
1529 if (ulFlags & CM_OPEN_CLASS_KEY_INTERFACE)
1530 {
1531 lstrcpyW(szKeyName, DeviceClasses);
1532 }
1533 else
1534 {
1535 lstrcpyW(szKeyName, ControlClass);
1536 }
1537
1538 if (pClassGuid != NULL)
1539 {
1540 if (UuidToStringW((UUID*)pClassGuid, &lpGuidString) != RPC_S_OK)
1541 {
1542 RegCloseKey(hKey);
1543 return CR_INVALID_DATA;
1544 }
1545
1546 lstrcatW(szKeyName, Backslash);
1547 lstrcatW(szKeyName, lpGuidString);
1548 }
1549
1550 if (Disposition == RegDisposition_OpenAlways)
1551 {
1552 dwError = RegCreateKeyExW(hKey, szKeyName, 0, NULL, 0, samDesired,
1553 NULL, phkClass, &dwDisposition);
1554 }
1555 else
1556 {
1557 dwError = RegOpenKeyExW(hKey, szKeyName, 0, samDesired, phkClass);
1558 }
1559
1560 RegCloseKey(hKey);
1561
1562 if (pClassGuid != NULL)
1563 RpcStringFreeW(&lpGuidString);
1564
1565 if (dwError != ERROR_SUCCESS)
1566 {
1567 *phkClass = NULL;
1568 return CR_NO_SUCH_REGISTRY_KEY;
1569 }
1570
1571 if (pszClassName != NULL)
1572 {
1573 RegSetValueExW(*phkClass, Class, 0, REG_SZ, (LPBYTE)pszClassName,
1574 (lstrlenW(pszClassName) + 1) * sizeof(WCHAR));
1575 }
1576
1577 return CR_SUCCESS;
1578 }
1579
1580
1581 /***********************************************************************
1582 * CM_Set_DevNode_Problem [SETUPAPI.@]
1583 */
1584 CONFIGRET WINAPI CM_Set_DevNode_Problem(
1585 DEVINST dnDevInst, ULONG ulProblem, ULONG ulFlags)
1586 {
1587 TRACE("%lx %lx %lx\n", dnDevInst, ulProblem, ulFlags);
1588 return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
1589 }
1590
1591
1592 /***********************************************************************
1593 * CM_Set_DevNode_Problem_Ex [SETUPAPI.@]
1594 */
1595 CONFIGRET WINAPI CM_Set_DevNode_Problem_Ex(
1596 DEVINST dnDevInst, ULONG ulProblem, ULONG ulFlags, HMACHINE hMachine)
1597 {
1598 RPC_BINDING_HANDLE BindingHandle = NULL;
1599 HSTRING_TABLE StringTable = NULL;
1600 LPWSTR lpDevInst;
1601
1602 TRACE("%lx %lx %lx %lx\n", dnDevInst, ulProblem, ulFlags, hMachine);
1603
1604 if (dnDevInst == 0)
1605 return CR_INVALID_DEVNODE;
1606
1607 if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
1608 return CR_INVALID_FLAG;
1609
1610 if (hMachine != NULL)
1611 {
1612 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1613 if (BindingHandle == NULL)
1614 return CR_FAILURE;
1615
1616 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1617 if (StringTable == 0)
1618 return CR_FAILURE;
1619 }
1620 else
1621 {
1622 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1623 return CR_FAILURE;
1624 }
1625
1626 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1627 if (lpDevInst == NULL)
1628 return CR_INVALID_DEVNODE;
1629
1630 return PNP_SetDeviceProblem(BindingHandle,
1631 lpDevInst,
1632 ulProblem,
1633 ulFlags);
1634 }
1635
1636
1637 /***********************************************************************
1638 * CM_Set_DevNode_Registry_PropertyA [SETUPAPI.@]
1639 */
1640 CONFIGRET WINAPI CM_Set_DevNode_Registry_PropertyA(
1641 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1642 ULONG ulFlags)
1643 {
1644 TRACE("%lx %lu %p %lx %lx\n",
1645 dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
1646 return CM_Set_DevNode_Registry_Property_ExA(dnDevInst, ulProperty,
1647 Buffer, ulLength,
1648 ulFlags, NULL);
1649 }
1650
1651
1652 /***********************************************************************
1653 * CM_Set_DevNode_Registry_PropertyW [SETUPAPI.@]
1654 */
1655 CONFIGRET WINAPI CM_Set_DevNode_Registry_PropertyW(
1656 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1657 ULONG ulFlags)
1658 {
1659 TRACE("%lx %lu %p %lx %lx\n",
1660 dnDevInst, ulProperty, Buffer, ulLength, ulFlags);
1661 return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, ulProperty,
1662 Buffer, ulLength,
1663 ulFlags, NULL);
1664 }
1665
1666
1667 /***********************************************************************
1668 * CM_Set_DevNode_Registry_Property_ExA [SETUPAPI.@]
1669 */
1670 CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExA(
1671 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1672 ULONG ulFlags, HMACHINE hMachine)
1673 {
1674 CONFIGRET ret = CR_SUCCESS;
1675 LPWSTR lpBuffer;
1676 ULONG ulType;
1677
1678 FIXME("%lx %lu %p %lx %lx %lx\n",
1679 dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
1680
1681 if (Buffer == NULL && ulLength != 0)
1682 return CR_INVALID_POINTER;
1683
1684 if (Buffer == NULL)
1685 {
1686 ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
1687 ulProperty,
1688 NULL,
1689 0,
1690 ulFlags,
1691 hMachine);
1692 }
1693 else
1694 {
1695 /* Get property type */
1696 switch (ulProperty)
1697 {
1698 case CM_DRP_DEVICEDESC:
1699 ulType = REG_SZ;
1700 break;
1701
1702 case CM_DRP_HARDWAREID:
1703 ulType = REG_MULTI_SZ;
1704 break;
1705
1706 case CM_DRP_COMPATIBLEIDS:
1707 ulType = REG_MULTI_SZ;
1708 break;
1709
1710 case CM_DRP_SERVICE:
1711 ulType = REG_SZ;
1712 break;
1713
1714 case CM_DRP_CLASS:
1715 ulType = REG_SZ;
1716 break;
1717
1718 case CM_DRP_CLASSGUID:
1719 ulType = REG_SZ;
1720 break;
1721
1722 case CM_DRP_DRIVER:
1723 ulType = REG_SZ;
1724 break;
1725
1726 case CM_DRP_CONFIGFLAGS:
1727 ulType = REG_DWORD;
1728 break;
1729
1730 case CM_DRP_MFG:
1731 ulType = REG_SZ;
1732 break;
1733
1734 case CM_DRP_FRIENDLYNAME:
1735 ulType = REG_SZ;
1736 break;
1737
1738 case CM_DRP_LOCATION_INFORMATION:
1739 ulType = REG_SZ;
1740 break;
1741
1742 case CM_DRP_UPPERFILTERS:
1743 ulType = REG_MULTI_SZ;
1744 break;
1745
1746 case CM_DRP_LOWERFILTERS:
1747 ulType = REG_MULTI_SZ;
1748 break;
1749
1750 default:
1751 return CR_INVALID_PROPERTY;
1752 }
1753
1754 /* Allocate buffer if needed */
1755 if (ulType == REG_SZ ||
1756 ulType == REG_MULTI_SZ)
1757 {
1758 lpBuffer = MyMalloc(ulLength * sizeof(WCHAR));
1759 if (lpBuffer == NULL)
1760 {
1761 ret = CR_OUT_OF_MEMORY;
1762 }
1763 else
1764 {
1765 if (!MultiByteToWideChar(CP_ACP, 0, Buffer,
1766 ulLength, lpBuffer, ulLength))
1767 {
1768 MyFree(lpBuffer);
1769 ret = CR_FAILURE;
1770 }
1771 else
1772 {
1773 ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
1774 ulProperty,
1775 lpBuffer,
1776 ulLength * sizeof(WCHAR),
1777 ulFlags,
1778 hMachine);
1779 MyFree(lpBuffer);
1780 }
1781 }
1782 }
1783 else
1784 {
1785 ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
1786 ulProperty,
1787 Buffer,
1788 ulLength,
1789 ulFlags,
1790 hMachine);
1791 }
1792
1793 ret = CR_CALL_NOT_IMPLEMENTED;
1794 }
1795
1796 return ret;
1797 }
1798
1799
1800 /***********************************************************************
1801 * CM_Set_DevNode_Registry_Property_ExW [SETUPAPI.@]
1802 */
1803 CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExW(
1804 DEVINST dnDevInst, ULONG ulProperty, PCVOID Buffer, ULONG ulLength,
1805 ULONG ulFlags, HMACHINE hMachine)
1806 {
1807 RPC_BINDING_HANDLE BindingHandle = NULL;
1808 HSTRING_TABLE StringTable = NULL;
1809 LPWSTR lpDevInst;
1810 ULONG ulType;
1811
1812 TRACE("%lx %lu %p %lx %lx %lx\n",
1813 dnDevInst, ulProperty, Buffer, ulLength, ulFlags, hMachine);
1814
1815 if (dnDevInst == 0)
1816 return CR_INVALID_DEVNODE;
1817
1818 if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
1819 return CR_INVALID_PROPERTY;
1820
1821 if (Buffer != NULL && ulLength == 0)
1822 return CR_INVALID_POINTER;
1823
1824 if (ulFlags != 0)
1825 return CR_INVALID_FLAG;
1826
1827 if (hMachine != NULL)
1828 {
1829 BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
1830 if (BindingHandle == NULL)
1831 return CR_FAILURE;
1832
1833 StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
1834 if (StringTable == 0)
1835 return CR_FAILURE;
1836 }
1837 else
1838 {
1839 if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
1840 return CR_FAILURE;
1841 }
1842
1843 lpDevInst = StringTableStringFromId(StringTable, dnDevInst);
1844 if (lpDevInst == NULL)
1845 return CR_INVALID_DEVNODE;
1846
1847 switch (ulProperty)
1848 {
1849 case CM_DRP_DEVICEDESC:
1850 ulType = REG_SZ;
1851 break;
1852
1853 case CM_DRP_HARDWAREID:
1854 ulType = REG_MULTI_SZ;
1855 break;
1856
1857 case CM_DRP_COMPATIBLEIDS:
1858 ulType = REG_MULTI_SZ;
1859 break;
1860
1861 case CM_DRP_SERVICE:
1862 ulType = REG_SZ;
1863 break;
1864
1865 case CM_DRP_CLASS:
1866 ulType = REG_SZ;
1867 break;
1868
1869 case CM_DRP_CLASSGUID:
1870 ulType = REG_SZ;
1871 break;
1872
1873 case CM_DRP_DRIVER:
1874 ulType = REG_SZ;
1875 break;
1876
1877 case CM_DRP_CONFIGFLAGS:
1878 ulType = REG_DWORD;
1879 break;
1880
1881 case CM_DRP_MFG:
1882 ulType = REG_SZ;
1883 break;
1884
1885 case CM_DRP_FRIENDLYNAME:
1886 ulType = REG_SZ;
1887 break;
1888
1889 case CM_DRP_LOCATION_INFORMATION:
1890 ulType = REG_SZ;
1891 break;
1892
1893 case CM_DRP_UPPERFILTERS:
1894 ulType = REG_MULTI_SZ;
1895 break;
1896
1897 case CM_DRP_LOWERFILTERS:
1898 ulType = REG_MULTI_SZ;
1899 break;
1900
1901 default:
1902 return CR_INVALID_PROPERTY;
1903 }
1904
1905 return PNP_SetDeviceRegProp(BindingHandle,
1906 lpDevInst,
1907 ulProperty,
1908 ulType,
1909 (char *)Buffer,
1910 ulLength,
1911 ulFlags);
1912 }