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