- Do not write beyond the buffer.
[reactos.git] / reactos / dll / win32 / setupapi / devinst.c
1 /*
2 * SetupAPI device installer
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 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
25
26 /* Unicode constants */
27 static const WCHAR BackSlash[] = {'\\',0};
28 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class[] = {'C','l','a','s','s',0};
30 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
31 static const WCHAR DotHW[] = {'.','H','W',0};
32 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
34
35 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
39 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
40
41 typedef DWORD
42 (CALLBACK* CLASS_INSTALL_PROC) (
43 IN DI_FUNCTION InstallFunction,
44 IN HDEVINFO DeviceInfoSet,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
46 typedef BOOL
47 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
48 IN HDEVINFO DeviceInfoSet,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
50 typedef DWORD
51 (CALLBACK* COINSTALLER_PROC) (
52 IN DI_FUNCTION InstallFunction,
53 IN HDEVINFO DeviceInfoSet,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
56
57 struct CoInstallerElement
58 {
59 LIST_ENTRY ListEntry;
60
61 HMODULE Module;
62 COINSTALLER_PROC Function;
63 BOOL DoPostProcessing;
64 PVOID PrivateData;
65 };
66
67 struct GetSectionCallbackInfo
68 {
69 PSP_ALTPLATFORM_INFO PlatformInfo;
70 BYTE ProductType;
71 WORD SuiteMask;
72 DWORD PrefixLength;
73 WCHAR BestSection[LINE_LEN + 1];
74 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5;
75 };
76
77
78 /***********************************************************************
79 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
80 */
81 HDEVINFO WINAPI
82 SetupDiCreateDeviceInfoList(
83 IN CONST GUID *ClassGuid OPTIONAL,
84 IN HWND hwndParent OPTIONAL)
85 {
86 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
87 }
88
89 /***********************************************************************
90 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
91 */
92 HDEVINFO WINAPI
93 SetupDiCreateDeviceInfoListExA(
94 IN CONST GUID *ClassGuid OPTIONAL,
95 IN HWND hwndParent OPTIONAL,
96 IN PCSTR MachineName OPTIONAL,
97 IN PVOID Reserved)
98 {
99 LPWSTR MachineNameW = NULL;
100 HDEVINFO hDevInfo;
101
102 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
103 debugstr_a(MachineName), Reserved);
104
105 if (MachineName)
106 {
107 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
108 if (MachineNameW == NULL)
109 return (HDEVINFO)INVALID_HANDLE_VALUE;
110 }
111
112 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
113 MachineNameW, Reserved);
114
115 MyFree(MachineNameW);
116
117 return hDevInfo;
118 }
119
120 static DWORD
121 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
122 {
123 switch (cr)
124 {
125 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
126 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
127 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
128 case CR_FAILURE: return ERROR_GEN_FAILURE;
129 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER;
130 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER;
131 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
132 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER;
133 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
134 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER;
135 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER;
136 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND;
137 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
138 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND;
139 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
140 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE;
141 case CR_SUCCESS: return ERROR_SUCCESS;
142 default: return ERROR_GEN_FAILURE;
143 }
144
145 /* Does not happen */
146 }
147
148 /***********************************************************************
149 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
150 *
151 * Create an empty DeviceInfoSet list.
152 *
153 * PARAMS
154 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
155 * with this list.
156 * hwndParent [I] hwnd needed for interface related actions.
157 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
158 * local regestry will be used.
159 * Reserved [I] must be NULL
160 *
161 * RETURNS
162 * Success: empty list.
163 * Failure: INVALID_HANDLE_VALUE.
164 */
165 HDEVINFO WINAPI
166 SetupDiCreateDeviceInfoListExW(
167 IN CONST GUID *ClassGuid OPTIONAL,
168 IN HWND hwndParent OPTIONAL,
169 IN PCWSTR MachineName OPTIONAL,
170 IN PVOID Reserved)
171 {
172 struct DeviceInfoSet *list;
173 LPWSTR UNCServerName = NULL;
174 DWORD size;
175 DWORD rc;
176 CONFIGRET cr;
177 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;;
178
179 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
180 debugstr_w(MachineName), Reserved);
181
182 size = FIELD_OFFSET(struct DeviceInfoSet, szData);
183 if (MachineName)
184 size += (strlenW(MachineName) + 3) * sizeof(WCHAR);
185 list = MyMalloc(size);
186 if (!list)
187 {
188 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
189 goto cleanup;
190 }
191 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
192
193 list->magic = SETUP_DEV_INFO_SET_MAGIC;
194 memcpy(
195 &list->ClassGuid,
196 ClassGuid ? ClassGuid : &GUID_NULL,
197 sizeof(list->ClassGuid));
198 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
199 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
200 list->InstallParams.hwndParent = hwndParent;
201 if (MachineName)
202 {
203 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
204 if (rc != ERROR_SUCCESS)
205 {
206 SetLastError(rc);
207 goto cleanup;
208 }
209 UNCServerName = MyMalloc((strlenW(MachineName) + 3) * sizeof(WCHAR));
210 if (!UNCServerName)
211 {
212 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
213 goto cleanup;
214 }
215
216 UNCServerName[0] = UNCServerName[1] = '\\';
217 strcpyW(UNCServerName + 2, MachineName);
218 list->szData[0] = list->szData[1] = '\\';
219 strcpyW(list->szData + 2, MachineName);
220 list->MachineName = list->szData;
221 }
222 else
223 {
224 list->HKLM = HKEY_LOCAL_MACHINE;
225 list->MachineName = NULL;
226 }
227 cr = CM_Connect_MachineW(UNCServerName, &list->hMachine);
228 if (cr != CR_SUCCESS)
229 {
230 SetLastError(GetErrorCodeFromCrCode(cr));
231 goto cleanup;
232 }
233 InitializeListHead(&list->DriverListHead);
234 InitializeListHead(&list->ListHead);
235
236 ret = (HDEVINFO)list;
237
238 cleanup:
239 if (ret == INVALID_HANDLE_VALUE)
240 {
241 if (list)
242 {
243 if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
244 RegCloseKey(list->HKLM);
245 MyFree(list);
246 }
247 }
248 MyFree(UNCServerName);
249 return ret;
250 }
251
252 /***********************************************************************
253 * SetupDiEnumDeviceInfo (SETUPAPI.@)
254 */
255 BOOL WINAPI
256 SetupDiEnumDeviceInfo(
257 IN HDEVINFO DeviceInfoSet,
258 IN DWORD MemberIndex,
259 OUT PSP_DEVINFO_DATA DeviceInfoData)
260 {
261 BOOL ret = FALSE;
262
263 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet, MemberIndex, DeviceInfoData);
264 if (!DeviceInfoData)
265 SetLastError(ERROR_INVALID_PARAMETER);
266 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
267 {
268 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
269
270 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
271 SetLastError(ERROR_INVALID_HANDLE);
272 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
273 SetLastError(ERROR_INVALID_USER_BUFFER);
274 else
275 {
276 PLIST_ENTRY ItemList = list->ListHead.Flink;
277 while (ItemList != &list->ListHead && MemberIndex-- > 0)
278 ItemList = ItemList->Flink;
279 if (ItemList == &list->ListHead)
280 SetLastError(ERROR_NO_MORE_ITEMS);
281 else
282 {
283 struct DeviceInfoElement *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfoElement, ListEntry);
284 memcpy(&DeviceInfoData->ClassGuid,
285 &DevInfo->ClassGuid,
286 sizeof(GUID));
287 DeviceInfoData->DevInst = DevInfo->dnDevInst;
288 DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
289 ret = TRUE;
290 }
291 }
292 }
293 else
294 SetLastError(ERROR_INVALID_HANDLE);
295 return ret;
296 }
297
298 /***********************************************************************
299 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
300 */
301 BOOL WINAPI
302 SetupDiGetActualSectionToInstallA(
303 IN HINF InfHandle,
304 IN PCSTR InfSectionName,
305 OUT PSTR InfSectionWithExt OPTIONAL,
306 IN DWORD InfSectionWithExtSize,
307 OUT PDWORD RequiredSize OPTIONAL,
308 OUT PSTR *Extension OPTIONAL)
309 {
310 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
311 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
312 Extension, NULL);
313 }
314
315 /***********************************************************************
316 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
317 */
318 BOOL WINAPI
319 SetupDiGetActualSectionToInstallW(
320 IN HINF InfHandle,
321 IN PCWSTR InfSectionName,
322 OUT PWSTR InfSectionWithExt OPTIONAL,
323 IN DWORD InfSectionWithExtSize,
324 OUT PDWORD RequiredSize OPTIONAL,
325 OUT PWSTR *Extension OPTIONAL)
326 {
327 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
328 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
329 Extension, NULL);
330 }
331
332 /***********************************************************************
333 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
334 */
335 BOOL WINAPI
336 SetupDiGetActualSectionToInstallExA(
337 IN HINF InfHandle,
338 IN PCSTR InfSectionName,
339 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
340 OUT PSTR InfSectionWithExt OPTIONAL,
341 IN DWORD InfSectionWithExtSize,
342 OUT PDWORD RequiredSize OPTIONAL,
343 OUT PSTR* Extension OPTIONAL,
344 IN PVOID Reserved)
345 {
346 LPWSTR InfSectionNameW = NULL;
347 LPWSTR InfSectionWithExtW = NULL;
348 PWSTR ExtensionW;
349 BOOL bResult = FALSE;
350
351 TRACE("\n");
352
353 if (InfSectionName)
354 {
355 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
356 if (InfSectionNameW == NULL)
357 goto cleanup;
358 }
359 if (InfSectionWithExt)
360 {
361 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
362 if (InfSectionWithExtW == NULL)
363 goto cleanup;
364 }
365
366 bResult = SetupDiGetActualSectionToInstallExW(
367 InfHandle, InfSectionNameW, AlternatePlatformInfo,
368 InfSectionWithExt ? InfSectionWithExtW : NULL,
369 InfSectionWithExtSize,
370 RequiredSize,
371 Extension ? &ExtensionW : NULL,
372 Reserved);
373
374 if (bResult && InfSectionWithExt)
375 {
376 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
377 InfSectionWithExtSize, NULL, NULL) != 0;
378 }
379 if (bResult && Extension)
380 {
381 if (ExtensionW == NULL)
382 *Extension = NULL;
383 else
384 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
385 }
386
387 cleanup:
388 MyFree(InfSectionNameW);
389 MyFree(InfSectionWithExtW);
390
391 return bResult;
392 }
393
394 /* Lower scores are best ones */
395 static BOOL
396 CheckSectionValid(
397 IN LPCWSTR SectionName,
398 IN PSP_ALTPLATFORM_INFO PlatformInfo,
399 IN BYTE ProductType,
400 IN WORD SuiteMask,
401 OUT PDWORD ScorePlatform,
402 OUT PDWORD ScoreMajorVersion,
403 OUT PDWORD ScoreMinorVersion,
404 OUT PDWORD ScoreProductType,
405 OUT PDWORD ScoreSuiteMask)
406 {
407 LPWSTR Section = NULL;
408 LPCWSTR pExtensionPlatform, pExtensionArchitecture;
409 LPWSTR Fields[6];
410 DWORD i;
411 BOOL ret = FALSE;
412
413 static const WCHAR ExtensionPlatformNone[] = {'.',0};
414 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
415 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
416
417 static const WCHAR ExtensionArchitectureNone[] = {0};
418 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
419 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
420 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
421 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
422 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
423 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
424
425 TRACE("%s %p 0x%x 0x%x\n",
426 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
427
428 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
429
430 Section = DuplicateString(SectionName);
431 if (!Section)
432 {
433 TRACE("DuplicateString() failed\n");
434 goto cleanup;
435 }
436
437 /* Set various extensions values */
438 switch (PlatformInfo->Platform)
439 {
440 case VER_PLATFORM_WIN32_WINDOWS:
441 pExtensionPlatform = ExtensionPlatformWindows;
442 break;
443 case VER_PLATFORM_WIN32_NT:
444 pExtensionPlatform = ExtensionPlatformNT;
445 break;
446 default:
447 ERR("Unkown platform 0x%lx\n", PlatformInfo->Platform);
448 pExtensionPlatform = ExtensionPlatformNone;
449 break;
450 }
451 switch (PlatformInfo->ProcessorArchitecture)
452 {
453 case PROCESSOR_ARCHITECTURE_ALPHA:
454 pExtensionArchitecture = ExtensionArchitecturealpha;
455 break;
456 case PROCESSOR_ARCHITECTURE_AMD64:
457 pExtensionArchitecture = ExtensionArchitectureamd64;
458 break;
459 case PROCESSOR_ARCHITECTURE_IA64:
460 pExtensionArchitecture = ExtensionArchitectureia64;
461 break;
462 case PROCESSOR_ARCHITECTURE_INTEL:
463 pExtensionArchitecture = ExtensionArchitecturex86;
464 break;
465 case PROCESSOR_ARCHITECTURE_MIPS:
466 pExtensionArchitecture = ExtensionArchitecturemips;
467 break;
468 case PROCESSOR_ARCHITECTURE_PPC:
469 pExtensionArchitecture = ExtensionArchitectureppc;
470 break;
471 default:
472 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
473 case PROCESSOR_ARCHITECTURE_UNKNOWN:
474 pExtensionArchitecture = ExtensionArchitectureNone;
475 break;
476 }
477
478 /*
479 * Field[0] Platform
480 * Field[1] Architecture
481 * Field[2] Major version
482 * Field[3] Minor version
483 * Field[4] Product type
484 * Field[5] Suite mask
485 * Remark: lastests fields may be NULL if the information is not provided
486 */
487 Fields[0] = Section;
488 if (Fields[0] == NULL)
489 {
490 TRACE("No extension found\n");
491 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
492 ret = TRUE;
493 goto cleanup;
494 }
495 Fields[1] = Fields[0] + 1;
496 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
497 for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
498 {
499 Fields[i] = wcschr(Fields[i - 1], '.');
500 if (Fields[i])
501 {
502 Fields[i]++;
503 *(Fields[i] - 1) = L'\0';
504 }
505 }
506 /* Take care of first 2 fields */
507 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
508 {
509 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
510 {
511 TRACE("Mismatch on platform field\n");
512 goto cleanup;
513 }
514 Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
515 }
516 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
517 {
518 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
519 {
520 TRACE("Mismatch on platform field\n");
521 goto cleanup;
522 }
523 Fields[1] += wcslen(ExtensionPlatformNT) - 1;
524 }
525 else
526 {
527 /* No platform specified */
528 *ScorePlatform |= 0x02;
529 }
530 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
531 {
532 /* No architecture specified */
533 *ScorePlatform |= 0x01;
534 }
535 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
536 {
537 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
538 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
539 goto cleanup;
540 }
541
542 /* Check if informations are matching */
543 if (Fields[2] && *Fields[2])
544 {
545 DWORD MajorVersion, MinorVersion = 0;
546 MajorVersion = strtoulW(Fields[2], NULL, 0);
547 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
548 (errno == ERANGE || errno == EINVAL))
549 {
550 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
551 goto cleanup;
552 }
553 if (Fields[3] && *Fields[3])
554 {
555 MinorVersion = strtoulW(Fields[3], NULL, 0);
556 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
557 (errno == ERANGE || errno == EINVAL))
558 {
559 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
560 goto cleanup;
561 }
562 }
563 if (PlatformInfo->MajorVersion < MajorVersion ||
564 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
565 {
566 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
567 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
568 goto cleanup;
569 }
570 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
571 if (MajorVersion == PlatformInfo->MajorVersion)
572 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
573 else
574 *ScoreMinorVersion = MinorVersion;
575 }
576 else if (Fields[3] && *Fields[3])
577 {
578 TRACE("Minor version found without major version\n");
579 goto cleanup;
580 }
581 else
582 {
583 *ScoreMajorVersion = PlatformInfo->MajorVersion;
584 *ScoreMinorVersion = PlatformInfo->MinorVersion;
585 }
586
587 if (Fields[4] && *Fields[4])
588 {
589 DWORD CurrentProductType;
590 CurrentProductType = strtoulW(Fields[4], NULL, 0);
591 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
592 (errno == ERANGE || errno == EINVAL))
593 {
594 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
595 goto cleanup;
596 }
597 if (CurrentProductType != ProductType)
598 {
599 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
600 CurrentProductType, ProductType);
601 goto cleanup;
602 }
603 }
604 else
605 *ScoreProductType = 1;
606
607 if (Fields[5] && *Fields[5])
608 {
609 DWORD CurrentSuiteMask;
610 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
611 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
612 (errno == ERANGE || errno == EINVAL))
613 {
614 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
615 goto cleanup;
616 }
617 if ((CurrentSuiteMask & ~SuiteMask) != 0)
618 {
619 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
620 CurrentSuiteMask, SuiteMask);
621 goto cleanup;
622 }
623 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
624 }
625 else
626 *ScoreSuiteMask = SuiteMask;
627
628 ret = TRUE;
629
630 cleanup:
631 MyFree(Section);
632 return ret;
633 }
634
635 static BOOL
636 GetSectionCallback(
637 IN LPCWSTR SectionName,
638 IN PVOID Context)
639 {
640 struct GetSectionCallbackInfo *info = Context;
641 DWORD Score1, Score2, Score3, Score4, Score5;
642 BOOL ret;
643
644 if (SectionName[info->PrefixLength] != '.')
645 return TRUE;
646
647 ret = CheckSectionValid(
648 &SectionName[info->PrefixLength],
649 info->PlatformInfo,
650 info->ProductType,
651 info->SuiteMask,
652 &Score1, &Score2, &Score3, &Score4, &Score5);
653 if (!ret)
654 {
655 TRACE("Section %s not compatible\n", debugstr_w(SectionName));
656 return TRUE;
657 }
658 if (Score1 > info->BestScore1) goto done;
659 if (Score1 < info->BestScore1) goto bettersection;
660 if (Score2 > info->BestScore2) goto done;
661 if (Score2 < info->BestScore2) goto bettersection;
662 if (Score3 > info->BestScore3) goto done;
663 if (Score3 < info->BestScore3) goto bettersection;
664 if (Score4 > info->BestScore4) goto done;
665 if (Score4 < info->BestScore4) goto bettersection;
666 if (Score5 > info->BestScore5) goto done;
667 if (Score5 < info->BestScore5) goto bettersection;
668 goto done;
669
670 bettersection:
671 strcpyW(info->BestSection, SectionName);
672 info->BestScore1 = Score1;
673 info->BestScore2 = Score2;
674 info->BestScore3 = Score3;
675 info->BestScore4 = Score4;
676 info->BestScore5 = Score5;
677
678 done:
679 return TRUE;
680 }
681
682 /***********************************************************************
683 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
684 */
685 BOOL WINAPI
686 SetupDiGetActualSectionToInstallExW(
687 IN HINF InfHandle,
688 IN PCWSTR InfSectionName,
689 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
690 OUT PWSTR InfSectionWithExt OPTIONAL,
691 IN DWORD InfSectionWithExtSize,
692 OUT PDWORD RequiredSize OPTIONAL,
693 OUT PWSTR* Extension OPTIONAL,
694 IN PVOID Reserved)
695 {
696 BOOL ret = FALSE;
697
698 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
699 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
700 RequiredSize, Extension, Reserved);
701
702 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
703 SetLastError(ERROR_INVALID_HANDLE);
704 else if (!InfSectionName)
705 SetLastError(ERROR_INVALID_PARAMETER);
706 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
707 SetLastError(ERROR_INVALID_USER_BUFFER);
708 else if (Reserved != NULL)
709 SetLastError(ERROR_INVALID_PARAMETER);
710 else
711 {
712 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
713 static BYTE CurrentProductType = 0;
714 static WORD CurrentSuiteMask = 0;
715 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
716 struct GetSectionCallbackInfo CallbackInfo;
717 DWORD dwFullLength;
718 BYTE ProductType;
719 WORD SuiteMask;
720
721 /* Fill platform info if needed */
722 if (AlternatePlatformInfo)
723 {
724 pPlatformInfo = AlternatePlatformInfo;
725 ProductType = 0;
726 SuiteMask = 0;
727 }
728 else
729 {
730 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
731 {
732 /* That's the first time we go here. We need to fill in the structure */
733 OSVERSIONINFOEX VersionInfo;
734 SYSTEM_INFO SystemInfo;
735 VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
736 ret = GetVersionEx((POSVERSIONINFO)&VersionInfo);
737 if (!ret)
738 goto done;
739 GetSystemInfo(&SystemInfo);
740 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
741 CurrentPlatform.Platform = VersionInfo.dwPlatformId;
742 CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
743 CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
744 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
745 CurrentPlatform.Reserved = 0;
746 CurrentProductType = VersionInfo.wProductType;
747 CurrentSuiteMask = VersionInfo.wSuiteMask;
748 }
749 ProductType = CurrentProductType;
750 SuiteMask = CurrentSuiteMask;
751 }
752
753 CallbackInfo.PlatformInfo = pPlatformInfo;
754 CallbackInfo.ProductType = ProductType;
755 CallbackInfo.SuiteMask = SuiteMask;
756 CallbackInfo.PrefixLength = strlenW(InfSectionName);
757 CallbackInfo.BestScore1 = ULONG_MAX;
758 CallbackInfo.BestScore2 = ULONG_MAX;
759 CallbackInfo.BestScore3 = ULONG_MAX;
760 CallbackInfo.BestScore4 = ULONG_MAX;
761 CallbackInfo.BestScore5 = ULONG_MAX;
762 strcpyW(CallbackInfo.BestSection, InfSectionName);
763 if (!EnumerateSectionsStartingWith(
764 InfHandle,
765 InfSectionName,
766 GetSectionCallback,
767 &CallbackInfo))
768 {
769 SetLastError(ERROR_GEN_FAILURE);
770 goto done;
771 }
772
773 dwFullLength = lstrlenW(CallbackInfo.BestSection);
774 if (RequiredSize != NULL)
775 *RequiredSize = dwFullLength + 1;
776
777 if (InfSectionWithExtSize > 0)
778 {
779 if (InfSectionWithExtSize < dwFullLength + 1)
780 {
781 SetLastError(ERROR_INSUFFICIENT_BUFFER);
782 goto done;
783 }
784 strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
785 if (Extension)
786 {
787 DWORD dwLength = lstrlenW(InfSectionName);
788 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
789 }
790 }
791
792 ret = TRUE;
793 }
794
795 done:
796 TRACE("Returning %d\n", ret);
797 return ret;
798 }
799
800
801 BOOL
802 CreateDeviceInfoElement(
803 IN struct DeviceInfoSet *list,
804 IN LPCWSTR InstancePath,
805 IN LPCGUID pClassGuid,
806 OUT struct DeviceInfoElement **pDeviceInfo)
807 {
808 DWORD size;
809 CONFIGRET cr;
810 struct DeviceInfoElement *deviceInfo;
811
812 *pDeviceInfo = NULL;
813
814 size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
815 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
816 if (!deviceInfo)
817 {
818 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
819 return FALSE;
820 }
821 ZeroMemory(deviceInfo, size);
822
823 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
824 if (cr != CR_SUCCESS)
825 {
826 SetLastError(GetErrorCodeFromCrCode(cr));
827 return FALSE;
828 }
829
830 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
831 strcpyW(deviceInfo->Data, InstancePath);
832 deviceInfo->DeviceName = deviceInfo->Data;
833 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
834 deviceInfo->DeviceDescription = NULL;
835 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
836 deviceInfo->CreationFlags = 0;
837 InitializeListHead(&deviceInfo->DriverListHead);
838 InitializeListHead(&deviceInfo->InterfaceListHead);
839
840 *pDeviceInfo = deviceInfo;
841 return TRUE;
842 }
843
844
845 static BOOL
846 DestroyClassInstallParams(struct ClassInstallParams* installParams)
847 {
848 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
849 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
850 return TRUE;
851 }
852
853 static BOOL
854 DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
855 {
856 PLIST_ENTRY ListEntry;
857 struct DriverInfoElement *driverInfo;
858 struct DeviceInterface *deviceInterface;
859
860 while (!IsListEmpty(&deviceInfo->DriverListHead))
861 {
862 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
863 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
864 if (!DestroyDriverInfoElement(driverInfo))
865 return FALSE;
866 }
867 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
868 {
869 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
870 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
871 if (!DestroyDeviceInterface(deviceInterface))
872 return FALSE;
873 }
874 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
875 return HeapFree(GetProcessHeap(), 0, deviceInfo);
876 }
877
878 static BOOL
879 DestroyDeviceInfoSet(struct DeviceInfoSet* list)
880 {
881 PLIST_ENTRY ListEntry;
882 struct DeviceInfoElement *deviceInfo;
883
884 while (!IsListEmpty(&list->ListHead))
885 {
886 ListEntry = RemoveHeadList(&list->ListHead);
887 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfoElement, ListEntry);
888 if (!DestroyDeviceInfoElement(deviceInfo))
889 return FALSE;
890 }
891 if (list->HKLM != HKEY_LOCAL_MACHINE)
892 RegCloseKey(list->HKLM);
893 CM_Disconnect_Machine(list->hMachine);
894 DestroyClassInstallParams(&list->ClassInstallParams);
895 return HeapFree(GetProcessHeap(), 0, list);
896 }
897
898 /***********************************************************************
899 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
900 */
901 BOOL WINAPI
902 SetupDiDestroyDeviceInfoList(
903 IN HDEVINFO DeviceInfoSet)
904 {
905 BOOL ret = FALSE;
906
907 TRACE("%p\n", DeviceInfoSet);
908 if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
909 {
910 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
911
912 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
913 ret = DestroyDeviceInfoSet(list);
914 else
915 SetLastError(ERROR_INVALID_HANDLE);
916 }
917 else
918 SetLastError(ERROR_INVALID_HANDLE);
919
920 TRACE("Returning %d\n", ret);
921 return ret;
922 }
923
924 /***********************************************************************
925 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
926 */
927 BOOL WINAPI
928 SetupDiGetDeviceRegistryPropertyA(
929 IN HDEVINFO DeviceInfoSet,
930 IN PSP_DEVINFO_DATA DeviceInfoData,
931 IN DWORD Property,
932 OUT PDWORD PropertyRegDataType OPTIONAL,
933 OUT PBYTE PropertyBuffer OPTIONAL,
934 IN DWORD PropertyBufferSize,
935 OUT PDWORD RequiredSize OPTIONAL)
936 {
937 BOOL bResult;
938 BOOL bIsStringProperty;
939 DWORD RegType;
940 DWORD RequiredSizeA, RequiredSizeW;
941 DWORD PropertyBufferSizeW = 0;
942 PBYTE PropertyBufferW = NULL;
943
944 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
945 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
946 RequiredSize);
947
948 if (PropertyBufferSize != 0)
949 {
950 PropertyBufferSizeW = PropertyBufferSize * 2;
951 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
952 if (!PropertyBufferW)
953 {
954 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
955 return FALSE;
956 }
957 }
958
959 bResult = SetupDiGetDeviceRegistryPropertyW(
960 DeviceInfoSet,
961 DeviceInfoData,
962 Property,
963 &RegType,
964 PropertyBufferW,
965 PropertyBufferSizeW,
966 &RequiredSizeW);
967
968 if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
969 {
970 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
971
972 if (bIsStringProperty)
973 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
974 else
975 RequiredSizeA = RequiredSizeW;
976 if (RequiredSize)
977 *RequiredSize = RequiredSizeA;
978 if (PropertyRegDataType)
979 *PropertyRegDataType = RegType;
980 }
981
982 if (!bResult)
983 {
984 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
985 return bResult;
986 }
987
988 if (RequiredSizeA <= PropertyBufferSize)
989 {
990 if (bIsStringProperty && PropertyBufferSize > 0)
991 {
992 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
993 {
994 /* Last error is already set by WideCharToMultiByte */
995 bResult = FALSE;
996 }
997 }
998 else
999 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
1000 }
1001 else
1002 {
1003 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1004 bResult = FALSE;
1005 }
1006
1007 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
1008 return bResult;
1009 }
1010
1011 /***********************************************************************
1012 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1013 */
1014 BOOL WINAPI
1015 SetupDiGetDeviceRegistryPropertyW(
1016 IN HDEVINFO DeviceInfoSet,
1017 IN PSP_DEVINFO_DATA DeviceInfoData,
1018 IN DWORD Property,
1019 OUT PDWORD PropertyRegDataType OPTIONAL,
1020 OUT PBYTE PropertyBuffer OPTIONAL,
1021 IN DWORD PropertyBufferSize,
1022 OUT PDWORD RequiredSize OPTIONAL)
1023 {
1024 HKEY hEnumKey, hKey;
1025 DWORD rc;
1026 BOOL ret = FALSE;
1027
1028 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
1029 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1030 RequiredSize);
1031
1032 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1033 SetLastError(ERROR_INVALID_HANDLE);
1034 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1035 SetLastError(ERROR_INVALID_HANDLE);
1036 else if (!DeviceInfoData)
1037 SetLastError(ERROR_INVALID_PARAMETER);
1038 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1039 SetLastError(ERROR_INVALID_USER_BUFFER);
1040 else if (Property >= SPDRP_MAXIMUM_PROPERTY)
1041 SetLastError(ERROR_INVALID_PARAMETER);
1042 else
1043 {
1044 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
1045 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
1046
1047 switch (Property)
1048 {
1049 case SPDRP_CAPABILITIES:
1050 case SPDRP_CLASS:
1051 case SPDRP_CLASSGUID:
1052 case SPDRP_COMPATIBLEIDS:
1053 case SPDRP_CONFIGFLAGS:
1054 case SPDRP_DEVICEDESC:
1055 case SPDRP_DRIVER:
1056 case SPDRP_FRIENDLYNAME:
1057 case SPDRP_HARDWAREID:
1058 case SPDRP_LOCATION_INFORMATION:
1059 case SPDRP_LOWERFILTERS:
1060 case SPDRP_MFG:
1061 case SPDRP_SECURITY:
1062 case SPDRP_SERVICE:
1063 case SPDRP_UI_NUMBER:
1064 case SPDRP_UI_NUMBER_DESC_FORMAT:
1065 case SPDRP_UPPERFILTERS:
1066 {
1067 LPCWSTR RegistryPropertyName;
1068 DWORD BufferSize;
1069
1070 switch (Property)
1071 {
1072 case SPDRP_CAPABILITIES:
1073 RegistryPropertyName = REGSTR_VAL_CAPABILITIES; break;
1074 case SPDRP_CLASS:
1075 RegistryPropertyName = REGSTR_VAL_CLASS; break;
1076 case SPDRP_CLASSGUID:
1077 RegistryPropertyName = REGSTR_VAL_CLASSGUID; break;
1078 case SPDRP_COMPATIBLEIDS:
1079 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS; break;
1080 case SPDRP_CONFIGFLAGS:
1081 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS; break;
1082 case SPDRP_DEVICEDESC:
1083 RegistryPropertyName = REGSTR_VAL_DEVDESC; break;
1084 case SPDRP_DRIVER:
1085 RegistryPropertyName = REGSTR_VAL_DRIVER; break;
1086 case SPDRP_FRIENDLYNAME:
1087 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME; break;
1088 case SPDRP_HARDWAREID:
1089 RegistryPropertyName = REGSTR_VAL_HARDWAREID; break;
1090 case SPDRP_LOCATION_INFORMATION:
1091 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION; break;
1092 case SPDRP_LOWERFILTERS:
1093 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS; break;
1094 case SPDRP_MFG:
1095 RegistryPropertyName = REGSTR_VAL_MFG; break;
1096 case SPDRP_SECURITY:
1097 RegistryPropertyName = REGSTR_SECURITY; break;
1098 case SPDRP_SERVICE:
1099 RegistryPropertyName = REGSTR_VAL_SERVICE; break;
1100 case SPDRP_UI_NUMBER:
1101 RegistryPropertyName = REGSTR_VAL_UI_NUMBER; break;
1102 case SPDRP_UI_NUMBER_DESC_FORMAT:
1103 RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT; break;
1104 case SPDRP_UPPERFILTERS:
1105 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS; break;
1106 default:
1107 /* Should not happen */
1108 RegistryPropertyName = NULL; break;
1109 }
1110
1111 /* Open registry key name */
1112 rc = RegOpenKeyExW(
1113 list->HKLM,
1114 REGSTR_PATH_SYSTEMENUM,
1115 0, /* Options */
1116 0,
1117 &hEnumKey);
1118 if (rc != ERROR_SUCCESS)
1119 {
1120 SetLastError(rc);
1121 break;
1122 }
1123 rc = RegOpenKeyExW(
1124 hEnumKey,
1125 DevInfo->Data,
1126 0, /* Options */
1127 KEY_QUERY_VALUE,
1128 &hKey);
1129 RegCloseKey(hEnumKey);
1130 if (rc != ERROR_SUCCESS)
1131 {
1132 SetLastError(rc);
1133 break;
1134 }
1135 /* Read registry entry */
1136 BufferSize = PropertyBufferSize;
1137 rc = RegQueryValueExW(
1138 hKey,
1139 RegistryPropertyName,
1140 NULL, /* Reserved */
1141 PropertyRegDataType,
1142 PropertyBuffer,
1143 &BufferSize);
1144 if (RequiredSize)
1145 *RequiredSize = BufferSize;
1146 switch(rc) {
1147 case ERROR_SUCCESS:
1148 if (PropertyBuffer != NULL || BufferSize == 0)
1149 ret = TRUE;
1150 else
1151 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1152 break;
1153 case ERROR_MORE_DATA:
1154 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1155 break;
1156 default:
1157 SetLastError(rc);
1158 }
1159 RegCloseKey(hKey);
1160 break;
1161 }
1162
1163 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
1164 {
1165 DWORD required = (strlenW(DevInfo->Data) + 1) * sizeof(WCHAR);
1166
1167 if (PropertyRegDataType)
1168 *PropertyRegDataType = REG_SZ;
1169 if (RequiredSize)
1170 *RequiredSize = required;
1171 if (PropertyBufferSize >= required)
1172 {
1173 strcpyW((LPWSTR)PropertyBuffer, DevInfo->Data);
1174 ret = TRUE;
1175 }
1176 else
1177 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1178 break;
1179 }
1180
1181 /*case SPDRP_BUSTYPEGUID:
1182 case SPDRP_LEGACYBUSTYPE:
1183 case SPDRP_BUSNUMBER:
1184 case SPDRP_ENUMERATOR_NAME:
1185 case SPDRP_SECURITY_SDS:
1186 case SPDRP_DEVTYPE:
1187 case SPDRP_EXCLUSIVE:
1188 case SPDRP_CHARACTERISTICS:
1189 case SPDRP_ADDRESS:
1190 case SPDRP_DEVICE_POWER_DATA:*/
1191 #if (WINVER >= 0x501)
1192 /*case SPDRP_REMOVAL_POLICY:
1193 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
1194 case SPDRP_REMOVAL_POLICY_OVERRIDE:
1195 case SPDRP_INSTALL_STATE:*/
1196 #endif
1197
1198 default:
1199 {
1200 ERR("Property 0x%lx not implemented\n", Property);
1201 SetLastError(ERROR_NOT_SUPPORTED);
1202 }
1203 }
1204 }
1205
1206 TRACE("Returning %d\n", ret);
1207 return ret;
1208 }
1209
1210 /***********************************************************************
1211 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
1212 */
1213 BOOL WINAPI
1214 SetupDiSetDeviceRegistryPropertyA(
1215 IN HDEVINFO DeviceInfoSet,
1216 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
1217 IN DWORD Property,
1218 IN CONST BYTE *PropertyBuffer OPTIONAL,
1219 IN DWORD PropertyBufferSize)
1220 {
1221 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
1222 Property, PropertyBuffer, PropertyBufferSize);
1223 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1224 return FALSE;
1225 }
1226
1227 /***********************************************************************
1228 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
1229 */
1230 BOOL WINAPI
1231 SetupDiSetDeviceRegistryPropertyW(
1232 IN HDEVINFO DeviceInfoSet,
1233 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
1234 IN DWORD Property,
1235 IN CONST BYTE *PropertyBuffer OPTIONAL,
1236 IN DWORD PropertyBufferSize)
1237 {
1238 struct DeviceInfoSet *list;
1239 BOOL ret = FALSE;
1240
1241 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
1242 Property, PropertyBuffer, PropertyBufferSize);
1243
1244 if (!DeviceInfoSet)
1245 SetLastError(ERROR_INVALID_HANDLE);
1246 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1247 SetLastError(ERROR_INVALID_HANDLE);
1248 else if (!DeviceInfoData)
1249 SetLastError(ERROR_INVALID_HANDLE);
1250 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1251 SetLastError(ERROR_INVALID_USER_BUFFER);
1252 else
1253 {
1254 switch (Property)
1255 {
1256 case SPDRP_COMPATIBLEIDS:
1257 case SPDRP_CONFIGFLAGS:
1258 case SPDRP_FRIENDLYNAME:
1259 case SPDRP_HARDWAREID:
1260 case SPDRP_LOCATION_INFORMATION:
1261 case SPDRP_LOWERFILTERS:
1262 case SPDRP_SECURITY:
1263 case SPDRP_SERVICE:
1264 case SPDRP_UI_NUMBER_DESC_FORMAT:
1265 case SPDRP_UPPERFILTERS:
1266 {
1267 LPCWSTR RegistryPropertyName;
1268 DWORD RegistryDataType;
1269 HKEY hKey;
1270 LONG rc;
1271
1272 switch (Property)
1273 {
1274 case SPDRP_COMPATIBLEIDS:
1275 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS;
1276 RegistryDataType = REG_MULTI_SZ;
1277 break;
1278 case SPDRP_CONFIGFLAGS:
1279 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS;
1280 RegistryDataType = REG_DWORD;
1281 break;
1282 case SPDRP_FRIENDLYNAME:
1283 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME;
1284 RegistryDataType = REG_SZ;
1285 break;
1286 case SPDRP_HARDWAREID:
1287 RegistryPropertyName = REGSTR_VAL_HARDWAREID;
1288 RegistryDataType = REG_MULTI_SZ;
1289 break;
1290 case SPDRP_LOCATION_INFORMATION:
1291 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION;
1292 RegistryDataType = REG_SZ;
1293 break;
1294 case SPDRP_LOWERFILTERS:
1295 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS;
1296 RegistryDataType = REG_MULTI_SZ;
1297 break;
1298 case SPDRP_SECURITY:
1299 RegistryPropertyName = REGSTR_SECURITY;
1300 RegistryDataType = REG_BINARY;
1301 break;
1302 case SPDRP_SERVICE:
1303 RegistryPropertyName = REGSTR_VAL_SERVICE;
1304 RegistryDataType = REG_SZ;
1305 break;
1306 case SPDRP_UI_NUMBER_DESC_FORMAT:
1307 RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT;
1308 RegistryDataType = REG_SZ;
1309 break;
1310 case SPDRP_UPPERFILTERS:
1311 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS;
1312 RegistryDataType = REG_MULTI_SZ;
1313 break;
1314 default:
1315 /* Should not happen */
1316 RegistryPropertyName = NULL;
1317 RegistryDataType = REG_BINARY;
1318 break;
1319 }
1320 /* Open device registry key */
1321 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
1322 if (hKey != INVALID_HANDLE_VALUE)
1323 {
1324 /* Write new data */
1325 rc = RegSetValueExW(
1326 hKey,
1327 RegistryPropertyName,
1328 0, /* Reserved */
1329 RegistryDataType,
1330 PropertyBuffer,
1331 PropertyBufferSize);
1332 if (rc == ERROR_SUCCESS)
1333 ret = TRUE;
1334 else
1335 SetLastError(rc);
1336 RegCloseKey(hKey);
1337 }
1338 break;
1339 }
1340
1341 /*case SPDRP_CHARACTERISTICS:
1342 case SPDRP_DEVTYPE:
1343 case SPDRP_EXCLUSIVE:*/
1344 #if (WINVER >= 0x501)
1345 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
1346 #endif
1347 //case SPDRP_SECURITY_SDS:
1348
1349 default:
1350 {
1351 ERR("Property 0x%lx not implemented\n", Property);
1352 SetLastError(ERROR_NOT_SUPPORTED);
1353 }
1354 }
1355 }
1356
1357 TRACE("Returning %d\n", ret);
1358 return ret;
1359 }
1360
1361
1362 static BOOL WINAPI
1363 IntSetupDiRegisterDeviceInfo(
1364 IN HDEVINFO DeviceInfoSet,
1365 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
1366 {
1367 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL);
1368 }
1369
1370 /***********************************************************************
1371 * SetupDiCallClassInstaller (SETUPAPI.@)
1372 */
1373 BOOL WINAPI
1374 SetupDiCallClassInstaller(
1375 IN DI_FUNCTION InstallFunction,
1376 IN HDEVINFO DeviceInfoSet,
1377 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
1378 {
1379 BOOL ret = FALSE;
1380
1381 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
1382
1383 if (!DeviceInfoSet)
1384 SetLastError(ERROR_INVALID_PARAMETER);
1385 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1386 SetLastError(ERROR_INVALID_HANDLE);
1387 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1388 SetLastError(ERROR_INVALID_HANDLE);
1389 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
1390 SetLastError(ERROR_INVALID_HANDLE);
1391 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1392 SetLastError(ERROR_INVALID_USER_BUFFER);
1393 else
1394 {
1395 SP_DEVINSTALL_PARAMS_W InstallParams;
1396 #define CLASS_COINSTALLER 0x1
1397 #define DEVICE_COINSTALLER 0x2
1398 #define CLASS_INSTALLER 0x4
1399 UCHAR CanHandle = 0;
1400 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
1401
1402 switch (InstallFunction)
1403 {
1404 case DIF_ADDPROPERTYPAGE_ADVANCED:
1405 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1406 break;
1407 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
1408 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1409 break;
1410 case DIF_ALLOW_INSTALL:
1411 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1412 break;
1413 case DIF_DETECT:
1414 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1415 break;
1416 case DIF_DESTROYPRIVATEDATA:
1417 CanHandle = CLASS_INSTALLER;
1418 break;
1419 case DIF_INSTALLDEVICE:
1420 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1421 DefaultHandler = SetupDiInstallDevice;
1422 break;
1423 case DIF_INSTALLDEVICEFILES:
1424 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1425 DefaultHandler = SetupDiInstallDriverFiles;
1426 break;
1427 case DIF_INSTALLINTERFACES:
1428 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1429 DefaultHandler = SetupDiInstallDeviceInterfaces;
1430 break;
1431 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
1432 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1433 break;
1434 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
1435 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1436 break;
1437 case DIF_NEWDEVICEWIZARD_PREANALYZE:
1438 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1439 break;
1440 case DIF_NEWDEVICEWIZARD_PRESELECT:
1441 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1442 break;
1443 case DIF_NEWDEVICEWIZARD_SELECT:
1444 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1445 break;
1446 case DIF_POWERMESSAGEWAKE:
1447 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1448 break;
1449 case DIF_PROPERTYCHANGE:
1450 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1451 DefaultHandler = SetupDiChangeState;
1452 break;
1453 case DIF_REGISTER_COINSTALLERS:
1454 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1455 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
1456 break;
1457 case DIF_REGISTERDEVICE:
1458 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1459 DefaultHandler = IntSetupDiRegisterDeviceInfo;
1460 break;
1461 case DIF_REMOVE:
1462 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1463 DefaultHandler = SetupDiRemoveDevice;
1464 break;
1465 case DIF_SELECTBESTCOMPATDRV:
1466 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1467 DefaultHandler = SetupDiSelectBestCompatDrv;
1468 break;
1469 case DIF_SELECTDEVICE:
1470 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1471 DefaultHandler = SetupDiSelectDevice;
1472 break;
1473 case DIF_TROUBLESHOOTER:
1474 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1475 break;
1476 case DIF_UNREMOVE:
1477 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1478 DefaultHandler = SetupDiUnremoveDevice;
1479 break;
1480 default:
1481 ERR("Install function %u not supported\n", InstallFunction);
1482 SetLastError(ERROR_NOT_SUPPORTED);
1483 }
1484
1485 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1486 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
1487 /* Don't process this call, as a parameter is invalid */
1488 CanHandle = 0;
1489
1490 if (CanHandle != 0)
1491 {
1492 LIST_ENTRY ClassCoInstallersListHead;
1493 LIST_ENTRY DeviceCoInstallersListHead;
1494 HMODULE ClassInstallerLibrary = NULL;
1495 CLASS_INSTALL_PROC ClassInstaller = NULL;
1496 COINSTALLER_CONTEXT_DATA Context;
1497 PLIST_ENTRY ListEntry;
1498 HKEY hKey;
1499 DWORD dwRegType, dwLength;
1500 DWORD rc = NO_ERROR;
1501
1502 InitializeListHead(&ClassCoInstallersListHead);
1503 InitializeListHead(&DeviceCoInstallersListHead);
1504
1505 if (CanHandle & DEVICE_COINSTALLER)
1506 {
1507 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
1508 if (hKey != INVALID_HANDLE_VALUE)
1509 {
1510 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
1511 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
1512 {
1513 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
1514 if (KeyBuffer != NULL)
1515 {
1516 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1517 if (rc == ERROR_SUCCESS)
1518 {
1519 LPWSTR ptr;
1520 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
1521 {
1522 /* Add coinstaller to DeviceCoInstallersListHead list */
1523 struct CoInstallerElement *coinstaller;
1524 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
1525 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
1526 if (!coinstaller)
1527 continue;
1528 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
1529 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
1530 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
1531 else
1532 HeapFree(GetProcessHeap(), 0, coinstaller);
1533 }
1534 }
1535 HeapFree(GetProcessHeap(), 0, KeyBuffer);
1536 }
1537 }
1538 RegCloseKey(hKey);
1539 }
1540 }
1541 if (CanHandle & CLASS_COINSTALLER)
1542 {
1543 rc = RegOpenKeyEx(
1544 HKEY_LOCAL_MACHINE,
1545 REGSTR_PATH_CODEVICEINSTALLERS,
1546 0, /* Options */
1547 KEY_QUERY_VALUE,
1548 &hKey);
1549 if (rc == ERROR_SUCCESS)
1550 {
1551 LPWSTR lpGuidString;
1552 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
1553 {
1554 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
1555 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
1556 {
1557 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
1558 if (KeyBuffer != NULL)
1559 {
1560 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1561 if (rc == ERROR_SUCCESS)
1562 {
1563 LPWSTR ptr;
1564 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
1565 {
1566 /* Add coinstaller to ClassCoInstallersListHead list */
1567 struct CoInstallerElement *coinstaller;
1568 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
1569 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
1570 if (!coinstaller)
1571 continue;
1572 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
1573 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
1574 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
1575 else
1576 HeapFree(GetProcessHeap(), 0, coinstaller);
1577 }
1578 }
1579 HeapFree(GetProcessHeap(), 0, KeyBuffer);
1580 }
1581 }
1582 RpcStringFreeW(&lpGuidString);
1583 }
1584 RegCloseKey(hKey);
1585 }
1586 }
1587 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
1588 {
1589 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
1590 if (hKey != INVALID_HANDLE_VALUE)
1591 {
1592 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
1593 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
1594 {
1595 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
1596 if (KeyBuffer != NULL)
1597 {
1598 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1599 if (rc == ERROR_SUCCESS)
1600 {
1601 /* Get ClassInstaller function pointer */
1602 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
1603 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
1604 {
1605 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
1606 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
1607 }
1608 }
1609 HeapFree(GetProcessHeap(), 0, KeyBuffer);
1610 }
1611 }
1612 RegCloseKey(hKey);
1613 }
1614 }
1615
1616 /* Call Class co-installers */
1617 Context.PostProcessing = FALSE;
1618 rc = NO_ERROR;
1619 ListEntry = ClassCoInstallersListHead.Flink;
1620 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
1621 {
1622 struct CoInstallerElement *coinstaller;
1623 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1624 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1625 coinstaller->PrivateData = Context.PrivateData;
1626 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
1627 {
1628 coinstaller->DoPostProcessing = TRUE;
1629 rc = NO_ERROR;
1630 }
1631 ListEntry = ListEntry->Flink;
1632 }
1633
1634 /* Call Device co-installers */
1635 ListEntry = DeviceCoInstallersListHead.Flink;
1636 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
1637 {
1638 struct CoInstallerElement *coinstaller;
1639 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1640 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1641 coinstaller->PrivateData = Context.PrivateData;
1642 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
1643 {
1644 coinstaller->DoPostProcessing = TRUE;
1645 rc = NO_ERROR;
1646 }
1647 ListEntry = ListEntry->Flink;
1648 }
1649
1650 /* Call Class installer */
1651 if (ClassInstaller)
1652 {
1653 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
1654 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
1655 }
1656 else
1657 rc = ERROR_DI_DO_DEFAULT;
1658
1659 /* Call default handler */
1660 if (rc == ERROR_DI_DO_DEFAULT)
1661 {
1662 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
1663 {
1664 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
1665 rc = NO_ERROR;
1666 else
1667 rc = GetLastError();
1668 }
1669 else
1670 rc = NO_ERROR;
1671 }
1672
1673 /* Call Class co-installers that required postprocessing */
1674 Context.PostProcessing = TRUE;
1675 ListEntry = ClassCoInstallersListHead.Flink;
1676 while (ListEntry != &ClassCoInstallersListHead)
1677 {
1678 struct CoInstallerElement *coinstaller;
1679 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1680 if (coinstaller->DoPostProcessing)
1681 {
1682 Context.InstallResult = rc;
1683 Context.PrivateData = coinstaller->PrivateData;
1684 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1685 }
1686 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
1687 ListEntry = ListEntry->Flink;
1688 }
1689
1690 /* Call Device co-installers that required postprocessing */
1691 ListEntry = DeviceCoInstallersListHead.Flink;
1692 while (ListEntry != &DeviceCoInstallersListHead)
1693 {
1694 struct CoInstallerElement *coinstaller;
1695 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1696 if (coinstaller->DoPostProcessing)
1697 {
1698 Context.InstallResult = rc;
1699 Context.PrivateData = coinstaller->PrivateData;
1700 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1701 }
1702 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
1703 ListEntry = ListEntry->Flink;
1704 }
1705
1706 /* Free allocated memory */
1707 while (!IsListEmpty(&ClassCoInstallersListHead))
1708 {
1709 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
1710 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
1711 }
1712 while (!IsListEmpty(&DeviceCoInstallersListHead))
1713 {
1714 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
1715 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
1716 }
1717
1718 ret = (rc == NO_ERROR);
1719 }
1720 }
1721
1722 TRACE("Returning %d\n", ret);
1723 return ret;
1724 }
1725
1726 /***********************************************************************
1727 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
1728 */
1729 BOOL WINAPI
1730 SetupDiGetDeviceInfoListClass(
1731 IN HDEVINFO DeviceInfoSet,
1732 OUT LPGUID ClassGuid)
1733 {
1734 struct DeviceInfoSet *list;
1735 BOOL ret = FALSE;
1736
1737 TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
1738
1739 if (!DeviceInfoSet)
1740 SetLastError(ERROR_INVALID_HANDLE);
1741 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1742 SetLastError(ERROR_INVALID_HANDLE);
1743 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
1744 SetLastError(ERROR_NO_ASSOCIATED_CLASS);
1745 else
1746 {
1747 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
1748
1749 ret = TRUE;
1750 }
1751
1752 TRACE("Returning %d\n", ret);
1753 return ret;
1754 }
1755
1756 /***********************************************************************
1757 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
1758 */
1759 BOOL WINAPI
1760 SetupDiGetDeviceInfoListDetailW(
1761 IN HDEVINFO DeviceInfoSet,
1762 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
1763 {
1764 struct DeviceInfoSet *list;
1765 BOOL ret = FALSE;
1766
1767 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
1768
1769 if (!DeviceInfoSet)
1770 SetLastError(ERROR_INVALID_HANDLE);
1771 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1772 SetLastError(ERROR_INVALID_HANDLE);
1773 else if (!DeviceInfoListDetailData)
1774 SetLastError(ERROR_INVALID_PARAMETER);
1775 else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
1776 SetLastError(ERROR_INVALID_USER_BUFFER);
1777 else
1778 {
1779 memcpy(
1780 &DeviceInfoListDetailData->ClassGuid,
1781 &list->ClassGuid,
1782 sizeof(GUID));
1783 DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
1784 if (list->MachineName)
1785 strcpyW(DeviceInfoListDetailData->RemoteMachineName, list->MachineName + 2);
1786 else
1787 DeviceInfoListDetailData->RemoteMachineName[0] = 0;
1788
1789 ret = TRUE;
1790 }
1791
1792 TRACE("Returning %d\n", ret);
1793 return ret;
1794 }
1795
1796 /***********************************************************************
1797 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1798 */
1799 BOOL WINAPI
1800 SetupDiGetDeviceInstallParamsA(
1801 IN HDEVINFO DeviceInfoSet,
1802 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1803 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
1804 {
1805 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
1806 BOOL ret = FALSE;
1807
1808 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1809
1810 if (DeviceInstallParams == NULL)
1811 SetLastError(ERROR_INVALID_PARAMETER);
1812 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
1813 SetLastError(ERROR_INVALID_USER_BUFFER);
1814 else
1815 {
1816 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1817 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
1818
1819 if (ret)
1820 {
1821 /* Do W->A conversion */
1822 memcpy(
1823 DeviceInstallParams,
1824 &deviceInstallParamsW,
1825 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
1826 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
1827 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
1828 {
1829 DeviceInstallParams->DriverPath[0] = '\0';
1830 ret = FALSE;
1831 }
1832 }
1833 }
1834
1835 TRACE("Returning %d\n", ret);
1836 return ret;
1837 }
1838
1839 /***********************************************************************
1840 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
1841 */
1842 BOOL WINAPI
1843 SetupDiGetDeviceInstallParamsW(
1844 IN HDEVINFO DeviceInfoSet,
1845 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1846 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
1847 {
1848 struct DeviceInfoSet *list;
1849 BOOL ret = FALSE;
1850
1851 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1852
1853 if (!DeviceInfoSet)
1854 SetLastError(ERROR_INVALID_HANDLE);
1855 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1856 SetLastError(ERROR_INVALID_HANDLE);
1857 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1858 SetLastError(ERROR_INVALID_USER_BUFFER);
1859 else if (!DeviceInstallParams)
1860 SetLastError(ERROR_INVALID_PARAMETER);
1861 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
1862 SetLastError(ERROR_INVALID_USER_BUFFER);
1863 else
1864 {
1865 PSP_DEVINSTALL_PARAMS_W Source;
1866
1867 if (DeviceInfoData)
1868 Source = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
1869 else
1870 Source = &list->InstallParams;
1871 memcpy(DeviceInstallParams, Source, Source->cbSize);
1872 ret = TRUE;
1873 }
1874
1875 TRACE("Returning %d\n", ret);
1876 return ret;
1877 }
1878
1879 static BOOL
1880 CheckDeviceInstallParameters(
1881 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
1882 {
1883 DWORD SupportedFlags =
1884 DI_NOVCP | /* 0x00000008 */
1885 DI_DIDCOMPAT | /* 0x00000010 */
1886 DI_DIDCLASS | /* 0x00000020 */
1887 DI_NEEDRESTART | /* 0x00000080 */
1888 DI_NEEDREBOOT | /* 0x00000100 */
1889 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */
1890 DI_PROPERTIES_CHANGE | /* 0x00004000 */
1891 DI_ENUMSINGLEINF | /* 0x00010000 */
1892 DI_DONOTCALLCONFIGMG | /* 0x00020000 */
1893 DI_CLASSINSTALLPARAMS | /* 0x00100000 */
1894 DI_NODI_DEFAULTACTION | /* 0x00200000 */
1895 DI_QUIETINSTALL | /* 0x00800000 */
1896 DI_NOFILECOPY | /* 0x01000000 */
1897 DI_DRIVERPAGE_ADDED; /* 0x04000000 */
1898 DWORD SupportedFlagsEx =
1899 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */
1900 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */
1901 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */
1902 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */
1903 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */
1904 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */
1905 BOOL ret = FALSE;
1906
1907 /* FIXME: add support for more flags */
1908
1909 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
1910 * It should be checked before accessing to other values
1911 * of the SP_DEVINSTALL_PARAMS structure */
1912
1913 if (DeviceInstallParams->Flags & ~SupportedFlags)
1914 {
1915 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
1916 SetLastError(ERROR_INVALID_FLAGS);
1917 }
1918 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
1919 {
1920 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
1921 SetLastError(ERROR_INVALID_FLAGS);
1922 }
1923 else if ((DeviceInstallParams->Flags & DI_NOVCP)
1924 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
1925 SetLastError(ERROR_INVALID_USER_BUFFER);
1926 else
1927 {
1928 /* FIXME: check Reserved field */
1929 ret = TRUE;
1930 }
1931
1932 return ret;
1933 }
1934
1935 /***********************************************************************
1936 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
1937 */
1938 BOOL WINAPI
1939 SetupDiSetDeviceInstallParamsW(
1940 IN HDEVINFO DeviceInfoSet,
1941 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1942 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
1943 {
1944 struct DeviceInfoSet *list;
1945 BOOL ret = FALSE;
1946
1947 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1948
1949 if (!DeviceInfoSet)
1950 SetLastError(ERROR_INVALID_HANDLE);
1951 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1952 SetLastError(ERROR_INVALID_HANDLE);
1953 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1954 SetLastError(ERROR_INVALID_USER_BUFFER);
1955 else if (!DeviceInstallParams)
1956 SetLastError(ERROR_INVALID_PARAMETER);
1957 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
1958 SetLastError(ERROR_INVALID_USER_BUFFER);
1959 else if (CheckDeviceInstallParameters(DeviceInstallParams))
1960 {
1961 PSP_DEVINSTALL_PARAMS_W Destination;
1962
1963 if (DeviceInfoData)
1964 Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
1965 else
1966 Destination = &list->InstallParams;
1967 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
1968 ret = TRUE;
1969 }
1970
1971 TRACE("Returning %d\n", ret);
1972 return ret;
1973 }
1974
1975 /***********************************************************************
1976 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
1977 */
1978 BOOL WINAPI
1979 SetupDiGetDeviceInstanceIdA(
1980 IN HDEVINFO DeviceInfoSet,
1981 IN PSP_DEVINFO_DATA DeviceInfoData,
1982 OUT PSTR DeviceInstanceId OPTIONAL,
1983 IN DWORD DeviceInstanceIdSize,
1984 OUT PDWORD RequiredSize OPTIONAL)
1985 {
1986 PWSTR DeviceInstanceIdW = NULL;
1987 BOOL ret = FALSE;
1988
1989 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
1990 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
1991
1992 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1993 SetLastError(ERROR_INVALID_PARAMETER);
1994 else
1995 {
1996 if (DeviceInstanceIdSize != 0)
1997 {
1998 DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
1999 if (DeviceInstanceIdW == NULL)
2000 return FALSE;
2001 }
2002
2003 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
2004 DeviceInstanceIdW, DeviceInstanceIdSize,
2005 RequiredSize);
2006
2007 if (ret && DeviceInstanceIdW != NULL)
2008 {
2009 if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
2010 DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
2011 {
2012 DeviceInstanceId[0] = '\0';
2013 ret = FALSE;
2014 }
2015 }
2016 }
2017
2018 TRACE("Returning %d\n", ret);
2019 return ret;
2020 }
2021
2022 /***********************************************************************
2023 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
2024 */
2025 BOOL WINAPI
2026 SetupDiGetDeviceInstanceIdW(
2027 IN HDEVINFO DeviceInfoSet,
2028 IN PSP_DEVINFO_DATA DeviceInfoData,
2029 OUT PWSTR DeviceInstanceId OPTIONAL,
2030 IN DWORD DeviceInstanceIdSize,
2031 OUT PDWORD RequiredSize OPTIONAL)
2032 {
2033 BOOL ret = FALSE;
2034
2035 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
2036 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
2037
2038 if (!DeviceInfoSet)
2039 SetLastError(ERROR_INVALID_HANDLE);
2040 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2041 SetLastError(ERROR_INVALID_HANDLE);
2042 else if (!DeviceInfoData)
2043 SetLastError(ERROR_INVALID_PARAMETER);
2044 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2045 SetLastError(ERROR_INVALID_USER_BUFFER);
2046 else if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
2047 SetLastError(ERROR_INVALID_PARAMETER);
2048 else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
2049 SetLastError(ERROR_INVALID_PARAMETER);
2050 else
2051 {
2052 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2053 DWORD required;
2054
2055 required = (strlenW(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
2056 if (RequiredSize)
2057 *RequiredSize = required;
2058
2059 if (required <= DeviceInstanceIdSize)
2060 {
2061 strcpyW(DeviceInstanceId, DevInfo->DeviceName);
2062 ret = TRUE;
2063 }
2064 else
2065 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2066 }
2067
2068 TRACE("Returning %d\n", ret);
2069 return ret;
2070 }
2071
2072
2073 /***********************************************************************
2074 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
2075 */
2076 HKEY WINAPI
2077 SetupDiCreateDevRegKeyA(
2078 IN HDEVINFO DeviceInfoSet,
2079 IN PSP_DEVINFO_DATA DeviceInfoData,
2080 IN DWORD Scope,
2081 IN DWORD HwProfile,
2082 IN DWORD KeyType,
2083 IN HINF InfHandle OPTIONAL,
2084 IN PCSTR InfSectionName OPTIONAL)
2085 {
2086 PCWSTR InfSectionNameW = NULL;
2087 HKEY ret = INVALID_HANDLE_VALUE;
2088
2089 if (InfSectionName)
2090 {
2091 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2092 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
2093 }
2094
2095 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
2096 DeviceInfoData,
2097 Scope,
2098 HwProfile,
2099 KeyType,
2100 InfHandle,
2101 InfSectionNameW);
2102
2103 if (InfSectionNameW != NULL)
2104 MyFree((PVOID)InfSectionNameW);
2105
2106 return ret;
2107 }
2108
2109 static HKEY
2110 OpenHardwareProfileKey(
2111 IN HKEY HKLM,
2112 IN DWORD HwProfile,
2113 IN DWORD samDesired)
2114 {
2115 HKEY hHWProfilesKey = NULL;
2116 HKEY hHWProfileKey = NULL;
2117 HKEY ret = INVALID_HANDLE_VALUE;
2118 LONG rc;
2119
2120 rc = RegOpenKeyExW(HKLM,
2121 REGSTR_PATH_HWPROFILES,
2122 0,
2123 0,
2124 &hHWProfilesKey);
2125 if (rc != ERROR_SUCCESS)
2126 {
2127 SetLastError(rc);
2128 goto cleanup;
2129 }
2130 if (HwProfile == 0)
2131 {
2132 rc = RegOpenKeyExW(
2133 hHWProfilesKey,
2134 REGSTR_KEY_CURRENT,
2135 0,
2136 KEY_CREATE_SUB_KEY,
2137 &hHWProfileKey);
2138 }
2139 else
2140 {
2141 WCHAR subKey[5];
2142 snprintfW(subKey, 4, L"%04lu", HwProfile);
2143 subKey[4] = '\0';
2144 rc = RegOpenKeyExW(
2145 hHWProfilesKey,
2146 subKey,
2147 0,
2148 KEY_CREATE_SUB_KEY,
2149 &hHWProfileKey);
2150 }
2151 if (rc != ERROR_SUCCESS)
2152 {
2153 SetLastError(rc);
2154 goto cleanup;
2155 }
2156 ret = hHWProfileKey;
2157
2158 cleanup:
2159 if (hHWProfilesKey != NULL)
2160 RegCloseKey(hHWProfilesKey);
2161 if (hHWProfileKey != NULL && hHWProfileKey != ret)
2162 RegCloseKey(hHWProfileKey);
2163 return ret;
2164 }
2165
2166 /***********************************************************************
2167 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
2168 */
2169 HKEY WINAPI
2170 SetupDiCreateDevRegKeyW(
2171 IN HDEVINFO DeviceInfoSet,
2172 IN PSP_DEVINFO_DATA DeviceInfoData,
2173 IN DWORD Scope,
2174 IN DWORD HwProfile,
2175 IN DWORD KeyType,
2176 IN HINF InfHandle OPTIONAL,
2177 IN PCWSTR InfSectionName OPTIONAL)
2178 {
2179 struct DeviceInfoSet *list;
2180 HKEY ret = INVALID_HANDLE_VALUE;
2181
2182 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
2183 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
2184
2185 if (!DeviceInfoSet)
2186 SetLastError(ERROR_INVALID_HANDLE);
2187 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2188 SetLastError(ERROR_INVALID_HANDLE);
2189 else if (!DeviceInfoData)
2190 SetLastError(ERROR_INVALID_PARAMETER);
2191 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2192 SetLastError(ERROR_INVALID_USER_BUFFER);
2193 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
2194 SetLastError(ERROR_INVALID_PARAMETER);
2195 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
2196 SetLastError(ERROR_INVALID_PARAMETER);
2197 else if (InfHandle && !InfSectionName)
2198 SetLastError(ERROR_INVALID_PARAMETER);
2199 else if (!InfHandle && InfSectionName)
2200 SetLastError(ERROR_INVALID_PARAMETER);
2201 else
2202 {
2203 LPWSTR lpGuidString = NULL;
2204 LPWSTR DriverKey = NULL; /* {GUID}\Index */
2205 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
2206 DWORD Index; /* Index used in the DriverKey name */
2207 DWORD rc;
2208 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
2209 HKEY hEnumKey = NULL;
2210 HKEY hClassKey = NULL;
2211 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
2212 HKEY hKey = NULL;
2213 HKEY RootKey;
2214
2215 if (Scope == DICS_FLAG_GLOBAL)
2216 RootKey = list->HKLM;
2217 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
2218 {
2219 hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
2220 if (hHWProfileKey == INVALID_HANDLE_VALUE)
2221 goto cleanup;
2222 RootKey = hHWProfileKey;
2223 }
2224
2225 if (KeyType == DIREG_DEV)
2226 {
2227 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2228
2229 rc = RegCreateKeyExW(
2230 RootKey,
2231 REGSTR_PATH_SYSTEMENUM,
2232 0,
2233 NULL,
2234 REG_OPTION_NON_VOLATILE,
2235 KEY_CREATE_SUB_KEY,
2236 NULL,
2237 &hEnumKey,
2238 NULL);
2239 if (rc != ERROR_SUCCESS)
2240 {
2241 SetLastError(rc);
2242 goto cleanup;
2243 }
2244 rc = RegCreateKeyExW(
2245 hEnumKey,
2246 deviceInfo->DeviceName,
2247 0,
2248 NULL,
2249 REG_OPTION_NON_VOLATILE,
2250 #if _WIN32_WINNT >= 0x502
2251 KEY_READ | KEY_WRITE,
2252 #else
2253 KEY_ALL_ACCESS,
2254 #endif
2255 NULL,
2256 &hKey,
2257 NULL);
2258 if (rc != ERROR_SUCCESS)
2259 {
2260 SetLastError(rc);
2261 goto cleanup;
2262 }
2263 }
2264 else /* KeyType == DIREG_DRV */
2265 {
2266 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
2267 goto cleanup;
2268 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
2269 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
2270 if (!DriverKey)
2271 {
2272 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2273 goto cleanup;
2274 }
2275 DriverKey[0] = '{';
2276 strcpyW(&DriverKey[1], lpGuidString);
2277 strcatW(DriverKey, L"}\\");
2278 pDeviceInstance = &DriverKey[strlenW(DriverKey)];
2279 rc = RegOpenKeyExW(RootKey,
2280 REGSTR_PATH_CLASS_NT,
2281 0,
2282 KEY_CREATE_SUB_KEY,
2283 &hClassKey);
2284 if (rc != ERROR_SUCCESS)
2285 {
2286 SetLastError(rc);
2287 goto cleanup;
2288 }
2289
2290 /* Try all values for Index between 0 and 9999 */
2291 Index = 0;
2292 while (Index <= 9999)
2293 {
2294 DWORD Disposition;
2295 wsprintf(pDeviceInstance, L"%04lu", Index);
2296 rc = RegCreateKeyEx(hClassKey,
2297 DriverKey,
2298 0,
2299 NULL,
2300 REG_OPTION_NON_VOLATILE,
2301 #if _WIN32_WINNT >= 0x502
2302 KEY_READ | KEY_WRITE,
2303 #else
2304 KEY_ALL_ACCESS,
2305 #endif
2306 NULL,
2307 &hKey,
2308 &Disposition);
2309 if (rc != ERROR_SUCCESS)
2310 {
2311 SetLastError(rc);
2312 goto cleanup;
2313 }
2314 if (Disposition == REG_CREATED_NEW_KEY)
2315 break;
2316 RegCloseKey(hKey);
2317 hKey = NULL;
2318 Index++;
2319 }
2320 if (Index > 9999)
2321 {
2322 /* Unable to create more than 9999 devices within the same class */
2323 SetLastError(ERROR_GEN_FAILURE);
2324 goto cleanup;
2325 }
2326
2327 /* Open device key, to write Driver value */
2328 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
2329 if (hDeviceKey == INVALID_HANDLE_VALUE)
2330 goto cleanup;
2331 rc = RegSetValueEx(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
2332 if (rc != ERROR_SUCCESS)
2333 {
2334 SetLastError(rc);
2335 goto cleanup;
2336 }
2337 }
2338
2339 /* Do installation of the specified section */
2340 if (InfHandle)
2341 {
2342 FIXME("Need to install section %s in file %p\n",
2343 debugstr_w(InfSectionName), InfHandle);
2344 }
2345 ret = hKey;
2346
2347 cleanup:
2348 if (lpGuidString)
2349 RpcStringFreeW(&lpGuidString);
2350 HeapFree(GetProcessHeap(), 0, DriverKey);
2351 if (hHWProfileKey != INVALID_HANDLE_VALUE)
2352 RegCloseKey(hHWProfileKey);
2353 if (hEnumKey != NULL)
2354 RegCloseKey(hEnumKey);
2355 if (hClassKey != NULL)
2356 RegCloseKey(hClassKey);
2357 if (hDeviceKey != INVALID_HANDLE_VALUE)
2358 RegCloseKey(hDeviceKey);
2359 if (hKey != NULL && hKey != ret)
2360 RegCloseKey(hKey);
2361 }
2362
2363 TRACE("Returning 0x%p\n", ret);
2364 return ret;
2365 }
2366
2367 /***********************************************************************
2368 * SetupDiOpenDevRegKey (SETUPAPI.@)
2369 */
2370 HKEY WINAPI
2371 SetupDiOpenDevRegKey(
2372 IN HDEVINFO DeviceInfoSet,
2373 IN PSP_DEVINFO_DATA DeviceInfoData,
2374 IN DWORD Scope,
2375 IN DWORD HwProfile,
2376 IN DWORD KeyType,
2377 IN REGSAM samDesired)
2378 {
2379 struct DeviceInfoSet *list;
2380 HKEY ret = INVALID_HANDLE_VALUE;
2381
2382 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet, DeviceInfoData,
2383 Scope, HwProfile, KeyType, samDesired);
2384
2385 if (!DeviceInfoSet)
2386 SetLastError(ERROR_INVALID_HANDLE);
2387 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2388 SetLastError(ERROR_INVALID_HANDLE);
2389 else if (!DeviceInfoData)
2390 SetLastError(ERROR_INVALID_PARAMETER);
2391 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2392 SetLastError(ERROR_INVALID_USER_BUFFER);
2393 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
2394 SetLastError(ERROR_INVALID_PARAMETER);
2395 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
2396 SetLastError(ERROR_INVALID_PARAMETER);
2397 else
2398 {
2399 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2400 LPWSTR DriverKey = NULL;
2401 DWORD dwLength = 0;
2402 DWORD dwRegType;
2403 DWORD rc;
2404 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
2405 HKEY hEnumKey = NULL;
2406 HKEY hKey = NULL;
2407 HKEY RootKey;
2408
2409 if (Scope == DICS_FLAG_GLOBAL)
2410 RootKey = list->HKLM;
2411 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
2412 {
2413 hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, 0);
2414 if (hHWProfileKey == INVALID_HANDLE_VALUE)
2415 goto cleanup;
2416 RootKey = hHWProfileKey;
2417 }
2418
2419 rc = RegOpenKeyExW(
2420 RootKey,
2421 REGSTR_PATH_SYSTEMENUM,
2422 0, /* Options */
2423 0,
2424 &hEnumKey);
2425 if (rc != ERROR_SUCCESS)
2426 {
2427 SetLastError(rc);
2428 goto cleanup;
2429 }
2430 rc = RegOpenKeyExW(
2431 hEnumKey,
2432 deviceInfo->DeviceName,
2433 0, /* Options */
2434 KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
2435 &hKey);
2436 RegCloseKey(hEnumKey);
2437 hEnumKey = NULL;
2438 if (rc != ERROR_SUCCESS)
2439 {
2440 SetLastError(rc);
2441 goto cleanup;
2442 }
2443 if (KeyType == DIREG_DEV)
2444 {
2445 /* We're done. Just return the hKey handle */
2446 ret = hKey;
2447 goto cleanup;
2448 }
2449 /* Read the 'Driver' key */
2450 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
2451 if (rc != ERROR_SUCCESS)
2452 {
2453 SetLastError(rc);
2454 goto cleanup;
2455 }
2456 else if (dwRegType != REG_SZ)
2457 {
2458 SetLastError(ERROR_GEN_FAILURE);
2459 goto cleanup;
2460 }
2461 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
2462 if (!DriverKey)
2463 {
2464 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2465 goto cleanup;
2466 }
2467 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
2468 if (rc != ERROR_SUCCESS)
2469 {
2470 SetLastError(rc);
2471 goto cleanup;
2472 }
2473 RegCloseKey(hKey);
2474 hKey = NULL;
2475 /* Need to open the driver key */
2476 rc = RegOpenKeyExW(
2477 RootKey,
2478 REGSTR_PATH_CLASS_NT,
2479 0, /* Options */
2480 0,
2481 &hEnumKey);
2482 if (rc != ERROR_SUCCESS)
2483 {
2484 SetLastError(rc);
2485 goto cleanup;
2486 }
2487 rc = RegOpenKeyExW(
2488 hEnumKey,
2489 DriverKey,
2490 0, /* Options */
2491 samDesired,
2492 &hKey);
2493 if (rc != ERROR_SUCCESS)
2494 {
2495 SetLastError(rc);
2496 goto cleanup;
2497 }
2498 ret = hKey;
2499
2500 cleanup:
2501 if (hHWProfileKey != INVALID_HANDLE_VALUE)
2502 RegCloseKey(hHWProfileKey);
2503 if (hEnumKey != NULL)
2504 RegCloseKey(hEnumKey);
2505 if (hKey != NULL && hKey != ret)
2506 RegCloseKey(hKey);
2507 }
2508
2509 TRACE("Returning 0x%p\n", ret);
2510 return ret;
2511 }
2512
2513 /***********************************************************************
2514 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
2515 */
2516 BOOL WINAPI
2517 SetupDiCreateDeviceInfoA(
2518 IN HDEVINFO DeviceInfoSet,
2519 IN PCSTR DeviceName,
2520 IN CONST GUID *ClassGuid,
2521 IN PCSTR DeviceDescription OPTIONAL,
2522 IN HWND hwndParent OPTIONAL,
2523 IN DWORD CreationFlags,
2524 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
2525 {
2526 LPWSTR DeviceNameW = NULL;
2527 LPWSTR DeviceDescriptionW = NULL;
2528 BOOL bResult;
2529
2530 TRACE("\n");
2531
2532 if (DeviceName)
2533 {
2534 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
2535 if (DeviceNameW == NULL) return FALSE;
2536 }
2537 if (DeviceDescription)
2538 {
2539 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
2540 if (DeviceDescriptionW == NULL)
2541 {
2542 if (DeviceNameW) MyFree(DeviceNameW);
2543 return FALSE;
2544 }
2545 }
2546
2547 bResult = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW,
2548 ClassGuid, DeviceDescriptionW,
2549 hwndParent, CreationFlags,
2550 DeviceInfoData);
2551
2552 if (DeviceNameW) MyFree(DeviceNameW);
2553 if (DeviceDescriptionW) MyFree(DeviceDescriptionW);
2554
2555 return bResult;
2556 }
2557
2558 /***********************************************************************
2559 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
2560 */
2561 BOOL WINAPI
2562 SetupDiCreateDeviceInfoW(
2563 IN HDEVINFO DeviceInfoSet,
2564 IN PCWSTR DeviceName,
2565 IN CONST GUID *ClassGuid,
2566 IN PCWSTR DeviceDescription OPTIONAL,
2567 IN HWND hwndParent OPTIONAL,
2568 IN DWORD CreationFlags,
2569 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
2570 {
2571 struct DeviceInfoSet *list;
2572 BOOL ret = FALSE;
2573
2574 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet, debugstr_w(DeviceName),
2575 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
2576 hwndParent, CreationFlags, DeviceInfoData);
2577
2578 if (!DeviceInfoSet)
2579 SetLastError(ERROR_INVALID_HANDLE);
2580 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2581 SetLastError(ERROR_INVALID_HANDLE);
2582 else if (!ClassGuid)
2583 SetLastError(ERROR_INVALID_PARAMETER);
2584 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, ClassGuid))
2585 SetLastError(ERROR_CLASS_MISMATCH);
2586 else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
2587 {
2588 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
2589 SetLastError(ERROR_INVALID_FLAGS);
2590 }
2591 else
2592 {
2593 SP_DEVINFO_DATA DevInfo;
2594
2595 if (CreationFlags & DICD_GENERATE_ID)
2596 {
2597 /* Generate a new unique ID for this device */
2598 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2599 FIXME("not implemented\n");
2600 }
2601 else
2602 {
2603 /* Device name is fully qualified. Try to open it */
2604 BOOL rc;
2605
2606 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
2607 rc = SetupDiOpenDeviceInfoW(
2608 DeviceInfoSet,
2609 DeviceName,
2610 NULL, /* hwndParent */
2611 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
2612 &DevInfo);
2613
2614 if (rc)
2615 {
2616 /* SetupDiOpenDeviceInfoW has already added
2617 * the device info to the device info set
2618 */
2619 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
2620 }
2621 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
2622 {
2623 struct DeviceInfoElement *deviceInfo;
2624
2625 if (CreateDeviceInfoElement(list, DeviceName, ClassGuid, &deviceInfo))
2626 {
2627 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
2628
2629 if (!DeviceInfoData)
2630 ret = TRUE;
2631 else
2632 {
2633 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
2634 {
2635 SetLastError(ERROR_INVALID_USER_BUFFER);
2636 }
2637 else
2638 {
2639 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
2640 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
2641 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
2642 ret = TRUE;
2643 }
2644 }
2645 }
2646 }
2647 }
2648 }
2649
2650 TRACE("Returning %d\n", ret);
2651 return ret;
2652 }
2653
2654
2655 /***********************************************************************
2656 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
2657 */
2658 BOOL WINAPI
2659 SetupDiDeleteDeviceInfo(
2660 IN HDEVINFO DeviceInfoSet,
2661 IN PSP_DEVINFO_DATA DeviceInfoData)
2662 {
2663 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
2664
2665 FIXME("not implemented\n");
2666 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2667 return FALSE;
2668 }
2669
2670
2671 /***********************************************************************
2672 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
2673 */
2674 BOOL WINAPI
2675 SetupDiOpenDeviceInfoA(
2676 IN HDEVINFO DeviceInfoSet,
2677 IN PCSTR DeviceInstanceId,
2678 IN HWND hwndParent OPTIONAL,
2679 IN DWORD OpenFlags,
2680 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
2681 {
2682 LPWSTR DeviceInstanceIdW = NULL;
2683 BOOL bResult;
2684
2685 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
2686
2687 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
2688 if (DeviceInstanceIdW == NULL)
2689 return FALSE;
2690
2691 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
2692 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
2693
2694 MyFree(DeviceInstanceIdW);
2695
2696 return bResult;
2697 }
2698
2699
2700 /***********************************************************************
2701 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
2702 */
2703 BOOL WINAPI
2704 SetupDiOpenDeviceInfoW(
2705 IN HDEVINFO DeviceInfoSet,
2706 IN PCWSTR DeviceInstanceId,
2707 IN HWND hwndParent OPTIONAL,
2708 IN DWORD OpenFlags,
2709 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
2710 {
2711 struct DeviceInfoSet *list;
2712 HKEY hEnumKey, hKey = NULL;
2713 DWORD rc;
2714 BOOL ret = FALSE;
2715
2716 TRACE("%p %s %p %lx %p\n",
2717 DeviceInfoSet, debugstr_w(DeviceInstanceId),
2718 hwndParent, OpenFlags, DeviceInfoData);
2719
2720 if (OpenFlags & DIOD_CANCEL_REMOVE)
2721 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
2722
2723 if (!DeviceInfoSet)
2724 SetLastError(ERROR_INVALID_HANDLE);
2725 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2726 SetLastError(ERROR_INVALID_HANDLE);
2727 else if (!DeviceInstanceId)
2728 SetLastError(ERROR_INVALID_PARAMETER);
2729 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
2730 {
2731 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
2732 SetLastError(ERROR_INVALID_FLAGS);
2733 }
2734 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2735 SetLastError(ERROR_INVALID_USER_BUFFER);
2736 else
2737 {
2738 struct DeviceInfoElement *deviceInfo = NULL;
2739 /* Search if device already exists in DeviceInfoSet.
2740 * If yes, return the existing element
2741 * If no, create a new element using informations in registry
2742 */
2743 PLIST_ENTRY ItemList = list->ListHead.Flink;
2744 while (ItemList != &list->ListHead)
2745 {
2746 // TODO
2747 //if (good one)
2748 // break;
2749 FIXME("not implemented\n");
2750 ItemList = ItemList->Flink;
2751 }
2752
2753 if (deviceInfo)
2754 {
2755 /* good one found */
2756 ret = TRUE;
2757 }
2758 else
2759 {
2760 /* Open supposed registry key */
2761 rc = RegOpenKeyExW(
2762 list->HKLM,
2763 REGSTR_PATH_SYSTEMENUM,
2764 0, /* Options */
2765 0,
2766 &hEnumKey);
2767 if (rc != ERROR_SUCCESS)
2768 {
2769 SetLastError(rc);
2770 goto cleanup;
2771 }
2772 rc = RegOpenKeyExW(
2773 hEnumKey,
2774 DeviceInstanceId,
2775 0, /* Options */
2776 KEY_QUERY_VALUE,
2777 &hKey);
2778 RegCloseKey(hEnumKey);
2779 if (rc != ERROR_SUCCESS)
2780 {
2781 if (rc == ERROR_FILE_NOT_FOUND)
2782 rc = ERROR_NO_SUCH_DEVINST;
2783 SetLastError(rc);
2784 goto cleanup;
2785 }
2786
2787 /* FIXME: try to get ClassGUID from registry, instead of
2788 * sending GUID_NULL to CreateDeviceInfoElement
2789 */
2790 if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
2791 goto cleanup;
2792 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
2793
2794 ret = TRUE;
2795 }
2796
2797 if (ret && deviceInfo && DeviceInfoData)
2798 {
2799 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
2800 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
2801 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
2802 }
2803 }
2804
2805 cleanup:
2806 if (hKey != NULL)
2807 RegCloseKey(hKey);
2808 return ret;
2809 }
2810
2811
2812 /***********************************************************************
2813 * SetupDiGetSelectedDevice (SETUPAPI.@)
2814 */
2815 BOOL WINAPI
2816 SetupDiGetSelectedDevice(
2817 IN HDEVINFO DeviceInfoSet,
2818 OUT PSP_DEVINFO_DATA DeviceInfoData)
2819 {
2820 struct DeviceInfoSet *list;
2821 BOOL ret = FALSE;
2822
2823 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
2824
2825 if (!DeviceInfoSet)
2826 SetLastError(ERROR_INVALID_HANDLE);
2827 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2828 SetLastError(ERROR_INVALID_HANDLE);
2829 else if (list->SelectedDevice == NULL)
2830 SetLastError(ERROR_NO_DEVICE_SELECTED);
2831 else if (!DeviceInfoData)
2832 SetLastError(ERROR_INVALID_PARAMETER);
2833 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2834 SetLastError(ERROR_INVALID_USER_BUFFER);
2835 else
2836 {
2837 memcpy(&DeviceInfoData->ClassGuid,
2838 &list->SelectedDevice->ClassGuid,
2839 sizeof(GUID));
2840 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst;
2841 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice;
2842 ret = TRUE;
2843 }
2844
2845 TRACE("Returning %d\n", ret);
2846 return ret;
2847 }
2848
2849
2850 /***********************************************************************
2851 * SetupDiSetSelectedDevice (SETUPAPI.@)
2852 */
2853 BOOL WINAPI
2854 SetupDiSetSelectedDevice(
2855 IN HDEVINFO DeviceInfoSet,
2856 IN PSP_DEVINFO_DATA DeviceInfoData)
2857 {
2858 struct DeviceInfoSet *list;
2859 BOOL ret = FALSE;
2860
2861 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
2862
2863 if (!DeviceInfoSet)
2864 SetLastError(ERROR_INVALID_HANDLE);
2865 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2866 SetLastError(ERROR_INVALID_HANDLE);
2867 else if (!DeviceInfoData)
2868 SetLastError(ERROR_INVALID_PARAMETER);
2869 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2870 SetLastError(ERROR_INVALID_USER_BUFFER);
2871 else if (DeviceInfoData->Reserved == 0)
2872 SetLastError(ERROR_INVALID_USER_BUFFER);
2873 else
2874 {
2875 list->SelectedDevice = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2876 ret = TRUE;
2877 }
2878
2879 TRACE("Returning %d\n", ret);
2880 return ret;
2881 }
2882
2883
2884 /* Return the current hardware profile id, or -1 if error */
2885 static DWORD
2886 GetCurrentHwProfile(
2887 IN HDEVINFO DeviceInfoSet)
2888 {
2889 HKEY hKey = NULL;
2890 DWORD dwRegType, dwLength;
2891 DWORD hwProfile;
2892 LONG rc;
2893 DWORD ret = (DWORD)-1;
2894
2895 rc = RegOpenKeyExW(
2896 ((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
2897 REGSTR_PATH_IDCONFIGDB,
2898 0, /* Options */
2899 KEY_QUERY_VALUE,
2900 &hKey);
2901 if (rc != ERROR_SUCCESS)
2902 {
2903 SetLastError(rc);
2904 goto cleanup;
2905 }
2906
2907 dwLength = sizeof(DWORD);
2908 rc = RegQueryValueExW(
2909 hKey,
2910 REGSTR_VAL_CURRENTCONFIG,
2911 NULL,
2912 &dwRegType,
2913 (LPBYTE)&hwProfile, &dwLength);
2914 if (rc != ERROR_SUCCESS)
2915 {
2916 SetLastError(rc);
2917 goto cleanup;
2918 }
2919 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
2920 {
2921 SetLastError(ERROR_GEN_FAILURE);
2922 goto cleanup;
2923 }
2924
2925 ret = hwProfile;
2926
2927 cleanup:
2928 if (hKey != NULL)
2929 RegCloseKey(hKey);
2930
2931 return hwProfile;
2932 }
2933
2934 static BOOL
2935 ResetDevice(
2936 IN HDEVINFO DeviceInfoSet,
2937 IN PSP_DEVINFO_DATA DeviceInfoData)
2938 {
2939 #ifndef __WINESRC__
2940 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
2941 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2942 NTSTATUS Status;
2943
2944 if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
2945 {
2946 /* At the moment, I only know how to start local devices */
2947 SetLastError(ERROR_INVALID_COMPUTERNAME);
2948 return FALSE;
2949 }
2950
2951 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, deviceInfo->DeviceName);
2952 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
2953 SetLastError(RtlNtStatusToDosError(Status));
2954 return NT_SUCCESS(Status);
2955 #else
2956 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
2957 return TRUE;
2958 #endif
2959 }
2960
2961 static BOOL StopDevice(
2962 IN HDEVINFO DeviceInfoSet,
2963 IN PSP_DEVINFO_DATA DeviceInfoData)
2964 {
2965 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
2966 return TRUE;
2967 }
2968
2969 /***********************************************************************
2970 * SetupDiChangeState (SETUPAPI.@)
2971 */
2972 BOOL WINAPI
2973 SetupDiChangeState(
2974 IN HDEVINFO DeviceInfoSet,
2975 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
2976 {
2977 PSP_PROPCHANGE_PARAMS PropChange;
2978 HKEY hKey = INVALID_HANDLE_VALUE;
2979 LPCWSTR RegistryValueName;
2980 DWORD dwConfigFlags, dwLength, dwRegType;
2981 LONG rc;
2982 BOOL ret = FALSE;
2983
2984 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
2985
2986 if (!DeviceInfoData)
2987 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams;
2988 else
2989 PropChange = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams;
2990 if (!PropChange)
2991 {
2992 SetLastError(ERROR_INVALID_PARAMETER);
2993 goto cleanup;
2994 }
2995
2996 if (PropChange->Scope == DICS_FLAG_GLOBAL)
2997 RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
2998 else
2999 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
3000
3001 switch (PropChange->StateChange)
3002 {
3003 case DICS_ENABLE:
3004 case DICS_DISABLE:
3005 {
3006 /* Enable/disable device in registry */
3007 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
3008 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
3009 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
3010 if (hKey == INVALID_HANDLE_VALUE)
3011 break;
3012 dwLength = sizeof(DWORD);
3013 rc = RegQueryValueExW(
3014 hKey,
3015 RegistryValueName,
3016 NULL,
3017 &dwRegType,
3018 (LPBYTE)&dwConfigFlags, &dwLength);
3019 if (rc == ERROR_FILE_NOT_FOUND)
3020 dwConfigFlags = 0;
3021 else if (rc != ERROR_SUCCESS)
3022 {
3023 SetLastError(rc);
3024 goto cleanup;
3025 }
3026 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
3027 {
3028 SetLastError(ERROR_GEN_FAILURE);
3029 goto cleanup;
3030 }
3031 if (PropChange->StateChange == DICS_ENABLE)
3032 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
3033 else
3034 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
3035 rc = RegSetValueEx(
3036 hKey,
3037 RegistryValueName,
3038 0,
3039 REG_DWORD,
3040 (LPBYTE)&dwConfigFlags, sizeof(DWORD));
3041 if (rc != ERROR_SUCCESS)
3042 {
3043 SetLastError(rc);
3044 goto cleanup;
3045 }
3046
3047 /* Enable/disable device if needed */
3048 if (PropChange->Scope == DICS_FLAG_GLOBAL
3049 || PropChange->HwProfile == 0
3050 || PropChange->HwProfile == GetCurrentHwProfile(DeviceInfoSet))
3051 {
3052 if (PropChange->StateChange == DICS_ENABLE)
3053 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
3054 else
3055 ret = StopDevice(DeviceInfoSet, DeviceInfoData);
3056 }
3057 else
3058 ret = TRUE;
3059 break;
3060 }
3061 case DICS_PROPCHANGE:
3062 {
3063 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
3064 break;
3065 }
3066 default:
3067 {
3068 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange);
3069 SetLastError(ERROR_NOT_SUPPORTED);
3070 }
3071 }
3072
3073 cleanup:
3074 if (hKey != INVALID_HANDLE_VALUE)
3075 RegCloseKey(hKey);
3076
3077 TRACE("Returning %d\n", ret);
3078 return ret;
3079 }
3080
3081 /***********************************************************************
3082 * SetupDiSelectDevice (SETUPAPI.@)
3083 */
3084 BOOL WINAPI
3085 SetupDiSelectDevice(
3086 IN HDEVINFO DeviceInfoSet,
3087 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
3088 {
3089 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData);
3090 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3091 return FALSE;
3092 }
3093
3094
3095 /***********************************************************************
3096 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
3097 */
3098 BOOL WINAPI
3099 SetupDiRegisterCoDeviceInstallers(
3100 IN HDEVINFO DeviceInfoSet,
3101 IN PSP_DEVINFO_DATA DeviceInfoData)
3102 {
3103 BOOL ret = FALSE; /* Return value */
3104
3105 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
3106
3107 if (!DeviceInfoSet)
3108 SetLastError(ERROR_INVALID_PARAMETER);
3109 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3110 SetLastError(ERROR_INVALID_HANDLE);
3111 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3112 SetLastError(ERROR_INVALID_HANDLE);
3113 else if (!DeviceInfoData)
3114 SetLastError(ERROR_INVALID_PARAMETER);
3115 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3116 SetLastError(ERROR_INVALID_USER_BUFFER);
3117 else
3118 {
3119 SP_DEVINSTALL_PARAMS_W InstallParams;
3120 struct DriverInfoElement *SelectedDriver;
3121 BOOL Result;
3122 DWORD DoAction;
3123 WCHAR SectionName[MAX_PATH];
3124 DWORD SectionNameLength = 0;
3125 HKEY hKey = INVALID_HANDLE_VALUE;
3126 PVOID Context = NULL;
3127
3128 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3129 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3130 if (!Result)
3131 goto cleanup;
3132
3133 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
3134 if (SelectedDriver == NULL)
3135 {
3136 SetLastError(ERROR_NO_DRIVER_SELECTED);
3137 goto cleanup;
3138 }
3139
3140 /* Get .CoInstallers section name */
3141 Result = SetupDiGetActualSectionToInstallW(
3142 SelectedDriver->InfFileDetails->hInf,
3143 SelectedDriver->Details.SectionName,
3144 SectionName, MAX_PATH, &SectionNameLength, NULL);
3145 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1)
3146 goto cleanup;
3147 lstrcatW(SectionName, DotCoInstallers);
3148
3149 /* Open/Create driver key information */
3150 #if _WIN32_WINNT >= 0x502
3151 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
3152 #else
3153 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
3154 #endif
3155 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
3156 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
3157 if (hKey == INVALID_HANDLE_VALUE)
3158 goto cleanup;
3159
3160 /* Install .CoInstallers section */
3161 DoAction = SPINST_REGISTRY;
3162 if (!(InstallParams.Flags & DI_NOFILECOPY))
3163 {
3164 DoAction |= SPINST_FILES;
3165 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
3166 if (!Context)
3167 goto cleanup;
3168 }
3169 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
3170 SelectedDriver->InfFileDetails->hInf, SectionName,
3171 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
3172 SetupDefaultQueueCallback, Context,
3173 DeviceInfoSet, DeviceInfoData);
3174 if (!Result)
3175 goto cleanup;
3176
3177 ret = TRUE;
3178
3179 cleanup:
3180 if (Context)
3181 SetupTermDefaultQueueCallback(Context);
3182 if (hKey != INVALID_HANDLE_VALUE)
3183 RegCloseKey(hKey);
3184 }
3185
3186 TRACE("Returning %d\n", ret);
3187 return ret;
3188 }
3189
3190 static BOOL
3191 InfIsFromOEMLocation(
3192 IN PCWSTR FullName,
3193 OUT LPBOOL IsOEMLocation)
3194 {
3195 PWCHAR last;
3196
3197 last = strrchrW(FullName, '\\');
3198 if (!last)
3199 {
3200 /* No directory specified */
3201 *IsOEMLocation = FALSE;
3202 }
3203 else
3204 {
3205 LPWSTR Windir;
3206 UINT ret;
3207
3208 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR));
3209 if (!Windir)
3210 {
3211 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3212 return FALSE;
3213 }
3214
3215 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH);
3216 if (ret == 0 || ret > MAX_PATH)
3217 {
3218 MyFree(Windir);
3219 SetLastError(ERROR_GEN_FAILURE);
3220 return FALSE;
3221 }
3222 if (*Windir && Windir[strlenW(Windir) - 1] != '\\')
3223 strcatW(Windir, BackSlash);
3224 strcatW(Windir, InfDirectory);
3225
3226 if (strncmpiW(FullName, Windir, last - FullName) == 0)
3227 {
3228 /* The path is %SYSTEMROOT%\Inf */
3229 *IsOEMLocation = FALSE;
3230 }
3231 else
3232 {
3233 /* The file is in another place */
3234 *IsOEMLocation = TRUE;
3235 }
3236 MyFree(Windir);
3237 }
3238 return TRUE;
3239 }
3240
3241 /***********************************************************************
3242 * SetupDiInstallDevice (SETUPAPI.@)
3243 */
3244 BOOL WINAPI
3245 SetupDiInstallDevice(
3246 IN HDEVINFO DeviceInfoSet,
3247 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
3248 {
3249 SP_DEVINSTALL_PARAMS_W InstallParams;
3250 struct DriverInfoElement *SelectedDriver;
3251 SYSTEMTIME DriverDate;
3252 WCHAR SectionName[MAX_PATH];
3253 WCHAR Buffer[32];
3254 DWORD SectionNameLength = 0;
3255 BOOL Result = FALSE;
3256 ULONG DoAction;
3257 DWORD RequiredSize;
3258 LPWSTR pSectionName = NULL;
3259 WCHAR ClassName[MAX_CLASS_NAME_LEN];
3260 GUID ClassGuid;
3261 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
3262 BOOL RebootRequired = FALSE;
3263 HKEY hKey = INVALID_HANDLE_VALUE;
3264 BOOL NeedtoCopyFile;
3265 LARGE_INTEGER fullVersion;
3266 LONG rc;
3267 PVOID Context = NULL;
3268 BOOL ret = FALSE; /* Return value */
3269
3270 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
3271
3272 if (!DeviceInfoSet)
3273 SetLastError(ERROR_INVALID_PARAMETER);
3274 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3275 SetLastError(ERROR_INVALID_HANDLE);
3276 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
3277 SetLastError(ERROR_INVALID_HANDLE);
3278 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3279 SetLastError(ERROR_INVALID_USER_BUFFER);
3280 else
3281 Result = TRUE;
3282
3283 if (!Result)
3284 {
3285 /* One parameter is bad */
3286 goto cleanup;
3287 }
3288
3289 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3290 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3291 if (!Result)
3292 goto cleanup;
3293
3294 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
3295 {
3296 /* Set FAILEDINSTALL in ConfigFlags registry value */
3297 DWORD ConfigFlags, regType;
3298 Result = SetupDiGetDeviceRegistryPropertyW(
3299 DeviceInfoSet,
3300 DeviceInfoData,
3301 SPDRP_CONFIGFLAGS,
3302 &regType,
3303 (PBYTE)&ConfigFlags,
3304 sizeof(ConfigFlags),
3305 NULL);
3306 if (!Result || regType != REG_DWORD)
3307 {
3308 SetLastError(ERROR_GEN_FAILURE);
3309 goto cleanup;
3310 }
3311 ConfigFlags |= DNF_DISABLED;
3312 Result = SetupDiSetDeviceRegistryPropertyW(
3313 DeviceInfoSet,
3314 DeviceInfoData,
3315 SPDRP_CONFIGFLAGS,
3316 (PBYTE)&ConfigFlags,
3317 sizeof(ConfigFlags));
3318 if (!Result)
3319 {
3320 SetLastError(ERROR_GEN_FAILURE);
3321 goto cleanup;
3322 }
3323
3324 ret = TRUE;
3325 goto cleanup;
3326 }
3327
3328 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
3329 if (SelectedDriver == NULL)
3330 {
3331 SetLastError(ERROR_NO_DRIVER_SELECTED);
3332 goto cleanup;
3333 }
3334
3335 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
3336
3337 Result = SetupDiGetActualSectionToInstallW(
3338 SelectedDriver->InfFileDetails->hInf,
3339 SelectedDriver->Details.SectionName,
3340 SectionName, MAX_PATH, &SectionNameLength, NULL);
3341 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices))
3342 goto cleanup;
3343 pSectionName = &SectionName[strlenW(SectionName)];
3344
3345 /* Get information from [Version] section */
3346 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
3347 goto cleanup;
3348 /* Format ClassGuid to a string */
3349 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
3350 goto cleanup;
3351 RequiredSize = lstrlenW(lpGuidString);
3352 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
3353 if (!lpFullGuidString)
3354 {
3355 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3356 goto cleanup;
3357 }
3358 lpFullGuidString[0] = '{';
3359 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
3360 lpFullGuidString[RequiredSize + 1] = '}';
3361 lpFullGuidString[RequiredSize + 2] = '\0';
3362
3363 /* Copy .inf file to Inf\ directory (if needed) */
3364 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile);
3365 if (!Result)
3366 goto cleanup;
3367 if (NeedtoCopyFile)
3368 {
3369 WCHAR NewFileName[MAX_PATH];
3370 struct InfFileDetails *newInfFileDetails;
3371 Result = SetupCopyOEMInfW(
3372 SelectedDriver->Details.InfFileName,
3373 NULL,
3374 SPOST_NONE,
3375 SP_COPY_NOOVERWRITE,
3376 NewFileName, MAX_PATH,
3377 NULL,
3378 NULL);
3379 if (!Result)
3380 goto cleanup;
3381 /* Create a new struct InfFileDetails, and set it to
3382 * SelectedDriver->InfFileDetails, to release use of
3383 * current InfFile */
3384 newInfFileDetails = CreateInfFileDetails(NewFileName);
3385 if (!newInfFileDetails)
3386 goto cleanup;
3387 DereferenceInfFile(SelectedDriver->InfFileDetails);
3388 SelectedDriver->InfFileDetails = newInfFileDetails;
3389 strcpyW(SelectedDriver->Details.InfFileName, NewFileName);
3390 }
3391
3392 /* Open/Create driver key information */
3393 #if _WIN32_WINNT >= 0x502
3394 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
3395 #else
3396 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
3397 #endif
3398 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
3399 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
3400 if (hKey == INVALID_HANDLE_VALUE)
3401 goto cleanup;
3402
3403 /* Install main section */
3404 DoAction = 0;
3405 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
3406 DoAction |= SPINST_REGISTRY;
3407 if (!(InstallParams.Flags & DI_NOFILECOPY))
3408 {
3409 DoAction |= SPINST_FILES;
3410 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
3411 if (!Context)
3412 goto cleanup;
3413 }
3414 *pSectionName = '\0';
3415 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
3416 SelectedDriver->InfFileDetails->hInf, SectionName,
3417 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
3418 SetupDefaultQueueCallback, Context,
3419 DeviceInfoSet, DeviceInfoData);
3420 if (!Result)
3421 goto cleanup;
3422 InstallParams.Flags |= DI_NOFILECOPY;
3423 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3424
3425 /* Write information to driver key */
3426 *pSectionName = UNICODE_NULL;
3427 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
3428 TRACE("Write information to driver key\n");
3429 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
3430 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
3431 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
3432 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName));
3433 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
3434 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
3435 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId));
3436 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName));
3437 sprintfW(Buffer, L"%u-%u-%u", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
3438 rc = RegSetValueEx(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
3439 if (rc == ERROR_SUCCESS)
3440 rc = RegSetValueEx(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
3441 if (rc == ERROR_SUCCESS)
3442 rc = RegSetValueEx(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
3443 if (rc == ERROR_SUCCESS)
3444 {
3445 sprintfW(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
3446 rc = RegSetValueEx(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
3447 }
3448 if (rc == ERROR_SUCCESS)
3449 rc = RegSetValueEx(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR));
3450 if (rc == ERROR_SUCCESS)
3451 rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
3452 if (rc == ERROR_SUCCESS)
3453 rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTIONEXT, 0, REG_SZ, (const BYTE *)&SectionName[strlenW(SelectedDriver->Details.SectionName)], (strlenW(SectionName) - strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
3454 if (rc == ERROR_SUCCESS)
3455 rc = RegSetValueEx(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
3456 if (rc == ERROR_SUCCESS)
3457 rc = RegSetValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
3458 if (rc != ERROR_SUCCESS)
3459 {
3460 SetLastError(rc);
3461 goto cleanup;
3462 }
3463 RegCloseKey(hKey);
3464 hKey = INVALID_HANDLE_VALUE;
3465
3466 /* FIXME: Process .LogConfigOverride section */
3467
3468 /* Install .Services section */
3469 strcpyW(pSectionName, DotServices);
3470 Result = SetupInstallServicesFromInfSectionExW(
3471 SelectedDriver->InfFileDetails->hInf,
3472 SectionName,
3473 0,
3474 DeviceInfoSet,
3475 DeviceInfoData,
3476 NULL,
3477 NULL);
3478 if (!Result)
3479 goto cleanup;
3480 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
3481 RebootRequired = TRUE;
3482
3483 /* Open device registry key */
3484 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
3485 if (hKey == INVALID_HANDLE_VALUE)
3486 goto cleanup;
3487
3488 /* Install .HW section */
3489 DoAction = 0;
3490 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
3491 DoAction |= SPINST_REGISTRY;
3492 strcpyW(pSectionName, DotHW);
3493 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
3494 SelectedDriver->InfFileDetails->hInf, SectionName,
3495 DoAction, hKey, NULL, 0,
3496 NULL, NULL,
3497 DeviceInfoSet, DeviceInfoData);
3498 if (!Result)
3499 goto cleanup;
3500
3501 /* Write information to enum key */
3502 TRACE("Write information to enum key\n");
3503 TRACE("Class : '%s'\n", debugstr_w(ClassName));
3504 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString));
3505 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
3506 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName));
3507 rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR));
3508 if (rc == ERROR_SUCCESS)
3509 rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR));
3510 if (rc == ERROR_SUCCESS)
3511 rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
3512 if (rc == ERROR_SUCCESS)
3513 rc = RegSetValueEx(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
3514 if (rc != ERROR_SUCCESS)
3515 {
3516 SetLastError(rc);
3517 goto cleanup;
3518 }
3519
3520 /* Start the device */
3521 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
3522 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
3523 else
3524 ret = TRUE;
3525
3526 cleanup:
3527 /* End of installation */
3528 if (hKey != INVALID_HANDLE_VALUE)
3529 RegCloseKey(hKey);
3530 if (lpGuidString)
3531 RpcStringFreeW(&lpGuidString);
3532 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
3533 if (Context)
3534 SetupTermDefaultQueueCallback(Context);
3535 TRACE("Returning %d\n", ret);
3536 return ret;
3537 }