1 /*
2 * SetupAPI device class-related functions
3 *
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "setupapi_private.h"
23
24 #include <wingdi.h>
25 #include <shellapi.h>
26 #include <strsafe.h>
27
28 /* Unicode constants */
29 static const WCHAR BackSlash[] = {'\\',0};
30 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
31 static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
32 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
34 static const WCHAR SetupapiDll[] = {'s','e','t','u','p','a','p','i','.','d','l','l',0};
35
36 typedef BOOL
37 (WINAPI* PROPERTY_PAGE_PROVIDER) (
38 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
39 IN LPFNADDPROPSHEETPAGE fAddFunc,
40 IN LPARAM lParam);
41 typedef BOOL
42 (*UPDATE_CLASS_PARAM_HANDLER) (
43 IN HDEVINFO DeviceInfoSet,
44 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
45 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
46 IN DWORD ClassInstallParamsSize);
47
48 static BOOL
49 SETUP_PropertyChangeHandler(
50 IN HDEVINFO DeviceInfoSet,
51 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
52 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
53 IN DWORD ClassInstallParamsSize);
54
55 static BOOL
56 SETUP_PropertyAddPropertyAdvancedHandler(
57 IN HDEVINFO DeviceInfoSet,
58 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
59 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
60 IN DWORD ClassInstallParamsSize);
61
62 typedef struct _INSTALL_PARAMS_DATA
63 {
64 DI_FUNCTION Function;
65 UPDATE_CLASS_PARAM_HANDLER UpdateHandler;
66 ULONG ParamsSize;
67 LONG FieldOffset;
68 } INSTALL_PARAMS_DATA;
69
70 #define ADD_PARAM_HANDLER(Function, UpdateHandler, ParamsType, ParamsField) \
71 { Function, UpdateHandler, sizeof(ParamsType), FIELD_OFFSET(struct ClassInstallParams, ParamsField) },
72
73 static const INSTALL_PARAMS_DATA InstallParamsData[] = {
74 ADD_PARAM_HANDLER(DIF_PROPERTYCHANGE, SETUP_PropertyChangeHandler, SP_PROPCHANGE_PARAMS, PropChangeParams)
75 ADD_PARAM_HANDLER(DIF_ADDPROPERTYPAGE_ADVANCED, SETUP_PropertyAddPropertyAdvancedHandler, SP_ADDPROPERTYPAGE_DATA, AddPropertyPageData)
76 };
77 #undef ADD_PARAM_HANDLER
78
79 #define UNKNOWN_ICON_INDEX 18
80
81 /***********************************************************************
82 * SetupDiDestroyClassImageList(SETUPAPI.@)
83 */
84 BOOL WINAPI
SetupDiDestroyClassImageList(IN PSP_CLASSIMAGELIST_DATA ClassImageListData)85 SetupDiDestroyClassImageList(
86 IN PSP_CLASSIMAGELIST_DATA ClassImageListData)
87 {
88 struct ClassImageList *list;
89 BOOL ret = FALSE;
90
91 TRACE("%p\n", ClassImageListData);
92
93 if (!ClassImageListData)
94 SetLastError(ERROR_INVALID_PARAMETER);
95 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
96 SetLastError(ERROR_INVALID_USER_BUFFER);
97 else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
98 SetLastError(ERROR_INVALID_USER_BUFFER);
99 else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
100 SetLastError(ERROR_INVALID_USER_BUFFER);
101 else
102 {
103 /* If Reserved wasn't NULL, then this is valid too */
104 if (ClassImageListData->ImageList)
105 {
106 ImageList_Destroy(ClassImageListData->ImageList);
107 ClassImageListData->ImageList = NULL;
108 }
109
110 MyFree(list);
111 ClassImageListData->Reserved = 0;
112
113 ret = TRUE;
114 }
115
116 TRACE("Returning %d\n", ret);
117 return ret;
118 }
119
120 LONG
SETUP_CreateDevicesList(IN OUT struct DeviceInfoSet * list,IN PCWSTR MachineName OPTIONAL,IN CONST GUID * Class OPTIONAL,IN PCWSTR Enumerator OPTIONAL)121 SETUP_CreateDevicesList(
122 IN OUT struct DeviceInfoSet *list,
123 IN PCWSTR MachineName OPTIONAL,
124 IN CONST GUID *Class OPTIONAL,
125 IN PCWSTR Enumerator OPTIONAL)
126 {
127 PWCHAR Buffer = NULL;
128 DWORD BufferLength = 4096;
129 PCWSTR InstancePath;
130 struct DeviceInfo *deviceInfo;
131 WCHAR ClassGuidBuffer[MAX_GUID_STRING_LEN];
132 DWORD ClassGuidBufferSize;
133 GUID ClassGuid;
134 DEVINST dnDevInst;
135 CONFIGRET cr;
136
137 Buffer = HeapAlloc(GetProcessHeap(), 0, BufferLength);
138 if (!Buffer)
139 return ERROR_NOT_ENOUGH_MEMORY;
140
141 do
142 {
143 cr = CM_Get_Device_ID_List_ExW(Enumerator,
144 Buffer,
145 BufferLength / sizeof(WCHAR),
146 Enumerator ? CM_GETIDLIST_FILTER_ENUMERATOR : CM_GETIDLIST_FILTER_NONE,
147 list->hMachine);
148 if (cr == CR_BUFFER_SMALL)
149 {
150 if (Buffer)
151 HeapFree(GetProcessHeap(), 0, Buffer);
152 BufferLength *= 2;
153 Buffer = HeapAlloc(GetProcessHeap(), 0, BufferLength);
154 if (!Buffer)
155 return ERROR_NOT_ENOUGH_MEMORY;
156 }
157 else if (cr != CR_SUCCESS)
158 {
159 TRACE("CM_Get_Device_ID_List_ExW() failed with status 0x%x\n", cr);
160 if (Buffer)
161 HeapFree(GetProcessHeap(), 0, Buffer);
162 return (cr == CR_REGISTRY_ERROR) ? ERROR_INVALID_DATA : GetErrorCodeFromCrCode(cr);
163 }
164 }
165 while (cr != CR_SUCCESS);
166
167 for (InstancePath = Buffer; *InstancePath != UNICODE_NULL; InstancePath += wcslen(InstancePath) + 1)
168 {
169 /* Check that device really exists */
170 TRACE("Checking %S\n", InstancePath);
171 cr = CM_Locate_DevNode_Ex(&dnDevInst,
172 (DEVINSTID_W)InstancePath,
173 CM_LOCATE_DEVNODE_NORMAL,
174 list->hMachine);
175 if (cr != CR_SUCCESS)
176 {
177 ERR("CM_Locate_DevNode_ExW('%S') failed with status 0x%x\n", InstancePath, cr);
178 continue;
179 }
180
181 /* Retrieve GUID of this device */
182 ClassGuidBufferSize = sizeof(ClassGuidBuffer);
183 cr = CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
184 CM_DRP_CLASSGUID,
185 NULL,
186 ClassGuidBuffer,
187 &ClassGuidBufferSize,
188 0,
189 list->hMachine);
190 if (cr == CR_SUCCESS)
191 {
192 ClassGuidBuffer[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */
193 if (UuidFromStringW(&ClassGuidBuffer[1], &ClassGuid) != RPC_S_OK)
194 {
195 /* Bad GUID, skip the entry */
196 ERR("Invalid ClassGUID '%S' for device %S\n", ClassGuidBuffer, InstancePath);
197 continue;
198 }
199 }
200 else
201 {
202 TRACE("Using default class GUID_NULL for device %S\n", InstancePath);
203 memcpy(&ClassGuid, &GUID_NULL, sizeof(GUID));
204 }
205
206 if (Class && !IsEqualIID(&ClassGuid, Class))
207 {
208 TRACE("Skipping %S due to wrong class GUID\n", InstancePath);
209 continue;
210 }
211
212 /* Good! Create a device info element */
213 if (!CreateDeviceInfo(list, InstancePath, &ClassGuid, &deviceInfo))
214 {
215 ERR("Failed to create info for %S\n", InstancePath);
216 HeapFree(GetProcessHeap(), 0, Buffer);
217 return GetLastError();
218 }
219
220 TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
221 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
222 }
223
224 HeapFree(GetProcessHeap(), 0, Buffer);
225 return ERROR_SUCCESS;
226 }
227
228 static BOOL
SETUP_GetIconIndex(IN HKEY hClassKey,OUT PINT ImageIndex)229 SETUP_GetIconIndex(
230 IN HKEY hClassKey,
231 OUT PINT ImageIndex)
232 {
233 LPWSTR Buffer = NULL;
234 DWORD dwRegType, dwLength;
235 LONG rc;
236 BOOL ret = FALSE;
237
238 /* Read icon registry key */
239 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength);
240 if (rc != ERROR_SUCCESS)
241 {
242 SetLastError(rc);
243 goto cleanup;
244 } else if (dwRegType != REG_SZ)
245 {
246 SetLastError(ERROR_INVALID_INDEX);
247 goto cleanup;
248 }
249 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
250 if (!Buffer)
251 {
252 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
253 goto cleanup;
254 }
255 rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength);
256 if (rc != ERROR_SUCCESS)
257 {
258 SetLastError(rc);
259 goto cleanup;
260 }
261 /* make sure the returned buffer is NULL-terminated */
262 Buffer[dwLength / sizeof(WCHAR)] = 0;
263
264 /* Transform icon value to a INT */
265 *ImageIndex = atoiW(Buffer);
266 ret = TRUE;
267
268 cleanup:
269 MyFree(Buffer);
270 return ret;
271 }
272
273 /***********************************************************************
274 * SetupDiGetClassImageIndex (SETUPAPI.@)
275 */
276 BOOL WINAPI
SetupDiGetClassImageIndex(IN PSP_CLASSIMAGELIST_DATA ClassImageListData,IN CONST GUID * ClassGuid,OUT PINT ImageIndex)277 SetupDiGetClassImageIndex(
278 IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
279 IN CONST GUID *ClassGuid,
280 OUT PINT ImageIndex)
281 {
282 struct ClassImageList *list;
283 BOOL ret = FALSE;
284
285 TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex);
286
287 if (!ClassImageListData || !ClassGuid || !ImageIndex)
288 SetLastError(ERROR_INVALID_PARAMETER);
289 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
290 SetLastError(ERROR_INVALID_USER_BUFFER);
291 else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
292 SetLastError(ERROR_INVALID_USER_BUFFER);
293 else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
294 SetLastError(ERROR_INVALID_USER_BUFFER);
295 else
296 {
297 DWORD i;
298
299 for (i = 0; i < list->NumberOfGuids; i++)
300 {
301 if (IsEqualIID(ClassGuid, &list->Guids[i]))
302 break;
303 }
304
305 if (i == list->NumberOfGuids || list->IconIndexes[i] < 0)
306 SetLastError(ERROR_FILE_NOT_FOUND);
307 else
308 {
309 *ImageIndex = list->IconIndexes[i];
310 ret = TRUE;
311 }
312 }
313
314 TRACE("Returning %d\n", ret);
315 return ret;
316 }
317
318 /***********************************************************************
319 * SetupDiGetClassImageList(SETUPAPI.@)
320 */
321 BOOL WINAPI
SetupDiGetClassImageList(OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)322 SetupDiGetClassImageList(
323 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
324 {
325 return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
326 }
327
328 /***********************************************************************
329 * SetupDiGetClassImageListExA(SETUPAPI.@)
330 */
331 BOOL WINAPI
SetupDiGetClassImageListExA(OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,IN PCSTR MachineName OPTIONAL,IN PVOID Reserved)332 SetupDiGetClassImageListExA(
333 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
334 IN PCSTR MachineName OPTIONAL,
335 IN PVOID Reserved)
336 {
337 PWSTR MachineNameW = NULL;
338 BOOL ret;
339
340 if (MachineName)
341 {
342 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
343 if (MachineNameW == NULL)
344 return FALSE;
345 }
346
347 ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved);
348
349 MyFree(MachineNameW);
350
351 return ret;
352 }
353
354 static BOOL WINAPI
SETUP_GetClassIconInfo(IN CONST GUID * ClassGuid,OUT PINT OutIndex,OUT LPWSTR * OutDllName)355 SETUP_GetClassIconInfo(IN CONST GUID *ClassGuid, OUT PINT OutIndex, OUT LPWSTR *OutDllName)
356 {
357 LPWSTR Buffer = NULL;
358 INT iconIndex = -UNKNOWN_ICON_INDEX;
359 HKEY hKey = INVALID_HANDLE_VALUE;
360 BOOL ret = FALSE;
361
362 if (ClassGuid)
363 {
364 hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
365 if (hKey != INVALID_HANDLE_VALUE)
366 {
367 SETUP_GetIconIndex(hKey, &iconIndex);
368 }
369 }
370
371 if (iconIndex > 0)
372 {
373 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
374 PWCHAR Comma;
375 LONG rc;
376 DWORD dwRegType, dwLength;
377 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
378 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
379 {
380 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
381 if (Buffer == NULL)
382 {
383 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
384 goto cleanup;
385 }
386 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
387 if (rc != ERROR_SUCCESS)
388 {
389 SetLastError(rc);
390 goto cleanup;
391 }
392 /* make sure the returned buffer is NULL-terminated */
393 Buffer[dwLength / sizeof(WCHAR)] = 0;
394 }
395 else if
396 (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
397 && dwRegType == REG_SZ)
398 {
399 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
400 if (Buffer == NULL)
401 {
402 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
403 goto cleanup;
404 }
405 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
406 if (rc != ERROR_SUCCESS)
407 {
408 SetLastError(rc);
409 goto cleanup;
410 }
411 /* make sure the returned buffer is NULL-terminated */
412 Buffer[dwLength / sizeof(WCHAR)] = 0;
413 }
414 else
415 {
416 /* Unable to find where to load the icon */
417 SetLastError(ERROR_FILE_NOT_FOUND);
418 goto cleanup;
419 }
420 Comma = strchrW(Buffer, ',');
421 if (!Comma)
422 {
423 SetLastError(ERROR_GEN_FAILURE);
424 goto cleanup;
425 }
426 *Comma = '\0';
427 *OutDllName = Buffer;
428 }
429 else
430 {
431 /* Look up icon in setupapi.dll */
432 iconIndex = -iconIndex;
433 *OutDllName = NULL;
434 }
435
436 *OutIndex = iconIndex;
437 ret = TRUE;
438
439 TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(*OutDllName ? *OutDllName : SetupapiDll));
440
441 cleanup:
442
443 if (hKey != INVALID_HANDLE_VALUE)
444 RegCloseKey(hKey);
445
446 if (Buffer && !ret)
447 MyFree(Buffer);
448
449 return ret;
450 }
451
452
453 /***********************************************************************
454 * SetupDiGetClassImageListExW(SETUPAPI.@)
455 */
456 BOOL WINAPI
SetupDiGetClassImageListExW(OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,IN PCWSTR MachineName OPTIONAL,IN PVOID Reserved)457 SetupDiGetClassImageListExW(
458 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
459 IN PCWSTR MachineName OPTIONAL,
460 IN PVOID Reserved)
461 {
462 BOOL ret = FALSE;
463
464 TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved);
465
466 if (!ClassImageListData)
467 SetLastError(ERROR_INVALID_PARAMETER);
468 else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
469 SetLastError(ERROR_INVALID_USER_BUFFER);
470 else if (Reserved)
471 SetLastError(ERROR_INVALID_PARAMETER);
472 else
473 {
474 struct ClassImageList *list = NULL;
475 HDC hDC;
476 DWORD RequiredSize;
477 DWORD ilMask, bkColor;
478 HICON hIcon;
479 DWORD size;
480 INT i, bpp;
481 UINT idx;
482
483 /* Get list of all class GUIDs in given computer */
484 ret = SetupDiBuildClassInfoListExW(
485 0,
486 NULL,
487 0,
488 &RequiredSize,
489 MachineName,
490 NULL);
491 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
492 goto cleanup;
493
494 size = sizeof(struct ClassImageList)
495 + (sizeof(GUID) + sizeof(INT)) * RequiredSize;
496 list = HeapAlloc(GetProcessHeap(), 0, size);
497 if (!list)
498 {
499 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
500 goto cleanup;
501 }
502 list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC;
503 list->NumberOfGuids = RequiredSize;
504 list->Guids = (GUID*)(list + 1);
505 list->IconIndexes = (INT*)((ULONG_PTR)(list + 1) + sizeof(GUID) * RequiredSize);
506
507 ret = SetupDiBuildClassInfoListExW(
508 0,
509 list->Guids,
510 list->NumberOfGuids,
511 &RequiredSize,
512 MachineName,
513 NULL);
514 if (!ret)
515 goto cleanup;
516 else if (RequiredSize != list->NumberOfGuids)
517 {
518 /* Hm. Class list changed since last call. Ignore
519 * this case as it should be very rare */
520 SetLastError(ERROR_GEN_FAILURE);
521 ret = FALSE;
522 goto cleanup;
523 }
524
525 /* Prepare a HIMAGELIST */
526 InitCommonControls();
527
528 hDC = GetDC(NULL);
529 if (!hDC)
530 goto cleanup;
531
532 bpp = GetDeviceCaps(hDC, BITSPIXEL);
533 ReleaseDC(NULL, hDC);
534
535 if (bpp <= 4)
536 ilMask = ILC_COLOR4;
537 else if (bpp <= 8)
538 ilMask = ILC_COLOR8;
539 else if (bpp <= 16)
540 ilMask = ILC_COLOR16;
541 else if (bpp <= 24)
542 ilMask = ILC_COLOR24;
543 else if (bpp <= 32)
544 ilMask = ILC_COLOR32;
545 else
546 ilMask = ILC_COLOR;
547
548 ilMask |= ILC_MASK;
549
550 ClassImageListData->ImageList = ImageList_Create(16, 16, ilMask, 100, 10);
551 if (!ClassImageListData->ImageList)
552 goto cleanup;
553
554 ClassImageListData->Reserved = (ULONG_PTR)list;
555
556 /* For some reason, Windows sets the list background to COLOR_WINDOW */
557 bkColor = GetSysColor(COLOR_WINDOW);
558 ImageList_SetBkColor(ClassImageListData->ImageList, bkColor);
559
560 /* Now, we "simply" need to load icons associated with all class guids,
561 * and put their index in the image list in the IconIndexes array */
562 for (i = 0; i < list->NumberOfGuids; i++)
563 {
564 INT miniIconIndex;
565 LPWSTR DllName = NULL;
566
567 if (SETUP_GetClassIconInfo(&list->Guids[i], &miniIconIndex, &DllName))
568 {
569 if (DllName && ExtractIconExW(DllName, -miniIconIndex, NULL, &hIcon, 1) == 1)
570 {
571 list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
572 }
573 else if(!DllName)
574 {
575 hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
576 list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
577 }
578
579 if(hIcon)
580 DestroyIcon(hIcon);
581 else
582 list->IconIndexes[i] = -1;
583
584 if(DllName)
585 MyFree(DllName);
586 }
587 else
588 {
589 list->IconIndexes[i] = -1; /* Special value to indicate that the icon is unavailable */
590 }
591 }
592
593 /* Finally, add the overlay icons to the image list */
594 for (i = 0; i <= 2; i++)
595 {
596 hIcon = LoadImage(hInstance, MAKEINTRESOURCE(500 + i), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
597 if (hIcon)
598 {
599 idx = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
600 if (idx != -1)
601 ImageList_SetOverlayImage(ClassImageListData->ImageList, idx, i + 1);
602 DestroyIcon(hIcon);
603 }
604 }
605
606 ret = TRUE;
607
608 cleanup:
609 if (!ret)
610 {
611 if (ClassImageListData->Reserved)
612 SetupDiDestroyClassImageList(ClassImageListData);
613 else if (list)
614 MyFree(list);
615 }
616 }
617
618 TRACE("Returning %d\n", ret);
619 return ret;
620 }
621
622 /***********************************************************************
623 * SetupDiGetClassInstallParamsA(SETUPAPI.@)
624 */
625 BOOL WINAPI
SetupDiGetClassInstallParamsA(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,IN DWORD ClassInstallParamsSize,OUT PDWORD RequiredSize OPTIONAL)626 SetupDiGetClassInstallParamsA(
627 IN HDEVINFO DeviceInfoSet,
628 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
629 OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
630 IN DWORD ClassInstallParamsSize,
631 OUT PDWORD RequiredSize OPTIONAL)
632 {
633 FIXME("SetupDiGetClassInstallParamsA(%p %p %p %lu %p) Stub\n",
634 DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize, RequiredSize);
635 return FALSE;
636 }
637
638 /***********************************************************************
639 * SetupDiGetClassInstallParamsW(SETUPAPI.@)
640 */
641 BOOL WINAPI
SetupDiGetClassInstallParamsW(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,IN DWORD ClassInstallParamsSize,OUT PDWORD RequiredSize OPTIONAL)642 SetupDiGetClassInstallParamsW(
643 IN HDEVINFO DeviceInfoSet,
644 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
645 OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
646 IN DWORD ClassInstallParamsSize,
647 OUT PDWORD RequiredSize OPTIONAL)
648 {
649 FIXME("SetupDiGetClassInstallParamsW(%p %p %p %lu %p) Stub\n",
650 DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize, RequiredSize);
651 return FALSE;
652 }
653
654 /***********************************************************************
655 * SetupDiLoadClassIcon(SETUPAPI.@)
656 */
657 BOOL WINAPI
SetupDiLoadClassIcon(IN CONST GUID * ClassGuid,OUT HICON * LargeIcon OPTIONAL,OUT PINT MiniIconIndex OPTIONAL)658 SetupDiLoadClassIcon(
659 IN CONST GUID *ClassGuid,
660 OUT HICON *LargeIcon OPTIONAL,
661 OUT PINT MiniIconIndex OPTIONAL)
662 {
663 INT iconIndex = 0;
664 LPWSTR DllName = NULL;
665 BOOL ret = FALSE;
666 HICON hIcon = NULL;
667
668 if (LargeIcon)
669 {
670 if(!SETUP_GetClassIconInfo(ClassGuid, &iconIndex, &DllName))
671 goto cleanup;
672
673 if (!DllName || ExtractIconExW(DllName, -iconIndex, &hIcon, NULL, 1) != 1 || hIcon == NULL)
674 {
675 /* load the default unknown device icon if ExtractIcon failed */
676 if(DllName)
677 iconIndex = UNKNOWN_ICON_INDEX;
678
679 hIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
680
681 if(!hIcon)
682 goto cleanup;
683 }
684
685 *LargeIcon = hIcon;
686 }
687
688 if (MiniIconIndex)
689 *MiniIconIndex = iconIndex;
690
691 ret = TRUE;
692
693 cleanup:
694
695 if(DllName)
696 MyFree(DllName);
697
698 TRACE("Returning %d\n", ret);
699 return ret;
700 }
701
702 /***********************************************************************
703 * SetupDiInstallClassExW (SETUPAPI.@)
704 */
705 HKEY
706 SETUP_CreateClassKey(HINF hInf);
707 BOOL WINAPI
SetupDiInstallClassExW(IN HWND hwndParent OPTIONAL,IN PCWSTR InfFileName OPTIONAL,IN DWORD Flags,IN HSPFILEQ FileQueue OPTIONAL,IN CONST GUID * InterfaceClassGuid OPTIONAL,IN PVOID Reserved1,IN PVOID Reserved2)708 SetupDiInstallClassExW(
709 IN HWND hwndParent OPTIONAL,
710 IN PCWSTR InfFileName OPTIONAL,
711 IN DWORD Flags,
712 IN HSPFILEQ FileQueue OPTIONAL,
713 IN CONST GUID *InterfaceClassGuid OPTIONAL,
714 IN PVOID Reserved1,
715 IN PVOID Reserved2)
716 {
717 BOOL ret = FALSE;
718
719 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags,
720 FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2);
721
722 if (!InfFileName)
723 {
724 FIXME("Case not implemented: InfFileName NULL\n");
725 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
726 }
727 else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
728 {
729 TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
730 SetLastError(ERROR_INVALID_FLAGS);
731 }
732 else if ((Flags & DI_NOVCP) && FileQueue == NULL)
733 SetLastError(ERROR_INVALID_PARAMETER);
734 else if (Reserved1 != NULL)
735 SetLastError(ERROR_INVALID_PARAMETER);
736 else if (Reserved2 != NULL)
737 SetLastError(ERROR_INVALID_PARAMETER);
738 else
739 {
740 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
741 SP_DEVINSTALL_PARAMS_W InstallParams;
742 WCHAR SectionName[MAX_PATH];
743 HINF hInf = INVALID_HANDLE_VALUE;
744 HKEY hRootKey = INVALID_HANDLE_VALUE;
745 PVOID callback_context = NULL;
746
747 hDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL);
748 if (hDeviceInfo == INVALID_HANDLE_VALUE)
749 goto cleanup;
750
751 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
752 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams))
753 goto cleanup;
754
755 InstallParams.Flags &= ~(DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
756 InstallParams.Flags |= Flags & (DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
757 if (Flags & DI_NOVCP)
758 InstallParams.FileQueue = FileQueue;
759 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams))
760 goto cleanup;
761
762 /* Open the .inf file */
763 hInf = SetupOpenInfFileW(
764 InfFileName,
765 NULL,
766 INF_STYLE_WIN4,
767 NULL);
768 if (hInf == INVALID_HANDLE_VALUE)
769 goto cleanup;
770
771 /* Try to append a layout file */
772 SetupOpenAppendInfFileW(NULL, hInf, NULL);
773
774 if (InterfaceClassGuid)
775 {
776 /* Retrieve the actual section name */
777 ret = SetupDiGetActualSectionToInstallW(
778 hInf,
779 InterfaceInstall32,
780 SectionName,
781 MAX_PATH,
782 NULL,
783 NULL);
784 if (!ret)
785 goto cleanup;
786
787 /* Open registry key related to this interface */
788 /* FIXME: What happens if the key doesn't exist? */
789 hRootKey = SetupDiOpenClassRegKeyExW(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL);
790 if (hRootKey == INVALID_HANDLE_VALUE)
791 goto cleanup;
792
793 /* SetupDiCreateDeviceInterface??? */
794 FIXME("Installing an interface is not implemented\n");
795 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
796 }
797 else
798 {
799 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
800 hRootKey = SETUP_CreateClassKey(hInf);
801 if (hRootKey == INVALID_HANDLE_VALUE)
802 goto cleanup;
803
804 /* Retrieve the actual section name */
805 ret = SetupDiGetActualSectionToInstallW(
806 hInf,
807 ClassInstall32,
808 SectionName,
809 MAX_PATH - strlenW(DotServices),
810 NULL,
811 NULL);
812 if (!ret)
813 goto cleanup;
814
815 callback_context = SetupInitDefaultQueueCallback(hwndParent);
816 if (!callback_context)
817 goto cleanup;
818
819 ret = SetupInstallFromInfSectionW(
820 hwndParent,
821 hInf,
822 SectionName,
823 SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG,
824 hRootKey,
825 NULL, /* FIXME: SourceRootPath */
826 !(Flags & DI_NOVCP) && (Flags & DI_FORCECOPY) ? SP_COPY_FORCE_IN_USE : 0, /* CopyFlags */
827 SetupDefaultQueueCallbackW,
828 callback_context,
829 hDeviceInfo,
830 NULL);
831 if (!ret)
832 goto cleanup;
833
834 /* OPTIONAL: Install .Services section */
835 lstrcatW(SectionName, DotServices);
836 SetupInstallServicesFromInfSectionExW(
837 hInf,
838 SectionName,
839 0,
840 hDeviceInfo,
841 NULL,
842 NULL,
843 NULL);
844 ret = TRUE;
845 }
846
847 cleanup:
848 if (hDeviceInfo != INVALID_HANDLE_VALUE)
849 SetupDiDestroyDeviceInfoList(hDeviceInfo);
850 if (hInf != INVALID_HANDLE_VALUE)
851 SetupCloseInfFile(hInf);
852 if (hRootKey != INVALID_HANDLE_VALUE)
853 RegCloseKey(hRootKey);
854 SetupTermDefaultQueueCallback(callback_context);
855 }
856
857 TRACE("Returning %d\n", ret);
858 return ret;
859 }
860
861 /***********************************************************************
862 * Helper functions for SetupDiSetClassInstallParamsW
863 */
864 static BOOL
SETUP_PropertyChangeHandler(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData,IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,IN DWORD ClassInstallParamsSize)865 SETUP_PropertyChangeHandler(
866 IN HDEVINFO DeviceInfoSet,
867 IN PSP_DEVINFO_DATA DeviceInfoData,
868 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
869 IN DWORD ClassInstallParamsSize)
870 {
871 PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams;
872 BOOL ret = FALSE;
873
874 if (!DeviceInfoData)
875 SetLastError(ERROR_INVALID_PARAMETER);
876 else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
877 SetLastError(ERROR_INVALID_PARAMETER);
878 else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE
879 && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE
880 && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP)
881 SetLastError(ERROR_INVALID_FLAGS);
882 else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL
883 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
884 SetLastError(ERROR_INVALID_FLAGS);
885 else if (PropChangeParams
886 && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP)
887 && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
888 SetLastError(ERROR_INVALID_USER_BUFFER);
889 else
890 {
891 PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams;
892 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
893 CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChangeParams;
894
895 if (*CurrentPropChangeParams)
896 {
897 MyFree(*CurrentPropChangeParams);
898 *CurrentPropChangeParams = NULL;
899 }
900 if (PropChangeParams)
901 {
902 *CurrentPropChangeParams = MyMalloc(ClassInstallParamsSize);
903 if (!*CurrentPropChangeParams)
904 {
905 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
906 goto done;
907 }
908 memcpy(*CurrentPropChangeParams, PropChangeParams, ClassInstallParamsSize);
909 }
910 ret = TRUE;
911 }
912
913 done:
914 return ret;
915 }
916
917 static BOOL
SETUP_PropertyAddPropertyAdvancedHandler(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,IN DWORD ClassInstallParamsSize)918 SETUP_PropertyAddPropertyAdvancedHandler(
919 IN HDEVINFO DeviceInfoSet,
920 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
921 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
922 IN DWORD ClassInstallParamsSize)
923 {
924 PSP_ADDPROPERTYPAGE_DATA AddPropertyPageData = (PSP_ADDPROPERTYPAGE_DATA)ClassInstallParams;
925 BOOL ret = FALSE;
926
927 if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
928 SetLastError(ERROR_INVALID_PARAMETER);
929 else if (AddPropertyPageData && AddPropertyPageData->Flags != 0)
930 SetLastError(ERROR_INVALID_FLAGS);
931 else if (AddPropertyPageData && AddPropertyPageData->NumDynamicPages >= MAX_INSTALLWIZARD_DYNAPAGES)
932 SetLastError(ERROR_INVALID_USER_BUFFER);
933 else
934 {
935 PSP_ADDPROPERTYPAGE_DATA *CurrentAddPropertyPageData;
936 if (!DeviceInfoData)
937 {
938 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
939 CurrentAddPropertyPageData = &list->ClassInstallParams.AddPropertyPageData;
940 }
941 else
942 {
943 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
944 CurrentAddPropertyPageData = &deviceInfo->ClassInstallParams.AddPropertyPageData;
945 }
946 if (*CurrentAddPropertyPageData)
947 {
948 MyFree(*CurrentAddPropertyPageData);
949 *CurrentAddPropertyPageData = NULL;
950 }
951 if (AddPropertyPageData)
952 {
953 *CurrentAddPropertyPageData = MyMalloc(ClassInstallParamsSize);
954 if (!*CurrentAddPropertyPageData)
955 {
956 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
957 goto done;
958 }
959 memcpy(*CurrentAddPropertyPageData, AddPropertyPageData, ClassInstallParamsSize);
960 }
961 ret = TRUE;
962 }
963
964 done:
965 return ret;
966 }
967
968 /***********************************************************************
969 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
970 */
971 BOOL WINAPI
SetupDiSetClassInstallParamsW(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,IN DWORD ClassInstallParamsSize)972 SetupDiSetClassInstallParamsW(
973 IN HDEVINFO DeviceInfoSet,
974 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
975 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
976 IN DWORD ClassInstallParamsSize)
977 {
978 struct DeviceInfoSet *list;
979 BOOL ret = FALSE;
980
981 TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData,
982 ClassInstallParams, ClassInstallParamsSize);
983
984 if (!DeviceInfoSet)
985 SetLastError(ERROR_INVALID_PARAMETER);
986 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
987 SetLastError(ERROR_INVALID_HANDLE);
988 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
989 SetLastError(ERROR_INVALID_HANDLE);
990 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
991 SetLastError(ERROR_INVALID_USER_BUFFER);
992 else if (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER))
993 SetLastError(ERROR_INVALID_USER_BUFFER);
994 else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER))
995 SetLastError(ERROR_INVALID_PARAMETER);
996 else if (!ClassInstallParams && ClassInstallParamsSize != 0)
997 SetLastError(ERROR_INVALID_PARAMETER);
998 else
999 {
1000 SP_DEVINSTALL_PARAMS_W InstallParams;
1001 BOOL Result;
1002
1003 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1004 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
1005 if (!Result)
1006 goto done;
1007
1008 if (ClassInstallParams)
1009 {
1010 DWORD i;
1011 /* Check parameters in ClassInstallParams */
1012 for (i = 0; i < sizeof(InstallParamsData) / sizeof(InstallParamsData[0]); i++)
1013 {
1014 if (InstallParamsData[i].Function == ClassInstallParams->InstallFunction)
1015 {
1016 ret = InstallParamsData[i].UpdateHandler(
1017 DeviceInfoSet,
1018 DeviceInfoData,
1019 ClassInstallParams,
1020 ClassInstallParamsSize);
1021 if (ret)
1022 {
1023 InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
1024 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
1025 }
1026 goto done;
1027 }
1028 }
1029 ERR("InstallFunction %u has no associated update handler\n", ClassInstallParams->InstallFunction);
1030 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1031 goto done;
1032 }
1033 else
1034 {
1035 InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS;
1036 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
1037 }
1038 }
1039
1040 done:
1041 TRACE("Returning %d\n", ret);
1042 return ret;
1043 }
1044
1045 /***********************************************************************
1046 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
1047 */
1048 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN LPPROPSHEETHEADERA PropertySheetHeader,IN DWORD PropertySheetHeaderPageListSize,OUT PDWORD RequiredSize OPTIONAL,IN DWORD PropertySheetType)1049 SetupDiGetClassDevPropertySheetsA(
1050 IN HDEVINFO DeviceInfoSet,
1051 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1052 IN LPPROPSHEETHEADERA PropertySheetHeader,
1053 IN DWORD PropertySheetHeaderPageListSize,
1054 OUT PDWORD RequiredSize OPTIONAL,
1055 IN DWORD PropertySheetType)
1056 {
1057 PROPSHEETHEADERW psh;
1058 BOOL ret = FALSE;
1059
1060 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
1061 PropertySheetHeader, PropertySheetHeaderPageListSize,
1062 RequiredSize, PropertySheetType);
1063
1064 if(PropertySheetHeader)
1065 {
1066 psh.dwFlags = PropertySheetHeader->dwFlags;
1067 psh.phpage = PropertySheetHeader->phpage;
1068 psh.nPages = PropertySheetHeader->nPages;
1069 }
1070
1071 ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
1072 PropertySheetHeaderPageListSize, RequiredSize,
1073 PropertySheetType);
1074 if (ret)
1075 {
1076 PropertySheetHeader->nPages = psh.nPages;
1077 }
1078
1079 TRACE("Returning %d\n", ret);
1080 return ret;
1081 }
1082
1083 struct ClassDevPropertySheetsData
1084 {
1085 LPPROPSHEETHEADERW PropertySheetHeader;
1086 DWORD PropertySheetHeaderPageListSize;
1087 DWORD NumberOfPages;
1088 BOOL DontCancel;
1089 };
1090
1091 static BOOL WINAPI
SETUP_GetClassDevPropertySheetsCallback(IN HPROPSHEETPAGE hPropSheetPage,IN OUT LPARAM lParam)1092 SETUP_GetClassDevPropertySheetsCallback(
1093 IN HPROPSHEETPAGE hPropSheetPage,
1094 IN OUT LPARAM lParam)
1095 {
1096 struct ClassDevPropertySheetsData *PropPageData;
1097
1098 PropPageData = (struct ClassDevPropertySheetsData *)lParam;
1099
1100 PropPageData->NumberOfPages++;
1101
1102 if (PropPageData->PropertySheetHeader->nPages < PropPageData->PropertySheetHeaderPageListSize)
1103 {
1104 PropPageData->PropertySheetHeader->phpage[PropPageData->PropertySheetHeader->nPages] = hPropSheetPage;
1105 PropPageData->PropertySheetHeader->nPages++;
1106 return TRUE;
1107 }
1108
1109 return PropPageData->DontCancel;
1110 }
1111
1112 static DWORD
SETUP_GetValueString(IN HKEY hKey,IN LPWSTR lpValueName,OUT LPWSTR * lpString)1113 SETUP_GetValueString(
1114 IN HKEY hKey,
1115 IN LPWSTR lpValueName,
1116 OUT LPWSTR *lpString)
1117 {
1118 LPWSTR lpBuffer;
1119 DWORD dwLength = 0;
1120 DWORD dwRegType;
1121 DWORD rc;
1122
1123 *lpString = NULL;
1124
1125 RegQueryValueExW(hKey, lpValueName, NULL, &dwRegType, NULL, &dwLength);
1126
1127 if (dwLength == 0 || dwRegType != REG_SZ)
1128 return ERROR_FILE_NOT_FOUND;
1129
1130 lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
1131 if (lpBuffer == NULL)
1132 return ERROR_NOT_ENOUGH_MEMORY;
1133
1134 rc = RegQueryValueExW(hKey, lpValueName, NULL, NULL, (LPBYTE)lpBuffer, &dwLength);
1135 if (rc != ERROR_SUCCESS)
1136 {
1137 HeapFree(GetProcessHeap(), 0, lpBuffer);
1138 return rc;
1139 }
1140
1141 lpBuffer[dwLength / sizeof(WCHAR)] = UNICODE_NULL;
1142
1143 *lpString = lpBuffer;
1144
1145 return ERROR_SUCCESS;
1146 }
1147
1148 static
1149 BOOL
SETUP_CallInstaller(IN DI_FUNCTION InstallFunction,IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN PSP_ADDPROPERTYPAGE_DATA PageData)1150 SETUP_CallInstaller(
1151 IN DI_FUNCTION InstallFunction,
1152 IN HDEVINFO DeviceInfoSet,
1153 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1154 IN PSP_ADDPROPERTYPAGE_DATA PageData)
1155 {
1156 PSP_CLASSINSTALL_HEADER pClassInstallParams = NULL;
1157 DWORD dwSize = 0;
1158 DWORD dwError;
1159 BOOL ret = TRUE;
1160
1161 /* Get the size of the old class install parameters */
1162 if (!SetupDiGetClassInstallParams(DeviceInfoSet,
1163 DeviceInfoData,
1164 NULL,
1165 0,
1166 &dwSize))
1167 {
1168 dwError = GetLastError();
1169 if (dwError != ERROR_INSUFFICIENT_BUFFER)
1170 {
1171 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", dwError);
1172 return FALSE;
1173 }
1174 }
1175
1176 /* Allocate a buffer for the old class install parameters */
1177 pClassInstallParams = HeapAlloc(GetProcessHeap(), 0, dwSize);
1178 if (pClassInstallParams == NULL)
1179 {
1180 ERR("Failed to allocate the parameters buffer!\n");
1181 return FALSE;
1182 }
1183
1184 /* Save the old class install parameters */
1185 if (!SetupDiGetClassInstallParams(DeviceInfoSet,
1186 DeviceInfoData,
1187 pClassInstallParams,
1188 dwSize,
1189 &dwSize))
1190 {
1191 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError());
1192 ret = FALSE;
1193 goto done;
1194 }
1195
1196 /* Set the new class install parameters */
1197 if (!SetupDiSetClassInstallParams(DeviceInfoSet,
1198 DeviceInfoData,
1199 &PageData->ClassInstallHeader,
1200 sizeof(SP_ADDPROPERTYPAGE_DATA)))
1201 {
1202 ERR("SetupDiSetClassInstallParams failed (Error %lu)\n", dwError);
1203 ret = FALSE;
1204 goto done;
1205 }
1206
1207 /* Call the installer */
1208 ret = SetupDiCallClassInstaller(InstallFunction,
1209 DeviceInfoSet,
1210 DeviceInfoData);
1211 if (ret == FALSE)
1212 {
1213 ERR("SetupDiCallClassInstaller failed\n");
1214 goto done;
1215 }
1216
1217 /* Read the new class installer parameters */
1218 if (!SetupDiGetClassInstallParams(DeviceInfoSet,
1219 DeviceInfoData,
1220 &PageData->ClassInstallHeader,
1221 sizeof(SP_ADDPROPERTYPAGE_DATA),
1222 NULL))
1223 {
1224 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError());
1225 ret = FALSE;
1226 goto done;
1227 }
1228
1229 done:
1230 /* Restore and free the old class install parameters */
1231 if (pClassInstallParams != NULL)
1232 {
1233 SetupDiSetClassInstallParams(DeviceInfoSet,
1234 DeviceInfoData,
1235 pClassInstallParams,
1236 dwSize);
1237
1238 HeapFree(GetProcessHeap(), 0, pClassInstallParams);
1239 }
1240
1241 return ret;
1242 }
1243
1244 /***********************************************************************
1245 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
1246 */
1247 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN OUT LPPROPSHEETHEADERW PropertySheetHeader,IN DWORD PropertySheetHeaderPageListSize,OUT PDWORD RequiredSize OPTIONAL,IN DWORD PropertySheetType)1248 SetupDiGetClassDevPropertySheetsW(
1249 IN HDEVINFO DeviceInfoSet,
1250 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1251 IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
1252 IN DWORD PropertySheetHeaderPageListSize,
1253 OUT PDWORD RequiredSize OPTIONAL,
1254 IN DWORD PropertySheetType)
1255 {
1256 struct DeviceInfoSet *devInfoSet = NULL;
1257 struct DeviceInfo *devInfo = NULL;
1258 BOOL ret = FALSE;
1259
1260 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
1261 PropertySheetHeader, PropertySheetHeaderPageListSize,
1262 RequiredSize, PropertySheetType);
1263
1264 if (!DeviceInfoSet)
1265 SetLastError(ERROR_INVALID_HANDLE);
1266 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1267 SetLastError(ERROR_INVALID_HANDLE);
1268 else if ((devInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1269 SetLastError(ERROR_INVALID_HANDLE);
1270 else if (!PropertySheetHeader)
1271 SetLastError(ERROR_INVALID_PARAMETER);
1272 else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
1273 SetLastError(ERROR_INVALID_FLAGS);
1274 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1275 SetLastError(ERROR_INVALID_USER_BUFFER);
1276 else if (!DeviceInfoData && IsEqualIID(&devInfoSet->ClassGuid, &GUID_NULL))
1277 SetLastError(ERROR_INVALID_PARAMETER);
1278 else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
1279 && PropertySheetType != DIGCDP_FLAG_BASIC
1280 && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
1281 && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
1282 SetLastError(ERROR_INVALID_PARAMETER);
1283 else
1284 {
1285 HKEY hKey = INVALID_HANDLE_VALUE;
1286 SP_PROPSHEETPAGE_REQUEST Request;
1287 LPWSTR PropPageProvider = NULL;
1288 HMODULE hModule = NULL;
1289 PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
1290 struct ClassDevPropertySheetsData PropPageData;
1291 SP_ADDPROPERTYPAGE_DATA InstallerPropPageData;
1292 DWORD InitialNumberOfPages, i;
1293 DWORD rc;
1294
1295 if (DeviceInfoData)
1296 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1297
1298 /* Get the class property page provider */
1299 if (devInfoSet->hmodClassPropPageProvider == NULL)
1300 {
1301 hKey = SetupDiOpenClassRegKeyExW(devInfo ? &devInfo->ClassGuid : &devInfoSet->ClassGuid, KEY_QUERY_VALUE,
1302 DIOCR_INSTALLER, NULL/*devInfoSet->MachineName + 2*/, NULL);
1303 if (hKey != INVALID_HANDLE_VALUE)
1304 {
1305 rc = SETUP_GetValueString(hKey, REGSTR_VAL_ENUMPROPPAGES_32, &PropPageProvider);
1306 if (rc == ERROR_SUCCESS)
1307 {
1308 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
1309 if (rc != ERROR_SUCCESS)
1310 {
1311 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
1312 goto cleanup;
1313 }
1314
1315 devInfoSet->hmodClassPropPageProvider = hModule;
1316 devInfoSet->pClassPropPageProvider = pPropPageProvider;
1317
1318 HeapFree(GetProcessHeap(), 0, PropPageProvider);
1319 PropPageProvider = NULL;
1320 }
1321
1322 RegCloseKey(hKey);
1323 hKey = INVALID_HANDLE_VALUE;
1324 }
1325 }
1326
1327 /* Get the device property page provider */
1328 if (devInfo != NULL && devInfo->hmodDevicePropPageProvider == NULL)
1329 {
1330 hKey = SETUPDI_OpenDrvKey(devInfoSet->HKLM, devInfo, KEY_QUERY_VALUE);
1331 if (hKey != INVALID_HANDLE_VALUE)
1332 {
1333 rc = SETUP_GetValueString(hKey, REGSTR_VAL_ENUMPROPPAGES_32, &PropPageProvider);
1334 if (rc == ERROR_SUCCESS)
1335 {
1336 rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
1337 if (rc != ERROR_SUCCESS)
1338 {
1339 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
1340 goto cleanup;
1341 }
1342
1343 devInfo->hmodDevicePropPageProvider = hModule;
1344 devInfo->pDevicePropPageProvider = pPropPageProvider;
1345
1346 HeapFree(GetProcessHeap(), 0, PropPageProvider);
1347 PropPageProvider = NULL;
1348 }
1349
1350 RegCloseKey(hKey);
1351 hKey = INVALID_HANDLE_VALUE;
1352 }
1353 }
1354
1355 InitialNumberOfPages = PropertySheetHeader->nPages;
1356
1357 Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
1358 Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
1359 Request.DeviceInfoSet = DeviceInfoSet;
1360 Request.DeviceInfoData = DeviceInfoData;
1361
1362 PropPageData.PropertySheetHeader = PropertySheetHeader;
1363 PropPageData.PropertySheetHeaderPageListSize = PropertySheetHeaderPageListSize;
1364 PropPageData.NumberOfPages = 0;
1365 PropPageData.DontCancel = (RequiredSize != NULL) ? TRUE : FALSE;
1366
1367 /* Call the class property page provider */
1368 if (devInfoSet->pClassPropPageProvider != NULL)
1369 ((PROPERTY_PAGE_PROVIDER)devInfoSet->pClassPropPageProvider)(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
1370
1371 /* Call the device property page provider */
1372 if (devInfo != NULL && devInfo->pDevicePropPageProvider != NULL)
1373 ((PROPERTY_PAGE_PROVIDER)devInfo->pDevicePropPageProvider)(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
1374
1375 /* Call the class installer and add the returned pages */
1376 ZeroMemory(&InstallerPropPageData, sizeof(SP_ADDPROPERTYPAGE_DATA));
1377 InstallerPropPageData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
1378 InstallerPropPageData.ClassInstallHeader.InstallFunction = DIF_ADDPROPERTYPAGE_ADVANCED;
1379 InstallerPropPageData.hwndWizardDlg = PropertySheetHeader->hwndParent;
1380
1381 if (SETUP_CallInstaller(DIF_ADDPROPERTYPAGE_ADVANCED,
1382 DeviceInfoSet,
1383 DeviceInfoData,
1384 &InstallerPropPageData))
1385 {
1386 for (i = 0; i < InstallerPropPageData.NumDynamicPages; i++)
1387 {
1388 if (PropPageData.PropertySheetHeader->nPages < PropertySheetHeaderPageListSize)
1389 {
1390 PropPageData.PropertySheetHeader->phpage[PropPageData.PropertySheetHeader->nPages] =
1391 InstallerPropPageData.DynamicPages[i];
1392 PropPageData.PropertySheetHeader->nPages++;
1393 }
1394 }
1395
1396 PropPageData.NumberOfPages += InstallerPropPageData.NumDynamicPages;
1397 }
1398
1399 if (RequiredSize)
1400 *RequiredSize = PropPageData.NumberOfPages;
1401
1402 if (InitialNumberOfPages + PropPageData.NumberOfPages <= PropertySheetHeaderPageListSize)
1403 {
1404 ret = TRUE;
1405 }
1406 else
1407 {
1408 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1409 }
1410
1411 cleanup:
1412 if (hKey != INVALID_HANDLE_VALUE)
1413 RegCloseKey(hKey);
1414
1415 if (PropPageProvider != NULL)
1416 HeapFree(GetProcessHeap(), 0, PropPageProvider);
1417 }
1418
1419 TRACE("Returning %d\n", ret);
1420 return ret;
1421 }
1422
1423 /***********************************************************************
1424 * SetupDiGetClassRegistryPropertyA(SETUPAPI.@)
1425 */
1426 BOOL WINAPI
SetupDiGetClassRegistryPropertyA(IN CONST GUID * ClassGuid,IN DWORD Property,OUT PDWORD PropertyRegDataType OPTIONAL,OUT PBYTE PropertyBuffer,IN DWORD PropertyBufferSize,OUT PDWORD RequiredSize OPTIONAL,IN PCSTR MachineName OPTIONAL,IN PVOID Reserved)1427 SetupDiGetClassRegistryPropertyA(
1428 IN CONST GUID *ClassGuid,
1429 IN DWORD Property,
1430 OUT PDWORD PropertyRegDataType OPTIONAL,
1431 OUT PBYTE PropertyBuffer,
1432 IN DWORD PropertyBufferSize,
1433 OUT PDWORD RequiredSize OPTIONAL,
1434 IN PCSTR MachineName OPTIONAL,
1435 IN PVOID Reserved)
1436 {
1437 HMACHINE hMachine = NULL;
1438 DWORD PropLength = 0;
1439 DWORD Error = ERROR_SUCCESS;
1440 CONFIGRET cr;
1441
1442 TRACE("%s %lu %p %p %lu %p %s %p\n",
1443 debugstr_guid(ClassGuid), Property, PropertyRegDataType, PropertyBuffer,
1444 PropertyBufferSize, RequiredSize, MachineName, Reserved);
1445
1446 if (Reserved != NULL)
1447 {
1448 SetLastError(ERROR_INVALID_PARAMETER);
1449 return FALSE;
1450 }
1451
1452 if (MachineName)
1453 {
1454 cr = CM_Connect_MachineA(MachineName, &hMachine);
1455 if (cr != CR_SUCCESS)
1456 goto done;
1457 }
1458
1459 if (Property >= SPCRP_MAXIMUM_PROPERTY)
1460 {
1461 cr = CR_INVALID_PROPERTY;
1462 goto done;
1463 }
1464
1465 PropLength = PropertyBufferSize;
1466 cr = CM_Get_Class_Registry_PropertyA((LPGUID)ClassGuid,
1467 Property + (CM_DRP_DEVICEDESC - SPDRP_DEVICEDESC),
1468 PropertyRegDataType,
1469 PropertyBuffer,
1470 &PropLength,
1471 0,
1472 hMachine);
1473 if ((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL))
1474 {
1475 if (RequiredSize)
1476 *RequiredSize = PropLength;
1477 }
1478
1479 done:
1480 if (cr != CR_SUCCESS)
1481 {
1482 switch (cr)
1483 {
1484 case CR_INVALID_DEVINST :
1485 Error = ERROR_NO_SUCH_DEVINST;
1486 break;
1487
1488 case CR_INVALID_PROPERTY :
1489 Error = ERROR_INVALID_REG_PROPERTY;
1490 break;
1491
1492 case CR_BUFFER_SMALL :
1493 Error = ERROR_INSUFFICIENT_BUFFER;
1494 break;
1495
1496 default :
1497 Error = GetErrorCodeFromCrCode(cr);
1498 }
1499 }
1500
1501 if (hMachine != NULL)
1502 CM_Disconnect_Machine(hMachine);
1503
1504 SetLastError(Error);
1505 return (cr == CR_SUCCESS);
1506 }
1507
1508 /***********************************************************************
1509 * SetupDiGetClassRegistryPropertyW(SETUPAPI.@)
1510 */
1511 BOOL WINAPI
SetupDiGetClassRegistryPropertyW(IN CONST GUID * ClassGuid,IN DWORD Property,OUT PDWORD PropertyRegDataType OPTIONAL,OUT PBYTE PropertyBuffer,IN DWORD PropertyBufferSize,OUT PDWORD RequiredSize OPTIONAL,IN PCWSTR MachineName OPTIONAL,IN PVOID Reserved)1512 SetupDiGetClassRegistryPropertyW(
1513 IN CONST GUID *ClassGuid,
1514 IN DWORD Property,
1515 OUT PDWORD PropertyRegDataType OPTIONAL,
1516 OUT PBYTE PropertyBuffer,
1517 IN DWORD PropertyBufferSize,
1518 OUT PDWORD RequiredSize OPTIONAL,
1519 IN PCWSTR MachineName OPTIONAL,
1520 IN PVOID Reserved)
1521 {
1522 HMACHINE hMachine = NULL;
1523 DWORD PropLength = 0;
1524 DWORD Error = ERROR_SUCCESS;
1525 CONFIGRET cr;
1526
1527 TRACE("%s %lu %p %p %lu %p %s %p\n",
1528 debugstr_guid(ClassGuid), Property, PropertyRegDataType, PropertyBuffer,
1529 PropertyBufferSize, RequiredSize, debugstr_w(MachineName), Reserved);
1530
1531 if (Reserved != NULL)
1532 {
1533 SetLastError(ERROR_INVALID_PARAMETER);
1534 return FALSE;
1535 }
1536
1537 if (MachineName)
1538 {
1539 cr = CM_Connect_MachineW(MachineName, &hMachine);
1540 if (cr != CR_SUCCESS)
1541 goto done;
1542 }
1543
1544 if (Property >= SPCRP_MAXIMUM_PROPERTY)
1545 {
1546 cr = CR_INVALID_PROPERTY;
1547 goto done;
1548 }
1549
1550 PropLength = PropertyBufferSize;
1551 cr = CM_Get_Class_Registry_PropertyW((LPGUID)ClassGuid,
1552 Property + (CM_DRP_DEVICEDESC - SPDRP_DEVICEDESC),
1553 PropertyRegDataType,
1554 PropertyBuffer,
1555 &PropLength,
1556 0,
1557 hMachine);
1558 if ((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL))
1559 {
1560 if (RequiredSize)
1561 *RequiredSize = PropLength;
1562 }
1563
1564 done:
1565 if (cr != CR_SUCCESS)
1566 {
1567 switch (cr)
1568 {
1569 case CR_INVALID_DEVINST :
1570 Error = ERROR_NO_SUCH_DEVINST;
1571 break;
1572
1573 case CR_INVALID_PROPERTY :
1574 Error = ERROR_INVALID_REG_PROPERTY;
1575 break;
1576
1577 case CR_BUFFER_SMALL :
1578 Error = ERROR_INSUFFICIENT_BUFFER;
1579 break;
1580
1581 default :
1582 Error = GetErrorCodeFromCrCode(cr);
1583 }
1584 }
1585
1586 if (hMachine != NULL)
1587 CM_Disconnect_Machine(hMachine);
1588
1589 SetLastError(Error);
1590 return (cr == CR_SUCCESS);
1591 }
1592
1593 /***********************************************************************
1594 * SetupDiSetClassRegistryPropertyA(SETUPAPI.@)
1595 */
1596 BOOL WINAPI
SetupDiSetClassRegistryPropertyA(IN CONST GUID * ClassGuid,IN DWORD Property,IN CONST BYTE * PropertyBuffer OPTIONAL,IN DWORD PropertyBufferSize,IN PCSTR MachineName OPTIONAL,IN PVOID Reserved)1597 SetupDiSetClassRegistryPropertyA(
1598 IN CONST GUID *ClassGuid,
1599 IN DWORD Property,
1600 IN CONST BYTE *PropertyBuffer OPTIONAL,
1601 IN DWORD PropertyBufferSize,
1602 IN PCSTR MachineName OPTIONAL,
1603 IN PVOID Reserved)
1604 {
1605 HMACHINE hMachine = NULL;
1606 DWORD Error = ERROR_SUCCESS;
1607 CONFIGRET cr;
1608
1609 TRACE("%s %lu %p %lu %s %p\n",
1610 debugstr_guid(ClassGuid), Property, PropertyBuffer,
1611 PropertyBufferSize, MachineName, Reserved);
1612
1613 if (Reserved != NULL)
1614 {
1615 SetLastError(ERROR_INVALID_PARAMETER);
1616 return FALSE;
1617 }
1618
1619 if (MachineName)
1620 {
1621 cr = CM_Connect_MachineA(MachineName, &hMachine);
1622 if (cr != CR_SUCCESS)
1623 goto done;
1624 }
1625
1626 if (Property >= SPCRP_MAXIMUM_PROPERTY)
1627 {
1628 cr = CR_INVALID_PROPERTY;
1629 goto done;
1630 }
1631
1632 cr = CM_Set_Class_Registry_PropertyA((LPGUID)ClassGuid,
1633 Property + (CM_DRP_DEVICEDESC - SPDRP_DEVICEDESC),
1634 PropertyBuffer,
1635 PropertyBufferSize,
1636 0,
1637 hMachine);
1638
1639 done:
1640 if (cr != CR_SUCCESS)
1641 {
1642 switch (cr)
1643 {
1644 case CR_INVALID_DEVINST:
1645 Error = ERROR_NO_SUCH_DEVINST;
1646 break;
1647
1648 case CR_INVALID_PROPERTY:
1649 Error = ERROR_INVALID_REG_PROPERTY;
1650 break;
1651
1652 case CR_BUFFER_SMALL:
1653 Error = ERROR_INSUFFICIENT_BUFFER;
1654 break;
1655
1656 default :
1657 Error = GetErrorCodeFromCrCode(cr);
1658 }
1659 }
1660
1661 if (hMachine != NULL)
1662 CM_Disconnect_Machine(hMachine);
1663
1664 SetLastError(Error);
1665 return (cr == CR_SUCCESS);
1666 }
1667
1668 /***********************************************************************
1669 * SetupDiSetClassRegistryPropertyW(SETUPAPI.@)
1670 */
1671 BOOL WINAPI
SetupDiSetClassRegistryPropertyW(IN CONST GUID * ClassGuid,IN DWORD Property,IN CONST BYTE * PropertyBuffer OPTIONAL,IN DWORD PropertyBufferSize,IN PCWSTR MachineName OPTIONAL,IN PVOID Reserved)1672 SetupDiSetClassRegistryPropertyW(
1673 IN CONST GUID *ClassGuid,
1674 IN DWORD Property,
1675 IN CONST BYTE *PropertyBuffer OPTIONAL,
1676 IN DWORD PropertyBufferSize,
1677 IN PCWSTR MachineName OPTIONAL,
1678 IN PVOID Reserved)
1679 {
1680 HMACHINE hMachine = NULL;
1681 DWORD Error = ERROR_SUCCESS;
1682 CONFIGRET cr;
1683
1684 TRACE("%s %lu %p %lu %s %p\n",
1685 debugstr_guid(ClassGuid), Property, PropertyBuffer,
1686 PropertyBufferSize, debugstr_w(MachineName), Reserved);
1687
1688 if (Reserved != NULL)
1689 {
1690 SetLastError(ERROR_INVALID_PARAMETER);
1691 return FALSE;
1692 }
1693
1694 if (MachineName)
1695 {
1696 cr = CM_Connect_MachineW(MachineName, &hMachine);
1697 if (cr != CR_SUCCESS)
1698 goto done;
1699 }
1700
1701 if (Property >= SPCRP_MAXIMUM_PROPERTY)
1702 {
1703 cr = CR_INVALID_PROPERTY;
1704 goto done;
1705 }
1706
1707 cr = CM_Set_Class_Registry_PropertyW((LPGUID)ClassGuid,
1708 Property + (CM_DRP_DEVICEDESC - SPDRP_DEVICEDESC),
1709 PropertyBuffer,
1710 PropertyBufferSize,
1711 0,
1712 hMachine);
1713
1714 done:
1715 if (cr != CR_SUCCESS)
1716 {
1717 switch (cr)
1718 {
1719 case CR_INVALID_DEVINST:
1720 Error = ERROR_NO_SUCH_DEVINST;
1721 break;
1722
1723 case CR_INVALID_PROPERTY:
1724 Error = ERROR_INVALID_REG_PROPERTY;
1725 break;
1726
1727 case CR_BUFFER_SMALL:
1728 Error = ERROR_INSUFFICIENT_BUFFER;
1729 break;
1730
1731 default :
1732 Error = GetErrorCodeFromCrCode(cr);
1733 }
1734 }
1735
1736 if (hMachine != NULL)
1737 CM_Disconnect_Machine(hMachine);
1738
1739 SetLastError(Error);
1740 return (cr == CR_SUCCESS);
1741 }
1742