Merge SetupGetFileCompressionInfo[Ex]A/W, SetupDecompressOrCopyFileA/W, SetupGetSourc...
[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 DateFormat[] = {'%','u','-','%','u','-','%','u',0};
31 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
32 static const WCHAR DotHW[] = {'.','H','W',0};
33 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
34 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
35 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
36 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
37
38 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
39 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
40 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
41 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
42 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};
43
44 typedef DWORD
45 (CALLBACK* CLASS_INSTALL_PROC) (
46 IN DI_FUNCTION InstallFunction,
47 IN HDEVINFO DeviceInfoSet,
48 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
49 typedef BOOL
50 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
51 IN HDEVINFO DeviceInfoSet,
52 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
53 typedef DWORD
54 (CALLBACK* COINSTALLER_PROC) (
55 IN DI_FUNCTION InstallFunction,
56 IN HDEVINFO DeviceInfoSet,
57 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
58 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
59
60 struct CoInstallerElement
61 {
62 LIST_ENTRY ListEntry;
63
64 HMODULE Module;
65 COINSTALLER_PROC Function;
66 BOOL DoPostProcessing;
67 PVOID PrivateData;
68 };
69
70 struct GetSectionCallbackInfo
71 {
72 PSP_ALTPLATFORM_INFO PlatformInfo;
73 BYTE ProductType;
74 WORD SuiteMask;
75 DWORD PrefixLength;
76 WCHAR BestSection[LINE_LEN + 1];
77 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5;
78 };
79
80
81 /***********************************************************************
82 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
83 */
84 HDEVINFO WINAPI
85 SetupDiCreateDeviceInfoList(
86 IN CONST GUID *ClassGuid OPTIONAL,
87 IN HWND hwndParent OPTIONAL)
88 {
89 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
90 }
91
92 /***********************************************************************
93 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
94 */
95 HDEVINFO WINAPI
96 SetupDiCreateDeviceInfoListExA(
97 IN CONST GUID *ClassGuid OPTIONAL,
98 IN HWND hwndParent OPTIONAL,
99 IN PCSTR MachineName OPTIONAL,
100 IN PVOID Reserved)
101 {
102 LPWSTR MachineNameW = NULL;
103 HDEVINFO hDevInfo;
104
105 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
106 debugstr_a(MachineName), Reserved);
107
108 if (MachineName)
109 {
110 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
111 if (MachineNameW == NULL)
112 return (HDEVINFO)INVALID_HANDLE_VALUE;
113 }
114
115 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
116 MachineNameW, Reserved);
117
118 MyFree(MachineNameW);
119
120 return hDevInfo;
121 }
122
123 static DWORD
124 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
125 {
126 switch (cr)
127 {
128 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
129 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
130 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
131 case CR_FAILURE: return ERROR_GEN_FAILURE;
132 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER;
133 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER;
134 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
135 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER;
136 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
137 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER;
138 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER;
139 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND;
140 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
141 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND;
142 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
143 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE;
144 case CR_SUCCESS: return ERROR_SUCCESS;
145 default: return ERROR_GEN_FAILURE;
146 }
147
148 /* Does not happen */
149 }
150
151 /***********************************************************************
152 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
153 *
154 * Create an empty DeviceInfoSet list.
155 *
156 * PARAMS
157 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
158 * with this list.
159 * hwndParent [I] hwnd needed for interface related actions.
160 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
161 * local regestry will be used.
162 * Reserved [I] must be NULL
163 *
164 * RETURNS
165 * Success: empty list.
166 * Failure: INVALID_HANDLE_VALUE.
167 */
168 HDEVINFO WINAPI
169 SetupDiCreateDeviceInfoListExW(
170 IN CONST GUID *ClassGuid OPTIONAL,
171 IN HWND hwndParent OPTIONAL,
172 IN PCWSTR MachineName OPTIONAL,
173 IN PVOID Reserved)
174 {
175 struct DeviceInfoSet *list = NULL;
176 DWORD size;
177 DWORD rc;
178 CONFIGRET cr;
179 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;;
180
181 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
182 debugstr_w(MachineName), Reserved);
183
184 if (Reserved != NULL)
185 {
186 SetLastError(ERROR_INVALID_PARAMETER);
187 goto cleanup;
188 }
189
190 size = FIELD_OFFSET(struct DeviceInfoSet, szData);
191 if (MachineName)
192 size += (strlenW(MachineName) + 3) * sizeof(WCHAR);
193 list = MyMalloc(size);
194 if (!list)
195 {
196 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
197 goto cleanup;
198 }
199 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
200
201 list->magic = SETUP_DEV_INFO_SET_MAGIC;
202 memcpy(
203 &list->ClassGuid,
204 ClassGuid ? ClassGuid : &GUID_NULL,
205 sizeof(list->ClassGuid));
206 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
207 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
208 list->InstallParams.hwndParent = hwndParent;
209 if (MachineName)
210 {
211 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
212 if (rc != ERROR_SUCCESS)
213 {
214 SetLastError(ERROR_INVALID_MACHINENAME);
215 goto cleanup;
216 }
217
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(list->MachineName, &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 return ret;
249 }
250
251 /***********************************************************************
252 * SetupDiEnumDeviceInfo (SETUPAPI.@)
253 */
254 BOOL WINAPI
255 SetupDiEnumDeviceInfo(
256 IN HDEVINFO DeviceInfoSet,
257 IN DWORD MemberIndex,
258 OUT PSP_DEVINFO_DATA DeviceInfoData)
259 {
260 BOOL ret = FALSE;
261
262 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet, MemberIndex, DeviceInfoData);
263 if (!DeviceInfoData)
264 SetLastError(ERROR_INVALID_PARAMETER);
265 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
266 {
267 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
268
269 if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
270 SetLastError(ERROR_INVALID_HANDLE);
271 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
272 SetLastError(ERROR_INVALID_USER_BUFFER);
273 else
274 {
275 PLIST_ENTRY ItemList = list->ListHead.Flink;
276 while (ItemList != &list->ListHead && MemberIndex-- > 0)
277 ItemList = ItemList->Flink;
278 if (ItemList == &list->ListHead)
279 SetLastError(ERROR_NO_MORE_ITEMS);
280 else
281 {
282 struct DeviceInfoElement *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfoElement, ListEntry);
283 memcpy(&DeviceInfoData->ClassGuid,
284 &DevInfo->ClassGuid,
285 sizeof(GUID));
286 DeviceInfoData->DevInst = DevInfo->dnDevInst;
287 DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
288 ret = TRUE;
289 }
290 }
291 }
292 else
293 SetLastError(ERROR_INVALID_HANDLE);
294 return ret;
295 }
296
297 /***********************************************************************
298 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
299 */
300 BOOL WINAPI
301 SetupDiGetActualSectionToInstallA(
302 IN HINF InfHandle,
303 IN PCSTR InfSectionName,
304 OUT PSTR InfSectionWithExt OPTIONAL,
305 IN DWORD InfSectionWithExtSize,
306 OUT PDWORD RequiredSize OPTIONAL,
307 OUT PSTR *Extension OPTIONAL)
308 {
309 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
310 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
311 Extension, NULL);
312 }
313
314 /***********************************************************************
315 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
316 */
317 BOOL WINAPI
318 SetupDiGetActualSectionToInstallW(
319 IN HINF InfHandle,
320 IN PCWSTR InfSectionName,
321 OUT PWSTR InfSectionWithExt OPTIONAL,
322 IN DWORD InfSectionWithExtSize,
323 OUT PDWORD RequiredSize OPTIONAL,
324 OUT PWSTR *Extension OPTIONAL)
325 {
326 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
327 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
328 Extension, NULL);
329 }
330
331 /***********************************************************************
332 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
333 */
334 BOOL WINAPI
335 SetupDiGetActualSectionToInstallExA(
336 IN HINF InfHandle,
337 IN PCSTR InfSectionName,
338 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
339 OUT PSTR InfSectionWithExt OPTIONAL,
340 IN DWORD InfSectionWithExtSize,
341 OUT PDWORD RequiredSize OPTIONAL,
342 OUT PSTR* Extension OPTIONAL,
343 IN PVOID Reserved)
344 {
345 LPWSTR InfSectionNameW = NULL;
346 LPWSTR InfSectionWithExtW = NULL;
347 PWSTR ExtensionW;
348 BOOL bResult = FALSE;
349
350 TRACE("\n");
351
352 if (InfSectionName)
353 {
354 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
355 if (InfSectionNameW == NULL)
356 goto cleanup;
357 }
358 if (InfSectionWithExt)
359 {
360 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
361 if (InfSectionWithExtW == NULL)
362 goto cleanup;
363 }
364
365 bResult = SetupDiGetActualSectionToInstallExW(
366 InfHandle, InfSectionNameW, AlternatePlatformInfo,
367 InfSectionWithExt ? InfSectionWithExtW : NULL,
368 InfSectionWithExtSize,
369 RequiredSize,
370 Extension ? &ExtensionW : NULL,
371 Reserved);
372
373 if (bResult && InfSectionWithExt)
374 {
375 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
376 InfSectionWithExtSize, NULL, NULL) != 0;
377 }
378 if (bResult && Extension)
379 {
380 if (ExtensionW == NULL)
381 *Extension = NULL;
382 else
383 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
384 }
385
386 cleanup:
387 MyFree(InfSectionNameW);
388 MyFree(InfSectionWithExtW);
389
390 return bResult;
391 }
392
393 /* Lower scores are best ones */
394 static BOOL
395 CheckSectionValid(
396 IN LPCWSTR SectionName,
397 IN PSP_ALTPLATFORM_INFO PlatformInfo,
398 IN BYTE ProductType,
399 IN WORD SuiteMask,
400 OUT PDWORD ScorePlatform,
401 OUT PDWORD ScoreMajorVersion,
402 OUT PDWORD ScoreMinorVersion,
403 OUT PDWORD ScoreProductType,
404 OUT PDWORD ScoreSuiteMask)
405 {
406 LPWSTR Section = NULL;
407 LPCWSTR pExtensionPlatform, pExtensionArchitecture;
408 LPWSTR Fields[6];
409 DWORD i;
410 BOOL ret = FALSE;
411
412 static const WCHAR ExtensionPlatformNone[] = {'.',0};
413 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
414 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
415
416 static const WCHAR ExtensionArchitectureNone[] = {0};
417 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
418 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
419 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
420 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
421 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
422 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
423
424 TRACE("%s %p 0x%x 0x%x\n",
425 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
426
427 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
428
429 Section = DuplicateString(SectionName);
430 if (!Section)
431 {
432 TRACE("DuplicateString() failed\n");
433 goto cleanup;
434 }
435
436 /* Set various extensions values */
437 switch (PlatformInfo->Platform)
438 {
439 case VER_PLATFORM_WIN32_WINDOWS:
440 pExtensionPlatform = ExtensionPlatformWindows;
441 break;
442 case VER_PLATFORM_WIN32_NT:
443 pExtensionPlatform = ExtensionPlatformNT;
444 break;
445 default:
446 ERR("Unkown platform 0x%lx\n", PlatformInfo->Platform);
447 pExtensionPlatform = ExtensionPlatformNone;
448 break;
449 }
450 switch (PlatformInfo->ProcessorArchitecture)
451 {
452 case PROCESSOR_ARCHITECTURE_ALPHA:
453 pExtensionArchitecture = ExtensionArchitecturealpha;
454 break;
455 case PROCESSOR_ARCHITECTURE_AMD64:
456 pExtensionArchitecture = ExtensionArchitectureamd64;
457 break;
458 case PROCESSOR_ARCHITECTURE_IA64:
459 pExtensionArchitecture = ExtensionArchitectureia64;
460 break;
461 case PROCESSOR_ARCHITECTURE_INTEL:
462 pExtensionArchitecture = ExtensionArchitecturex86;
463 break;
464 case PROCESSOR_ARCHITECTURE_MIPS:
465 pExtensionArchitecture = ExtensionArchitecturemips;
466 break;
467 case PROCESSOR_ARCHITECTURE_PPC:
468 pExtensionArchitecture = ExtensionArchitectureppc;
469 break;
470 default:
471 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
472 case PROCESSOR_ARCHITECTURE_UNKNOWN:
473 pExtensionArchitecture = ExtensionArchitectureNone;
474 break;
475 }
476
477 /*
478 * Field[0] Platform
479 * Field[1] Architecture
480 * Field[2] Major version
481 * Field[3] Minor version
482 * Field[4] Product type
483 * Field[5] Suite mask
484 * Remark: lastests fields may be NULL if the information is not provided
485 */
486 Fields[0] = Section;
487 if (Fields[0] == NULL)
488 {
489 TRACE("No extension found\n");
490 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
491 ret = TRUE;
492 goto cleanup;
493 }
494 Fields[1] = Fields[0] + 1;
495 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
496 for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
497 {
498 Fields[i] = wcschr(Fields[i - 1], '.');
499 if (Fields[i])
500 {
501 Fields[i]++;
502 *(Fields[i] - 1) = UNICODE_NULL;
503 }
504 }
505 /* Take care of first 2 fields */
506 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
507 {
508 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
509 {
510 TRACE("Mismatch on platform field\n");
511 goto cleanup;
512 }
513 Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
514 }
515 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
516 {
517 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
518 {
519 TRACE("Mismatch on platform field\n");
520 goto cleanup;
521 }
522 Fields[1] += wcslen(ExtensionPlatformNT) - 1;
523 }
524 else
525 {
526 /* No platform specified */
527 *ScorePlatform |= 0x02;
528 }
529 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
530 {
531 /* No architecture specified */
532 *ScorePlatform |= 0x01;
533 }
534 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
535 {
536 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
537 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
538 goto cleanup;
539 }
540
541 /* Check if informations are matching */
542 if (Fields[2] && *Fields[2])
543 {
544 DWORD MajorVersion, MinorVersion = 0;
545 MajorVersion = strtoulW(Fields[2], NULL, 0);
546 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
547 (errno == ERANGE || errno == EINVAL))
548 {
549 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
550 goto cleanup;
551 }
552 if (Fields[3] && *Fields[3])
553 {
554 MinorVersion = strtoulW(Fields[3], NULL, 0);
555 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
556 (errno == ERANGE || errno == EINVAL))
557 {
558 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
559 goto cleanup;
560 }
561 }
562 if (PlatformInfo->MajorVersion < MajorVersion ||
563 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
564 {
565 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
566 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
567 goto cleanup;
568 }
569 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
570 if (MajorVersion == PlatformInfo->MajorVersion)
571 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
572 else
573 *ScoreMinorVersion = MinorVersion;
574 }
575 else if (Fields[3] && *Fields[3])
576 {
577 TRACE("Minor version found without major version\n");
578 goto cleanup;
579 }
580 else
581 {
582 *ScoreMajorVersion = PlatformInfo->MajorVersion;
583 *ScoreMinorVersion = PlatformInfo->MinorVersion;
584 }
585
586 if (Fields[4] && *Fields[4])
587 {
588 DWORD CurrentProductType;
589 CurrentProductType = strtoulW(Fields[4], NULL, 0);
590 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
591 (errno == ERANGE || errno == EINVAL))
592 {
593 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
594 goto cleanup;
595 }
596 if (CurrentProductType != ProductType)
597 {
598 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
599 CurrentProductType, ProductType);
600 goto cleanup;
601 }
602 }
603 else
604 *ScoreProductType = 1;
605
606 if (Fields[5] && *Fields[5])
607 {
608 DWORD CurrentSuiteMask;
609 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
610 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
611 (errno == ERANGE || errno == EINVAL))
612 {
613 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
614 goto cleanup;
615 }
616 if ((CurrentSuiteMask & ~SuiteMask) != 0)
617 {
618 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
619 CurrentSuiteMask, SuiteMask);
620 goto cleanup;
621 }
622 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
623 }
624 else
625 *ScoreSuiteMask = SuiteMask;
626
627 ret = TRUE;
628
629 cleanup:
630 MyFree(Section);
631 return ret;
632 }
633
634 static BOOL
635 GetSectionCallback(
636 IN LPCWSTR SectionName,
637 IN PVOID Context)
638 {
639 struct GetSectionCallbackInfo *info = Context;
640 DWORD Score1, Score2, Score3, Score4, Score5;
641 BOOL ret;
642
643 if (SectionName[info->PrefixLength] != '.')
644 return TRUE;
645
646 ret = CheckSectionValid(
647 &SectionName[info->PrefixLength],
648 info->PlatformInfo,
649 info->ProductType,
650 info->SuiteMask,
651 &Score1, &Score2, &Score3, &Score4, &Score5);
652 if (!ret)
653 {
654 TRACE("Section %s not compatible\n", debugstr_w(SectionName));
655 return TRUE;
656 }
657 if (Score1 > info->BestScore1) goto done;
658 if (Score1 < info->BestScore1) goto bettersection;
659 if (Score2 > info->BestScore2) goto done;
660 if (Score2 < info->BestScore2) goto bettersection;
661 if (Score3 > info->BestScore3) goto done;
662 if (Score3 < info->BestScore3) goto bettersection;
663 if (Score4 > info->BestScore4) goto done;
664 if (Score4 < info->BestScore4) goto bettersection;
665 if (Score5 > info->BestScore5) goto done;
666 if (Score5 < info->BestScore5) goto bettersection;
667 goto done;
668
669 bettersection:
670 strcpyW(info->BestSection, SectionName);
671 info->BestScore1 = Score1;
672 info->BestScore2 = Score2;
673 info->BestScore3 = Score3;
674 info->BestScore4 = Score4;
675 info->BestScore5 = Score5;
676
677 done:
678 return TRUE;
679 }
680
681 /***********************************************************************
682 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
683 */
684 BOOL WINAPI
685 SetupDiGetActualSectionToInstallExW(
686 IN HINF InfHandle,
687 IN PCWSTR InfSectionName,
688 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
689 OUT PWSTR InfSectionWithExt OPTIONAL,
690 IN DWORD InfSectionWithExtSize,
691 OUT PDWORD RequiredSize OPTIONAL,
692 OUT PWSTR* Extension OPTIONAL,
693 IN PVOID Reserved)
694 {
695 BOOL ret = FALSE;
696
697 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
698 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
699 RequiredSize, Extension, Reserved);
700
701 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
702 SetLastError(ERROR_INVALID_HANDLE);
703 else if (!InfSectionName)
704 SetLastError(ERROR_INVALID_PARAMETER);
705 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
706 SetLastError(ERROR_INVALID_USER_BUFFER);
707 else if (Reserved != NULL)
708 SetLastError(ERROR_INVALID_PARAMETER);
709 else
710 {
711 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
712 static BYTE CurrentProductType = 0;
713 static WORD CurrentSuiteMask = 0;
714 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
715 struct GetSectionCallbackInfo CallbackInfo;
716 DWORD dwFullLength;
717 BYTE ProductType;
718 WORD SuiteMask;
719
720 /* Fill platform info if needed */
721 if (AlternatePlatformInfo)
722 {
723 pPlatformInfo = AlternatePlatformInfo;
724 ProductType = 0;
725 SuiteMask = 0;
726 }
727 else
728 {
729 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
730 {
731 /* That's the first time we go here. We need to fill in the structure */
732 OSVERSIONINFOEX VersionInfo;
733 SYSTEM_INFO SystemInfo;
734 VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
735 ret = GetVersionExW((OSVERSIONINFO*)&VersionInfo);
736 if (!ret)
737 goto done;
738 GetSystemInfo(&SystemInfo);
739 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
740 CurrentPlatform.Platform = VersionInfo.dwPlatformId;
741 CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
742 CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
743 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
744 CurrentPlatform.Reserved = 0;
745 CurrentProductType = VersionInfo.wProductType;
746 CurrentSuiteMask = VersionInfo.wSuiteMask;
747 }
748 ProductType = CurrentProductType;
749 SuiteMask = CurrentSuiteMask;
750 }
751
752 CallbackInfo.PlatformInfo = pPlatformInfo;
753 CallbackInfo.ProductType = ProductType;
754 CallbackInfo.SuiteMask = SuiteMask;
755 CallbackInfo.PrefixLength = strlenW(InfSectionName);
756 CallbackInfo.BestScore1 = ULONG_MAX;
757 CallbackInfo.BestScore2 = ULONG_MAX;
758 CallbackInfo.BestScore3 = ULONG_MAX;
759 CallbackInfo.BestScore4 = ULONG_MAX;
760 CallbackInfo.BestScore5 = ULONG_MAX;
761 strcpyW(CallbackInfo.BestSection, InfSectionName);
762 if (!EnumerateSectionsStartingWith(
763 InfHandle,
764 InfSectionName,
765 GetSectionCallback,
766 &CallbackInfo))
767 {
768 SetLastError(ERROR_GEN_FAILURE);
769 goto done;
770 }
771
772 dwFullLength = lstrlenW(CallbackInfo.BestSection);
773 if (RequiredSize != NULL)
774 *RequiredSize = dwFullLength + 1;
775
776 if (InfSectionWithExtSize > 0)
777 {
778 if (InfSectionWithExtSize < dwFullLength + 1)
779 {
780 SetLastError(ERROR_INSUFFICIENT_BUFFER);
781 goto done;
782 }
783 strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
784 if (Extension)
785 {
786 DWORD dwLength = lstrlenW(InfSectionName);
787 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
788 }
789 }
790
791 ret = TRUE;
792 }
793
794 done:
795 TRACE("Returning %d\n", ret);
796 return ret;
797 }
798
799
800 BOOL
801 CreateDeviceInfoElement(
802 IN struct DeviceInfoSet *list,
803 IN LPCWSTR InstancePath,
804 IN LPCGUID pClassGuid,
805 OUT struct DeviceInfoElement **pDeviceInfo)
806 {
807 DWORD size;
808 CONFIGRET cr;
809 struct DeviceInfoElement *deviceInfo;
810
811 *pDeviceInfo = NULL;
812
813 size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
814 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
815 if (!deviceInfo)
816 {
817 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
818 return FALSE;
819 }
820 ZeroMemory(deviceInfo, size);
821
822 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
823 if (cr != CR_SUCCESS)
824 {
825 SetLastError(GetErrorCodeFromCrCode(cr));
826 return FALSE;
827 }
828
829 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
830 strcpyW(deviceInfo->Data, InstancePath);
831 deviceInfo->DeviceName = deviceInfo->Data;
832 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
833 deviceInfo->DeviceDescription = NULL;
834 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
835 deviceInfo->CreationFlags = 0;
836 InitializeListHead(&deviceInfo->DriverListHead);
837 InitializeListHead(&deviceInfo->InterfaceListHead);
838
839 *pDeviceInfo = deviceInfo;
840 return TRUE;
841 }
842
843
844 static BOOL
845 DestroyClassInstallParams(struct ClassInstallParams* installParams)
846 {
847 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
848 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
849 return TRUE;
850 }
851
852 static BOOL
853 DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
854 {
855 PLIST_ENTRY ListEntry;
856 struct DriverInfoElement *driverInfo;
857 struct DeviceInterface *deviceInterface;
858
859 while (!IsListEmpty(&deviceInfo->DriverListHead))
860 {
861 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
862 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
863 if (!DestroyDriverInfoElement(driverInfo))
864 return FALSE;
865 }
866 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
867 {
868 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
869 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
870 if (!DestroyDeviceInterface(deviceInterface))
871 return FALSE;
872 }
873 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
874 return HeapFree(GetProcessHeap(), 0, deviceInfo);
875 }
876
877 static BOOL
878 DestroyDeviceInfoSet(struct DeviceInfoSet* list)
879 {
880 PLIST_ENTRY ListEntry;
881 struct DeviceInfoElement *deviceInfo;
882
883 while (!IsListEmpty(&list->ListHead))
884 {
885 ListEntry = RemoveHeadList(&list->ListHead);
886 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfoElement, ListEntry);
887 if (!DestroyDeviceInfoElement(deviceInfo))
888 return FALSE;
889 }
890 if (list->HKLM != HKEY_LOCAL_MACHINE)
891 RegCloseKey(list->HKLM);
892 CM_Disconnect_Machine(list->hMachine);
893 DestroyClassInstallParams(&list->ClassInstallParams);
894 return HeapFree(GetProcessHeap(), 0, list);
895 }
896
897 /***********************************************************************
898 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
899 */
900 BOOL WINAPI
901 SetupDiDestroyDeviceInfoList(
902 IN HDEVINFO DeviceInfoSet)
903 {
904 BOOL ret = FALSE;
905
906 TRACE("%p\n", DeviceInfoSet);
907 if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
908 {
909 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
910
911 if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
912 ret = DestroyDeviceInfoSet(list);
913 else
914 SetLastError(ERROR_INVALID_HANDLE);
915 }
916 else
917 SetLastError(ERROR_INVALID_HANDLE);
918
919 TRACE("Returning %d\n", ret);
920 return ret;
921 }
922
923 /***********************************************************************
924 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
925 */
926 BOOL WINAPI
927 SetupDiGetDeviceRegistryPropertyA(
928 IN HDEVINFO DeviceInfoSet,
929 IN PSP_DEVINFO_DATA DeviceInfoData,
930 IN DWORD Property,
931 OUT PDWORD PropertyRegDataType OPTIONAL,
932 OUT PBYTE PropertyBuffer OPTIONAL,
933 IN DWORD PropertyBufferSize,
934 OUT PDWORD RequiredSize OPTIONAL)
935 {
936 BOOL bResult;
937 BOOL bIsStringProperty;
938 DWORD RegType;
939 DWORD RequiredSizeA, RequiredSizeW;
940 DWORD PropertyBufferSizeW = 0;
941 PBYTE PropertyBufferW = NULL;
942
943 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
944 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
945 RequiredSize);
946
947 if (PropertyBufferSize != 0)
948 {
949 PropertyBufferSizeW = PropertyBufferSize * 2;
950 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
951 if (!PropertyBufferW)
952 {
953 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
954 return FALSE;
955 }
956 }
957
958 bResult = SetupDiGetDeviceRegistryPropertyW(
959 DeviceInfoSet,
960 DeviceInfoData,
961 Property,
962 &RegType,
963 PropertyBufferW,
964 PropertyBufferSizeW,
965 &RequiredSizeW);
966
967 if (bResult || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
968 {
969 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
970
971 if (bIsStringProperty)
972 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
973 else
974 RequiredSizeA = RequiredSizeW;
975 if (RequiredSize)
976 *RequiredSize = RequiredSizeA;
977 if (PropertyRegDataType)
978 *PropertyRegDataType = RegType;
979 }
980
981 if (!bResult)
982 {
983 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
984 return bResult;
985 }
986
987 if (RequiredSizeA <= PropertyBufferSize)
988 {
989 if (bIsStringProperty && PropertyBufferSize > 0)
990 {
991 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
992 {
993 /* Last error is already set by WideCharToMultiByte */
994 bResult = FALSE;
995 }
996 }
997 else
998 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
999 }
1000 else
1001 {
1002 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1003 bResult = FALSE;
1004 }
1005
1006 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
1007 return bResult;
1008 }
1009
1010 /***********************************************************************
1011 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1012 */
1013 BOOL WINAPI
1014 SetupDiGetDeviceRegistryPropertyW(
1015 IN HDEVINFO DeviceInfoSet,
1016 IN PSP_DEVINFO_DATA DeviceInfoData,
1017 IN DWORD Property,
1018 OUT PDWORD PropertyRegDataType OPTIONAL,
1019 OUT PBYTE PropertyBuffer OPTIONAL,
1020 IN DWORD PropertyBufferSize,
1021 OUT PDWORD RequiredSize OPTIONAL)
1022 {
1023 HKEY hEnumKey, hKey;
1024 DWORD rc;
1025 BOOL ret = FALSE;
1026
1027 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet, DeviceInfoData,
1028 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1029 RequiredSize);
1030
1031 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1032 SetLastError(ERROR_INVALID_HANDLE);
1033 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1034 SetLastError(ERROR_INVALID_HANDLE);
1035 else if (!DeviceInfoData)
1036 SetLastError(ERROR_INVALID_PARAMETER);
1037 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1038 SetLastError(ERROR_INVALID_USER_BUFFER);
1039 else if (Property >= SPDRP_MAXIMUM_PROPERTY)
1040 SetLastError(ERROR_INVALID_PARAMETER);
1041 else
1042 {
1043 struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
1044 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
1045
1046 switch (Property)
1047 {
1048 case SPDRP_CAPABILITIES:
1049 case SPDRP_CLASS:
1050 case SPDRP_CLASSGUID:
1051 case SPDRP_COMPATIBLEIDS:
1052 case SPDRP_CONFIGFLAGS:
1053 case SPDRP_DEVICEDESC:
1054 case SPDRP_DRIVER:
1055 case SPDRP_FRIENDLYNAME:
1056 case SPDRP_HARDWAREID:
1057 case SPDRP_LOCATION_INFORMATION:
1058 case SPDRP_LOWERFILTERS:
1059 case SPDRP_MFG:
1060 case SPDRP_SECURITY:
1061 case SPDRP_SERVICE:
1062 case SPDRP_UI_NUMBER:
1063 case SPDRP_UI_NUMBER_DESC_FORMAT:
1064 case SPDRP_UPPERFILTERS:
1065 {
1066 LPCWSTR RegistryPropertyName;
1067 DWORD BufferSize;
1068
1069 switch (Property)
1070 {
1071 case SPDRP_CAPABILITIES:
1072 RegistryPropertyName = REGSTR_VAL_CAPABILITIES; break;
1073 case SPDRP_CLASS:
1074 RegistryPropertyName = REGSTR_VAL_CLASS; break;
1075 case SPDRP_CLASSGUID:
1076 RegistryPropertyName = REGSTR_VAL_CLASSGUID; break;
1077 case SPDRP_COMPATIBLEIDS:
1078 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS; break;
1079 case SPDRP_CONFIGFLAGS:
1080 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS; break;
1081 case SPDRP_DEVICEDESC:
1082 RegistryPropertyName = REGSTR_VAL_DEVDESC; break;
1083 case SPDRP_DRIVER:
1084 RegistryPropertyName = REGSTR_VAL_DRIVER; break;
1085 case SPDRP_FRIENDLYNAME:
1086 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME; break;
1087 case SPDRP_HARDWAREID:
1088 RegistryPropertyName = REGSTR_VAL_HARDWAREID; break;
1089 case SPDRP_LOCATION_INFORMATION:
1090 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION; break;
1091 case SPDRP_LOWERFILTERS:
1092 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS; break;
1093 case SPDRP_MFG:
1094 RegistryPropertyName = REGSTR_VAL_MFG; break;
1095 case SPDRP_SECURITY:
1096 RegistryPropertyName = REGSTR_SECURITY; break;
1097 case SPDRP_SERVICE:
1098 RegistryPropertyName = REGSTR_VAL_SERVICE; break;
1099 case SPDRP_UI_NUMBER:
1100 RegistryPropertyName = REGSTR_VAL_UI_NUMBER; break;
1101 case SPDRP_UI_NUMBER_DESC_FORMAT:
1102 RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT; break;
1103 case SPDRP_UPPERFILTERS:
1104 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS; break;
1105 default:
1106 /* Should not happen */
1107 RegistryPropertyName = NULL; break;
1108 }
1109
1110 /* Open registry key name */
1111 rc = RegOpenKeyExW(
1112 list->HKLM,
1113 REGSTR_PATH_SYSTEMENUM,
1114 0, /* Options */
1115 0,
1116 &hEnumKey);
1117 if (rc != ERROR_SUCCESS)
1118 {
1119 SetLastError(rc);
1120 break;
1121 }
1122 rc = RegOpenKeyExW(
1123 hEnumKey,
1124 DevInfo->Data,
1125 0, /* Options */
1126 KEY_QUERY_VALUE,
1127 &hKey);
1128 RegCloseKey(hEnumKey);
1129 if (rc != ERROR_SUCCESS)
1130 {
1131 SetLastError(rc);
1132 break;
1133 }
1134 /* Read registry entry */
1135 BufferSize = PropertyBufferSize;
1136 rc = RegQueryValueExW(
1137 hKey,
1138 RegistryPropertyName,
1139 NULL, /* Reserved */
1140 PropertyRegDataType,
1141 PropertyBuffer,
1142 &BufferSize);
1143 if (RequiredSize)
1144 *RequiredSize = BufferSize;
1145 switch(rc) {
1146 case ERROR_SUCCESS:
1147 if (PropertyBuffer != NULL || BufferSize == 0)
1148 ret = TRUE;
1149 else
1150 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1151 break;
1152 case ERROR_MORE_DATA:
1153 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1154 break;
1155 default:
1156 SetLastError(rc);
1157 }
1158 RegCloseKey(hKey);
1159 break;
1160 }
1161
1162 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME:
1163 {
1164 DWORD required = (strlenW(DevInfo->Data) + 1) * sizeof(WCHAR);
1165
1166 if (PropertyRegDataType)
1167 *PropertyRegDataType = REG_SZ;
1168 if (RequiredSize)
1169 *RequiredSize = required;
1170 if (PropertyBufferSize >= required)
1171 {
1172 strcpyW((LPWSTR)PropertyBuffer, DevInfo->Data);
1173 ret = TRUE;
1174 }
1175 else
1176 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1177 break;
1178 }
1179
1180 /*case SPDRP_BUSTYPEGUID:
1181 case SPDRP_LEGACYBUSTYPE:
1182 case SPDRP_BUSNUMBER:
1183 case SPDRP_ENUMERATOR_NAME:
1184 case SPDRP_SECURITY_SDS:
1185 case SPDRP_DEVTYPE:
1186 case SPDRP_EXCLUSIVE:
1187 case SPDRP_CHARACTERISTICS:
1188 case SPDRP_ADDRESS:
1189 case SPDRP_DEVICE_POWER_DATA:*/
1190 #if (WINVER >= 0x501)
1191 /*case SPDRP_REMOVAL_POLICY:
1192 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
1193 case SPDRP_REMOVAL_POLICY_OVERRIDE:
1194 case SPDRP_INSTALL_STATE:*/
1195 #endif
1196
1197 default:
1198 {
1199 ERR("Property 0x%lx not implemented\n", Property);
1200 SetLastError(ERROR_NOT_SUPPORTED);
1201 }
1202 }
1203 }
1204
1205 TRACE("Returning %d\n", ret);
1206 return ret;
1207 }
1208
1209 /***********************************************************************
1210 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
1211 */
1212 BOOL WINAPI
1213 SetupDiSetDeviceRegistryPropertyA(
1214 IN HDEVINFO DeviceInfoSet,
1215 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
1216 IN DWORD Property,
1217 IN CONST BYTE *PropertyBuffer OPTIONAL,
1218 IN DWORD PropertyBufferSize)
1219 {
1220 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
1221 Property, PropertyBuffer, PropertyBufferSize);
1222 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1223 return FALSE;
1224 }
1225
1226 /***********************************************************************
1227 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
1228 */
1229 BOOL WINAPI
1230 SetupDiSetDeviceRegistryPropertyW(
1231 IN HDEVINFO DeviceInfoSet,
1232 IN OUT PSP_DEVINFO_DATA DeviceInfoData,
1233 IN DWORD Property,
1234 IN CONST BYTE *PropertyBuffer OPTIONAL,
1235 IN DWORD PropertyBufferSize)
1236 {
1237 struct DeviceInfoSet *list;
1238 BOOL ret = FALSE;
1239
1240 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
1241 Property, PropertyBuffer, PropertyBufferSize);
1242
1243 if (!DeviceInfoSet)
1244 SetLastError(ERROR_INVALID_HANDLE);
1245 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1246 SetLastError(ERROR_INVALID_HANDLE);
1247 else if (!DeviceInfoData)
1248 SetLastError(ERROR_INVALID_HANDLE);
1249 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1250 SetLastError(ERROR_INVALID_USER_BUFFER);
1251 else
1252 {
1253 switch (Property)
1254 {
1255 case SPDRP_COMPATIBLEIDS:
1256 case SPDRP_CONFIGFLAGS:
1257 case SPDRP_FRIENDLYNAME:
1258 case SPDRP_HARDWAREID:
1259 case SPDRP_LOCATION_INFORMATION:
1260 case SPDRP_LOWERFILTERS:
1261 case SPDRP_SECURITY:
1262 case SPDRP_SERVICE:
1263 case SPDRP_UI_NUMBER_DESC_FORMAT:
1264 case SPDRP_UPPERFILTERS:
1265 {
1266 LPCWSTR RegistryPropertyName;
1267 DWORD RegistryDataType;
1268 HKEY hKey;
1269 LONG rc;
1270
1271 switch (Property)
1272 {
1273 case SPDRP_COMPATIBLEIDS:
1274 RegistryPropertyName = REGSTR_VAL_COMPATIBLEIDS;
1275 RegistryDataType = REG_MULTI_SZ;
1276 break;
1277 case SPDRP_CONFIGFLAGS:
1278 RegistryPropertyName = REGSTR_VAL_CONFIGFLAGS;
1279 RegistryDataType = REG_DWORD;
1280 break;
1281 case SPDRP_FRIENDLYNAME:
1282 RegistryPropertyName = REGSTR_VAL_FRIENDLYNAME;
1283 RegistryDataType = REG_SZ;
1284 break;
1285 case SPDRP_HARDWAREID:
1286 RegistryPropertyName = REGSTR_VAL_HARDWAREID;
1287 RegistryDataType = REG_MULTI_SZ;
1288 break;
1289 case SPDRP_LOCATION_INFORMATION:
1290 RegistryPropertyName = REGSTR_VAL_LOCATION_INFORMATION;
1291 RegistryDataType = REG_SZ;
1292 break;
1293 case SPDRP_LOWERFILTERS:
1294 RegistryPropertyName = REGSTR_VAL_LOWERFILTERS;
1295 RegistryDataType = REG_MULTI_SZ;
1296 break;
1297 case SPDRP_SECURITY:
1298 RegistryPropertyName = REGSTR_SECURITY;
1299 RegistryDataType = REG_BINARY;
1300 break;
1301 case SPDRP_SERVICE:
1302 RegistryPropertyName = REGSTR_VAL_SERVICE;
1303 RegistryDataType = REG_SZ;
1304 break;
1305 case SPDRP_UI_NUMBER_DESC_FORMAT:
1306 RegistryPropertyName = REGSTR_UI_NUMBER_DESC_FORMAT;
1307 RegistryDataType = REG_SZ;
1308 break;
1309 case SPDRP_UPPERFILTERS:
1310 RegistryPropertyName = REGSTR_VAL_UPPERFILTERS;
1311 RegistryDataType = REG_MULTI_SZ;
1312 break;
1313 default:
1314 /* Should not happen */
1315 RegistryPropertyName = NULL;
1316 RegistryDataType = REG_BINARY;
1317 break;
1318 }
1319 /* Open device registry key */
1320 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
1321 if (hKey != INVALID_HANDLE_VALUE)
1322 {
1323 /* Write new data */
1324 rc = RegSetValueExW(
1325 hKey,
1326 RegistryPropertyName,
1327 0, /* Reserved */
1328 RegistryDataType,
1329 PropertyBuffer,
1330 PropertyBufferSize);
1331 if (rc == ERROR_SUCCESS)
1332 ret = TRUE;
1333 else
1334 SetLastError(rc);
1335 RegCloseKey(hKey);
1336 }
1337 break;
1338 }
1339
1340 /*case SPDRP_CHARACTERISTICS:
1341 case SPDRP_DEVTYPE:
1342 case SPDRP_EXCLUSIVE:*/
1343 #if (WINVER >= 0x501)
1344 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
1345 #endif
1346 //case SPDRP_SECURITY_SDS:
1347
1348 default:
1349 {
1350 ERR("Property 0x%lx not implemented\n", Property);
1351 SetLastError(ERROR_NOT_SUPPORTED);
1352 }
1353 }
1354 }
1355
1356 TRACE("Returning %d\n", ret);
1357 return ret;
1358 }
1359
1360
1361 static BOOL WINAPI
1362 IntSetupDiRegisterDeviceInfo(
1363 IN HDEVINFO DeviceInfoSet,
1364 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
1365 {
1366 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL);
1367 }
1368
1369 /***********************************************************************
1370 * SetupDiCallClassInstaller (SETUPAPI.@)
1371 */
1372 BOOL WINAPI
1373 SetupDiCallClassInstaller(
1374 IN DI_FUNCTION InstallFunction,
1375 IN HDEVINFO DeviceInfoSet,
1376 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
1377 {
1378 BOOL ret = FALSE;
1379
1380 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
1381
1382 if (!DeviceInfoSet)
1383 SetLastError(ERROR_INVALID_PARAMETER);
1384 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1385 SetLastError(ERROR_INVALID_HANDLE);
1386 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1387 SetLastError(ERROR_INVALID_HANDLE);
1388 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
1389 SetLastError(ERROR_INVALID_HANDLE);
1390 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1391 SetLastError(ERROR_INVALID_USER_BUFFER);
1392 else
1393 {
1394 SP_DEVINSTALL_PARAMS_W InstallParams;
1395 #define CLASS_COINSTALLER 0x1
1396 #define DEVICE_COINSTALLER 0x2
1397 #define CLASS_INSTALLER 0x4
1398 UCHAR CanHandle = 0;
1399 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
1400
1401 switch (InstallFunction)
1402 {
1403 case DIF_ADDPROPERTYPAGE_ADVANCED:
1404 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1405 break;
1406 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
1407 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1408 break;
1409 case DIF_ALLOW_INSTALL:
1410 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1411 break;
1412 case DIF_DETECT:
1413 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1414 break;
1415 case DIF_DESTROYPRIVATEDATA:
1416 CanHandle = CLASS_INSTALLER;
1417 break;
1418 case DIF_INSTALLDEVICE:
1419 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1420 DefaultHandler = SetupDiInstallDevice;
1421 break;
1422 case DIF_INSTALLDEVICEFILES:
1423 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1424 DefaultHandler = SetupDiInstallDriverFiles;
1425 break;
1426 case DIF_INSTALLINTERFACES:
1427 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1428 DefaultHandler = SetupDiInstallDeviceInterfaces;
1429 break;
1430 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
1431 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1432 break;
1433 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
1434 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1435 break;
1436 case DIF_NEWDEVICEWIZARD_PREANALYZE:
1437 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1438 break;
1439 case DIF_NEWDEVICEWIZARD_PRESELECT:
1440 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1441 break;
1442 case DIF_NEWDEVICEWIZARD_SELECT:
1443 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1444 break;
1445 case DIF_POWERMESSAGEWAKE:
1446 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1447 break;
1448 case DIF_PROPERTYCHANGE:
1449 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1450 DefaultHandler = SetupDiChangeState;
1451 break;
1452 case DIF_REGISTER_COINSTALLERS:
1453 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1454 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
1455 break;
1456 case DIF_REGISTERDEVICE:
1457 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1458 DefaultHandler = IntSetupDiRegisterDeviceInfo;
1459 break;
1460 case DIF_REMOVE:
1461 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1462 DefaultHandler = SetupDiRemoveDevice;
1463 break;
1464 case DIF_SELECTBESTCOMPATDRV:
1465 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1466 DefaultHandler = SetupDiSelectBestCompatDrv;
1467 break;
1468 case DIF_SELECTDEVICE:
1469 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
1470 DefaultHandler = SetupDiSelectDevice;
1471 break;
1472 case DIF_TROUBLESHOOTER:
1473 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1474 break;
1475 case DIF_UNREMOVE:
1476 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
1477 DefaultHandler = SetupDiUnremoveDevice;
1478 break;
1479 default:
1480 ERR("Install function %u not supported\n", InstallFunction);
1481 SetLastError(ERROR_NOT_SUPPORTED);
1482 }
1483
1484 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1485 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
1486 /* Don't process this call, as a parameter is invalid */
1487 CanHandle = 0;
1488
1489 if (CanHandle != 0)
1490 {
1491 LIST_ENTRY ClassCoInstallersListHead;
1492 LIST_ENTRY DeviceCoInstallersListHead;
1493 HMODULE ClassInstallerLibrary = NULL;
1494 CLASS_INSTALL_PROC ClassInstaller = NULL;
1495 COINSTALLER_CONTEXT_DATA Context;
1496 PLIST_ENTRY ListEntry;
1497 HKEY hKey;
1498 DWORD dwRegType, dwLength;
1499 DWORD rc = NO_ERROR;
1500
1501 InitializeListHead(&ClassCoInstallersListHead);
1502 InitializeListHead(&DeviceCoInstallersListHead);
1503
1504 if (CanHandle & DEVICE_COINSTALLER)
1505 {
1506 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
1507 if (hKey != INVALID_HANDLE_VALUE)
1508 {
1509 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
1510 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
1511 {
1512 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
1513 if (KeyBuffer != NULL)
1514 {
1515 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1516 if (rc == ERROR_SUCCESS)
1517 {
1518 LPWSTR ptr;
1519 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
1520 {
1521 /* Add coinstaller to DeviceCoInstallersListHead list */
1522 struct CoInstallerElement *coinstaller;
1523 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
1524 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
1525 if (!coinstaller)
1526 continue;
1527 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
1528 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
1529 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
1530 else
1531 HeapFree(GetProcessHeap(), 0, coinstaller);
1532 }
1533 }
1534 HeapFree(GetProcessHeap(), 0, KeyBuffer);
1535 }
1536 }
1537 RegCloseKey(hKey);
1538 }
1539 }
1540 if (CanHandle & CLASS_COINSTALLER)
1541 {
1542 rc = RegOpenKeyExW(
1543 HKEY_LOCAL_MACHINE,
1544 REGSTR_PATH_CODEVICEINSTALLERS,
1545 0, /* Options */
1546 KEY_QUERY_VALUE,
1547 &hKey);
1548 if (rc == ERROR_SUCCESS)
1549 {
1550 LPWSTR lpGuidString;
1551 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
1552 {
1553 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
1554 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
1555 {
1556 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
1557 if (KeyBuffer != NULL)
1558 {
1559 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1560 if (rc == ERROR_SUCCESS)
1561 {
1562 LPWSTR ptr;
1563 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
1564 {
1565 /* Add coinstaller to ClassCoInstallersListHead list */
1566 struct CoInstallerElement *coinstaller;
1567 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
1568 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
1569 if (!coinstaller)
1570 continue;
1571 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
1572 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
1573 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
1574 else
1575 HeapFree(GetProcessHeap(), 0, coinstaller);
1576 }
1577 }
1578 HeapFree(GetProcessHeap(), 0, KeyBuffer);
1579 }
1580 }
1581 RpcStringFreeW(&lpGuidString);
1582 }
1583 RegCloseKey(hKey);
1584 }
1585 }
1586 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
1587 {
1588 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
1589 if (hKey != INVALID_HANDLE_VALUE)
1590 {
1591 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
1592 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
1593 {
1594 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
1595 if (KeyBuffer != NULL)
1596 {
1597 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
1598 if (rc == ERROR_SUCCESS)
1599 {
1600 /* Get ClassInstaller function pointer */
1601 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
1602 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
1603 {
1604 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
1605 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
1606 }
1607 }
1608 HeapFree(GetProcessHeap(), 0, KeyBuffer);
1609 }
1610 }
1611 RegCloseKey(hKey);
1612 }
1613 }
1614
1615 /* Call Class co-installers */
1616 Context.PostProcessing = FALSE;
1617 rc = NO_ERROR;
1618 ListEntry = ClassCoInstallersListHead.Flink;
1619 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
1620 {
1621 struct CoInstallerElement *coinstaller;
1622 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1623 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1624 coinstaller->PrivateData = Context.PrivateData;
1625 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
1626 {
1627 coinstaller->DoPostProcessing = TRUE;
1628 rc = NO_ERROR;
1629 }
1630 ListEntry = ListEntry->Flink;
1631 }
1632
1633 /* Call Device co-installers */
1634 ListEntry = DeviceCoInstallersListHead.Flink;
1635 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
1636 {
1637 struct CoInstallerElement *coinstaller;
1638 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1639 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1640 coinstaller->PrivateData = Context.PrivateData;
1641 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
1642 {
1643 coinstaller->DoPostProcessing = TRUE;
1644 rc = NO_ERROR;
1645 }
1646 ListEntry = ListEntry->Flink;
1647 }
1648
1649 /* Call Class installer */
1650 if (ClassInstaller)
1651 {
1652 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
1653 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
1654 }
1655 else
1656 rc = ERROR_DI_DO_DEFAULT;
1657
1658 /* Call default handler */
1659 if (rc == ERROR_DI_DO_DEFAULT)
1660 {
1661 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
1662 {
1663 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
1664 rc = NO_ERROR;
1665 else
1666 rc = GetLastError();
1667 }
1668 else
1669 rc = NO_ERROR;
1670 }
1671
1672 /* Call Class co-installers that required postprocessing */
1673 Context.PostProcessing = TRUE;
1674 ListEntry = ClassCoInstallersListHead.Flink;
1675 while (ListEntry != &ClassCoInstallersListHead)
1676 {
1677 struct CoInstallerElement *coinstaller;
1678 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1679 if (coinstaller->DoPostProcessing)
1680 {
1681 Context.InstallResult = rc;
1682 Context.PrivateData = coinstaller->PrivateData;
1683 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1684 }
1685 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
1686 ListEntry = ListEntry->Flink;
1687 }
1688
1689 /* Call Device co-installers that required postprocessing */
1690 ListEntry = DeviceCoInstallersListHead.Flink;
1691 while (ListEntry != &DeviceCoInstallersListHead)
1692 {
1693 struct CoInstallerElement *coinstaller;
1694 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
1695 if (coinstaller->DoPostProcessing)
1696 {
1697 Context.InstallResult = rc;
1698 Context.PrivateData = coinstaller->PrivateData;
1699 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
1700 }
1701 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
1702 ListEntry = ListEntry->Flink;
1703 }
1704
1705 /* Free allocated memory */
1706 while (!IsListEmpty(&ClassCoInstallersListHead))
1707 {
1708 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
1709 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
1710 }
1711 while (!IsListEmpty(&DeviceCoInstallersListHead))
1712 {
1713 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
1714 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
1715 }
1716
1717 ret = (rc == NO_ERROR);
1718 }
1719 }
1720
1721 TRACE("Returning %d\n", ret);
1722 return ret;
1723 }
1724
1725 /***********************************************************************
1726 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
1727 */
1728 BOOL WINAPI
1729 SetupDiGetDeviceInfoListClass(
1730 IN HDEVINFO DeviceInfoSet,
1731 OUT LPGUID ClassGuid)
1732 {
1733 struct DeviceInfoSet *list;
1734 BOOL ret = FALSE;
1735
1736 TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
1737
1738 if (!DeviceInfoSet)
1739 SetLastError(ERROR_INVALID_HANDLE);
1740 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1741 SetLastError(ERROR_INVALID_HANDLE);
1742 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
1743 SetLastError(ERROR_NO_ASSOCIATED_CLASS);
1744 else
1745 {
1746 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
1747
1748 ret = TRUE;
1749 }
1750
1751 TRACE("Returning %d\n", ret);
1752 return ret;
1753 }
1754
1755 /***********************************************************************
1756 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
1757 */
1758 BOOL WINAPI
1759 SetupDiGetDeviceInfoListDetailW(
1760 IN HDEVINFO DeviceInfoSet,
1761 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
1762 {
1763 struct DeviceInfoSet *list;
1764 BOOL ret = FALSE;
1765
1766 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
1767
1768 if (!DeviceInfoSet)
1769 SetLastError(ERROR_INVALID_HANDLE);
1770 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1771 SetLastError(ERROR_INVALID_HANDLE);
1772 else if (!DeviceInfoListDetailData)
1773 SetLastError(ERROR_INVALID_PARAMETER);
1774 else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
1775 SetLastError(ERROR_INVALID_USER_BUFFER);
1776 else
1777 {
1778 memcpy(
1779 &DeviceInfoListDetailData->ClassGuid,
1780 &list->ClassGuid,
1781 sizeof(GUID));
1782 DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
1783 if (list->MachineName)
1784 strcpyW(DeviceInfoListDetailData->RemoteMachineName, list->MachineName + 2);
1785 else
1786 DeviceInfoListDetailData->RemoteMachineName[0] = 0;
1787
1788 ret = TRUE;
1789 }
1790
1791 TRACE("Returning %d\n", ret);
1792 return ret;
1793 }
1794
1795 /***********************************************************************
1796 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1797 */
1798 BOOL WINAPI
1799 SetupDiGetDeviceInstallParamsA(
1800 IN HDEVINFO DeviceInfoSet,
1801 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1802 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
1803 {
1804 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
1805 BOOL ret = FALSE;
1806
1807 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1808
1809 if (DeviceInstallParams == NULL)
1810 SetLastError(ERROR_INVALID_PARAMETER);
1811 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
1812 SetLastError(ERROR_INVALID_USER_BUFFER);
1813 else
1814 {
1815 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1816 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
1817
1818 if (ret)
1819 {
1820 /* Do W->A conversion */
1821 memcpy(
1822 DeviceInstallParams,
1823 &deviceInstallParamsW,
1824 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
1825 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
1826 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
1827 {
1828 DeviceInstallParams->DriverPath[0] = '\0';
1829 ret = FALSE;
1830 }
1831 }
1832 }
1833
1834 TRACE("Returning %d\n", ret);
1835 return ret;
1836 }
1837
1838 /***********************************************************************
1839 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
1840 */
1841 BOOL WINAPI
1842 SetupDiGetDeviceInstallParamsW(
1843 IN HDEVINFO DeviceInfoSet,
1844 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1845 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
1846 {
1847 struct DeviceInfoSet *list;
1848 BOOL ret = FALSE;
1849
1850 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1851
1852 if (!DeviceInfoSet)
1853 SetLastError(ERROR_INVALID_HANDLE);
1854 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1855 SetLastError(ERROR_INVALID_HANDLE);
1856 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1857 SetLastError(ERROR_INVALID_USER_BUFFER);
1858 else if (!DeviceInstallParams)
1859 SetLastError(ERROR_INVALID_PARAMETER);
1860 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
1861 SetLastError(ERROR_INVALID_USER_BUFFER);
1862 else
1863 {
1864 PSP_DEVINSTALL_PARAMS_W Source;
1865
1866 if (DeviceInfoData)
1867 Source = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
1868 else
1869 Source = &list->InstallParams;
1870 memcpy(DeviceInstallParams, Source, Source->cbSize);
1871 ret = TRUE;
1872 }
1873
1874 TRACE("Returning %d\n", ret);
1875 return ret;
1876 }
1877
1878 static BOOL
1879 CheckDeviceInstallParameters(
1880 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
1881 {
1882 DWORD SupportedFlags =
1883 DI_NOVCP | /* 0x00000008 */
1884 DI_DIDCOMPAT | /* 0x00000010 */
1885 DI_DIDCLASS | /* 0x00000020 */
1886 DI_NEEDRESTART | /* 0x00000080 */
1887 DI_NEEDREBOOT | /* 0x00000100 */
1888 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */
1889 DI_PROPERTIES_CHANGE | /* 0x00004000 */
1890 DI_ENUMSINGLEINF | /* 0x00010000 */
1891 DI_DONOTCALLCONFIGMG | /* 0x00020000 */
1892 DI_CLASSINSTALLPARAMS | /* 0x00100000 */
1893 DI_NODI_DEFAULTACTION | /* 0x00200000 */
1894 DI_QUIETINSTALL | /* 0x00800000 */
1895 DI_NOFILECOPY | /* 0x01000000 */
1896 DI_DRIVERPAGE_ADDED; /* 0x04000000 */
1897 DWORD SupportedFlagsEx =
1898 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */
1899 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */
1900 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */
1901 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */
1902 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */
1903 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */
1904 BOOL ret = FALSE;
1905
1906 /* FIXME: add support for more flags */
1907
1908 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
1909 * It should be checked before accessing to other values
1910 * of the SP_DEVINSTALL_PARAMS structure */
1911
1912 if (DeviceInstallParams->Flags & ~SupportedFlags)
1913 {
1914 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
1915 SetLastError(ERROR_INVALID_FLAGS);
1916 }
1917 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
1918 {
1919 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
1920 SetLastError(ERROR_INVALID_FLAGS);
1921 }
1922 else if ((DeviceInstallParams->Flags & DI_NOVCP)
1923 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
1924 SetLastError(ERROR_INVALID_USER_BUFFER);
1925 else
1926 {
1927 /* FIXME: check Reserved field */
1928 ret = TRUE;
1929 }
1930
1931 return ret;
1932 }
1933
1934 /***********************************************************************
1935 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
1936 */
1937 BOOL WINAPI
1938 SetupDiSetDeviceInstallParamsW(
1939 IN HDEVINFO DeviceInfoSet,
1940 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1941 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
1942 {
1943 struct DeviceInfoSet *list;
1944 BOOL ret = FALSE;
1945
1946 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1947
1948 if (!DeviceInfoSet)
1949 SetLastError(ERROR_INVALID_HANDLE);
1950 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
1951 SetLastError(ERROR_INVALID_HANDLE);
1952 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1953 SetLastError(ERROR_INVALID_USER_BUFFER);
1954 else if (!DeviceInstallParams)
1955 SetLastError(ERROR_INVALID_PARAMETER);
1956 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
1957 SetLastError(ERROR_INVALID_USER_BUFFER);
1958 else if (CheckDeviceInstallParameters(DeviceInstallParams))
1959 {
1960 PSP_DEVINSTALL_PARAMS_W Destination;
1961
1962 if (DeviceInfoData)
1963 Destination = &((struct DeviceInfoElement *)DeviceInfoData->Reserved)->InstallParams;
1964 else
1965 Destination = &list->InstallParams;
1966 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
1967 ret = TRUE;
1968 }
1969
1970 TRACE("Returning %d\n", ret);
1971 return ret;
1972 }
1973
1974 /***********************************************************************
1975 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
1976 */
1977 BOOL WINAPI
1978 SetupDiGetDeviceInstanceIdA(
1979 IN HDEVINFO DeviceInfoSet,
1980 IN PSP_DEVINFO_DATA DeviceInfoData,
1981 OUT PSTR DeviceInstanceId OPTIONAL,
1982 IN DWORD DeviceInstanceIdSize,
1983 OUT PDWORD RequiredSize OPTIONAL)
1984 {
1985 PWSTR DeviceInstanceIdW = NULL;
1986 BOOL ret = FALSE;
1987
1988 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
1989 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
1990
1991 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1992 SetLastError(ERROR_INVALID_PARAMETER);
1993 else
1994 {
1995 if (DeviceInstanceIdSize != 0)
1996 {
1997 DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
1998 if (DeviceInstanceIdW == NULL)
1999 return FALSE;
2000 }
2001
2002 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
2003 DeviceInstanceIdW, DeviceInstanceIdSize,
2004 RequiredSize);
2005
2006 if (ret && DeviceInstanceIdW != NULL)
2007 {
2008 if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
2009 DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
2010 {
2011 DeviceInstanceId[0] = '\0';
2012 ret = FALSE;
2013 }
2014 }
2015 }
2016
2017 TRACE("Returning %d\n", ret);
2018 return ret;
2019 }
2020
2021 /***********************************************************************
2022 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
2023 */
2024 BOOL WINAPI
2025 SetupDiGetDeviceInstanceIdW(
2026 IN HDEVINFO DeviceInfoSet,
2027 IN PSP_DEVINFO_DATA DeviceInfoData,
2028 OUT PWSTR DeviceInstanceId OPTIONAL,
2029 IN DWORD DeviceInstanceIdSize,
2030 OUT PDWORD RequiredSize OPTIONAL)
2031 {
2032 BOOL ret = FALSE;
2033
2034 TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
2035 DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
2036
2037 if (!DeviceInfoSet)
2038 SetLastError(ERROR_INVALID_HANDLE);
2039 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2040 SetLastError(ERROR_INVALID_HANDLE);
2041 else if (!DeviceInfoData)
2042 SetLastError(ERROR_INVALID_PARAMETER);
2043 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2044 SetLastError(ERROR_INVALID_USER_BUFFER);
2045 else if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
2046 SetLastError(ERROR_INVALID_PARAMETER);
2047 else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
2048 SetLastError(ERROR_INVALID_PARAMETER);
2049 else
2050 {
2051 struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2052 DWORD required;
2053
2054 required = (strlenW(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
2055 if (RequiredSize)
2056 *RequiredSize = required;
2057
2058 if (required <= DeviceInstanceIdSize)
2059 {
2060 strcpyW(DeviceInstanceId, DevInfo->DeviceName);
2061 ret = TRUE;
2062 }
2063 else
2064 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2065 }
2066
2067 TRACE("Returning %d\n", ret);
2068 return ret;
2069 }
2070
2071
2072 /***********************************************************************
2073 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
2074 */
2075 HKEY WINAPI
2076 SetupDiCreateDevRegKeyA(
2077 IN HDEVINFO DeviceInfoSet,
2078 IN PSP_DEVINFO_DATA DeviceInfoData,
2079 IN DWORD Scope,
2080 IN DWORD HwProfile,
2081 IN DWORD KeyType,
2082 IN HINF InfHandle OPTIONAL,
2083 IN PCSTR InfSectionName OPTIONAL)
2084 {
2085 PCWSTR InfSectionNameW = NULL;
2086 HKEY ret = INVALID_HANDLE_VALUE;
2087
2088 if (InfSectionName)
2089 {
2090 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2091 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
2092 }
2093
2094 ret = SetupDiCreateDevRegKeyW(DeviceInfoSet,
2095 DeviceInfoData,
2096 Scope,
2097 HwProfile,
2098 KeyType,
2099 InfHandle,
2100 InfSectionNameW);
2101
2102 if (InfSectionNameW != NULL)
2103 MyFree((PVOID)InfSectionNameW);
2104
2105 return ret;
2106 }
2107
2108 static HKEY
2109 OpenHardwareProfileKey(
2110 IN HKEY HKLM,
2111 IN DWORD HwProfile,
2112 IN DWORD samDesired)
2113 {
2114 HKEY hHWProfilesKey = NULL;
2115 HKEY hHWProfileKey = NULL;
2116 HKEY ret = INVALID_HANDLE_VALUE;
2117 LONG rc;
2118
2119 rc = RegOpenKeyExW(HKLM,
2120 REGSTR_PATH_HWPROFILES,
2121 0,
2122 0,
2123 &hHWProfilesKey);
2124 if (rc != ERROR_SUCCESS)
2125 {
2126 SetLastError(rc);
2127 goto cleanup;
2128 }
2129 if (HwProfile == 0)
2130 {
2131 rc = RegOpenKeyExW(
2132 hHWProfilesKey,
2133 REGSTR_KEY_CURRENT,
2134 0,
2135 KEY_CREATE_SUB_KEY,
2136 &hHWProfileKey);
2137 }
2138 else
2139 {
2140 WCHAR subKey[5];
2141 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile);
2142 subKey[4] = '\0';
2143 rc = RegOpenKeyExW(
2144 hHWProfilesKey,
2145 subKey,
2146 0,
2147 KEY_CREATE_SUB_KEY,
2148 &hHWProfileKey);
2149 }
2150 if (rc != ERROR_SUCCESS)
2151 {
2152 SetLastError(rc);
2153 goto cleanup;
2154 }
2155 ret = hHWProfileKey;
2156
2157 cleanup:
2158 if (hHWProfilesKey != NULL)
2159 RegCloseKey(hHWProfilesKey);
2160 if (hHWProfileKey != NULL && hHWProfileKey != ret)
2161 RegCloseKey(hHWProfileKey);
2162 return ret;
2163 }
2164
2165 /***********************************************************************
2166 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
2167 */
2168 HKEY WINAPI
2169 SetupDiCreateDevRegKeyW(
2170 IN HDEVINFO DeviceInfoSet,
2171 IN PSP_DEVINFO_DATA DeviceInfoData,
2172 IN DWORD Scope,
2173 IN DWORD HwProfile,
2174 IN DWORD KeyType,
2175 IN HINF InfHandle OPTIONAL,
2176 IN PCWSTR InfSectionName OPTIONAL)
2177 {
2178 struct DeviceInfoSet *list;
2179 HKEY ret = INVALID_HANDLE_VALUE;
2180
2181 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData,
2182 Scope, HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
2183
2184 if (!DeviceInfoSet)
2185 SetLastError(ERROR_INVALID_HANDLE);
2186 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
2187 SetLastError(ERROR_INVALID_HANDLE);
2188 else if (!DeviceInfoData)
2189 SetLastError(ERROR_INVALID_PARAMETER);
2190 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2191 SetLastError(ERROR_INVALID_USER_BUFFER);
2192 else if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
2193 SetLastError(ERROR_INVALID_PARAMETER);
2194 else if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
2195 SetLastError(ERROR_INVALID_PARAMETER);
2196 else if (InfHandle && !InfSectionName)
2197 SetLastError(ERROR_INVALID_PARAMETER);
2198 else if (!InfHandle && InfSectionName)
2199 SetLastError(ERROR_INVALID_PARAMETER);
2200 else
2201 {
2202 LPWSTR lpGuidString = NULL;
2203 LPWSTR DriverKey = NULL; /* {GUID}\Index */
2204 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
2205 DWORD Index; /* Index used in the DriverKey name */
2206 DWORD rc;
2207 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
2208 HKEY hEnumKey = NULL;
2209 HKEY hClassKey = NULL;
2210 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
2211 HKEY hKey = NULL;
2212 HKEY RootKey;
2213
2214 if (Scope == DICS_FLAG_GLOBAL)
2215 RootKey = list->HKLM;
2216 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
2217 {
2218 hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
2219 if (hHWProfileKey == INVALID_HANDLE_VALUE)
2220 goto cleanup;
2221 RootKey = hHWProfileKey;
2222 }
2223
2224 if (KeyType == DIREG_DEV)
2225 {
2226 struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
2227
2228 rc = RegCreateKeyExW(
2229 RootKey,
2230 REGSTR_PATH_SYSTEMENUM,
2231 0,
2232 NULL,
2233 REG_OPTION_NON_VOLATILE,
2234 KEY_CREATE_SUB_KEY,
2235 NULL,
2236 &hEnumKey,
2237 NULL);
2238 if (rc != ERROR_SUCCESS)
2239 {
2240 SetLastError(rc);
2241 goto cleanup;
2242 }
2243 rc = RegCreateKeyExW(
2244 hEnumKey,
2245 deviceInfo->DeviceName,
2246 0,
2247 NULL,
2248 REG_OPTION_NON_VOLATILE,
2249 #if _WIN32_WINNT >= 0x502
2250 KEY_READ | KEY_WRITE,
2251 #else
2252 KEY_ALL_ACCESS,
2253 #endif
2254 NULL,
2255 &hKey,
2256 NULL);
2257 if (rc != ERROR_SUCCESS)
2258 {
2259 SetLastError(rc);
2260 goto cleanup;
2261 }
2262 }
2263 else /* KeyType == DIREG_DRV */
2264 {
2265 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
2266 goto cleanup;
2267 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
2268 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
2269 if (!DriverKey)
2270 {
2271 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2272 goto cleanup;
2273 }
2274 DriverKey[0] = '{';
2275 strcpyW(&DriverKey[1], lpGuidString);
2276 pDeviceInstance = &DriverKey[strlenW(DriverKey)];
2277 *pDeviceInstance++ = '}';
2278 *pDeviceInstance++ = '\\';
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 sprintfW(pDeviceInstance, InstanceKeyFormat, Index);
2296 rc = RegCreateKeyExW(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 = RegSetValueExW(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 SETUPAPI_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 = RegSetValueExW(
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 == SETUPAPI_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 SetupDefaultQueueCallbackW, 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 SetupDefaultQueueCallbackW, 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 : '%ld.%ld.%lu.%ld'\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, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
3438 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
3439 if (rc == ERROR_SUCCESS)
3440 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
3441 if (rc == ERROR_SUCCESS)
3442 rc = RegSetValueExW(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, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
3446 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
3447 }
3448 if (rc == ERROR_SUCCESS)
3449 rc = RegSetValueExW(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 = RegSetValueExW(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 = RegSetValueExW(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 = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
3456 if (rc == ERROR_SUCCESS)
3457 rc = RegSetValueExW(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 = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR));
3508 if (rc == ERROR_SUCCESS)
3509 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR));
3510 if (rc == ERROR_SUCCESS)
3511 rc = RegSetValueExW(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 = RegSetValueExW(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 }