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