ReactOS  0.4.15-dev-3326-ga91f5e8
devinst.c
Go to the documentation of this file.
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 #include <pseh/pseh2.h>
25 
26 /* Unicode constants */
27 static const WCHAR BackSlash[] = {'\\',0};
28 static const WCHAR DateFormat[] = {'%','u','-','%','u','-','%','u',0};
29 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
30 static const WCHAR DotHW[] = {'.','H','W',0};
31 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
32 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
33 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
34 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
35 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
36 
37 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
38 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
39 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
40 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
41 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};
42 
43 typedef DWORD
45  IN DI_FUNCTION InstallFunction,
48 typedef BOOL
52 typedef DWORD
54  IN DI_FUNCTION InstallFunction,
58 
60 {
62 
67 };
68 
70 {
77 };
78 
79 
80 
82 {
83  static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
84  '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
85  'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
86  '0','2','X','}',0};
87 
88  sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
89  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
90  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
91 }
92 
93 DWORD
95 {
96  switch (cr)
97  {
101  case CR_FAILURE: return ERROR_GEN_FAILURE;
115  case CR_SUCCESS: return ERROR_SUCCESS;
116  default: return ERROR_GEN_FAILURE;
117  }
118 
119  /* Does not happen */
120 }
121 
122 /* Lower scores are best ones */
123 static BOOL
125  IN LPCWSTR SectionName,
126  IN PSP_ALTPLATFORM_INFO PlatformInfo,
127  IN BYTE ProductType,
128  IN WORD SuiteMask,
129  OUT PDWORD ScorePlatform,
130  OUT PDWORD ScoreMajorVersion,
131  OUT PDWORD ScoreMinorVersion,
132  OUT PDWORD ScoreProductType,
133  OUT PDWORD ScoreSuiteMask)
134 {
135  LPWSTR Section = NULL;
136  //LPCWSTR pExtensionPlatform;
137  LPCWSTR pExtensionArchitecture;
138  LPWSTR Fields[6];
139  DWORD i;
140  BOOL ret = FALSE;
141 
142  //static const WCHAR ExtensionPlatformNone[] = {'.',0};
143  static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
144  static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
145 
146  static const WCHAR ExtensionArchitectureNone[] = {0};
147  static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
148  static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
149  static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
150  static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
151  static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
152  static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
153 
154  TRACE("%s(%s %p 0x%x 0x%x)\n",
155  __FUNCTION__, debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
156 
157  *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
158 
159  Section = pSetupDuplicateString(SectionName);
160  if (!Section)
161  {
162  TRACE("pSetupDuplicateString() failed\n");
163  goto cleanup;
164  }
165 
166  /* Set various extensions values */
167  switch (PlatformInfo->Platform)
168  {
170  //pExtensionPlatform = ExtensionPlatformWindows;
171  break;
173  //pExtensionPlatform = ExtensionPlatformNT;
174  break;
175  default:
176  ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform);
177  //pExtensionPlatform = ExtensionPlatformNone;
178  break;
179  }
180  switch (PlatformInfo->ProcessorArchitecture)
181  {
183  pExtensionArchitecture = ExtensionArchitecturealpha;
184  break;
186  pExtensionArchitecture = ExtensionArchitectureamd64;
187  break;
189  pExtensionArchitecture = ExtensionArchitectureia64;
190  break;
192  pExtensionArchitecture = ExtensionArchitecturex86;
193  break;
195  pExtensionArchitecture = ExtensionArchitecturemips;
196  break;
198  pExtensionArchitecture = ExtensionArchitectureppc;
199  break;
200  default:
201  ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
203  pExtensionArchitecture = ExtensionArchitectureNone;
204  break;
205  }
206 
207  /*
208  * Field[0] Platform
209  * Field[1] Architecture
210  * Field[2] Major version
211  * Field[3] Minor version
212  * Field[4] Product type
213  * Field[5] Suite mask
214  * Remark: these fields may be NULL if the information is not provided
215  */
216  Fields[0] = Section;
217  if (Fields[0] == NULL)
218  {
219  TRACE("No extension found\n");
220  *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
221  ret = TRUE;
222  goto cleanup;
223  }
224  Fields[1] = Fields[0] + 1;
225  Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
226  for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
227  {
228  Fields[i] = wcschr(Fields[i - 1], '.');
229  if (Fields[i])
230  {
231  Fields[i]++;
232  *(Fields[i] - 1) = UNICODE_NULL;
233  }
234  }
235  /* Take care of first 2 fields */
236  if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
237  {
238  if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
239  {
240  TRACE("Mismatch on platform field\n");
241  goto cleanup;
242  }
243  Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
244  }
245  else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
246  {
247  if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
248  {
249  TRACE("Mismatch on platform field\n");
250  goto cleanup;
251  }
252  Fields[1] += wcslen(ExtensionPlatformNT) - 1;
253  }
254  else
255  {
256  /* No platform specified */
257  *ScorePlatform |= 0x02;
258  }
259  if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
260  {
261  /* No architecture specified */
262  *ScorePlatform |= 0x01;
263  }
264  else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
265  {
266  TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267  debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
268  goto cleanup;
269  }
270 
271  /* Check if informations are matching */
272  if (Fields[2] && *Fields[2])
273  {
275  MajorVersion = strtoulW(Fields[2], NULL, 0);
276  if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
277  (errno == ERANGE || errno == EINVAL))
278  {
279  TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
280  goto cleanup;
281  }
282  if (Fields[3] && *Fields[3])
283  {
284  MinorVersion = strtoulW(Fields[3], NULL, 0);
285  if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
286  (errno == ERANGE || errno == EINVAL))
287  {
288  TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
289  goto cleanup;
290  }
291  }
292  if (PlatformInfo->MajorVersion < MajorVersion ||
293  (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
294  {
295  TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296  MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
297  goto cleanup;
298  }
299  *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
300  if (MajorVersion == PlatformInfo->MajorVersion)
301  *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
302  else
303  *ScoreMinorVersion = MinorVersion;
304  }
305  else if (Fields[3] && *Fields[3])
306  {
307  TRACE("Minor version found without major version\n");
308  goto cleanup;
309  }
310  else
311  {
312  *ScoreMajorVersion = PlatformInfo->MajorVersion;
313  *ScoreMinorVersion = PlatformInfo->MinorVersion;
314  }
315 
316  if (Fields[4] && *Fields[4])
317  {
318  DWORD CurrentProductType;
319  CurrentProductType = strtoulW(Fields[4], NULL, 0);
320  if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
321  (errno == ERANGE || errno == EINVAL))
322  {
323  TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
324  goto cleanup;
325  }
326  if (CurrentProductType != ProductType)
327  {
328  TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329  CurrentProductType, ProductType);
330  goto cleanup;
331  }
332  }
333  else
334  *ScoreProductType = 1;
335 
336  if (Fields[5] && *Fields[5])
337  {
338  DWORD CurrentSuiteMask;
339  CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
340  if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
341  (errno == ERANGE || errno == EINVAL))
342  {
343  TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
344  goto cleanup;
345  }
346  if ((CurrentSuiteMask & ~SuiteMask) != 0)
347  {
348  TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349  CurrentSuiteMask, SuiteMask);
350  goto cleanup;
351  }
352  *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
353  }
354  else
355  *ScoreSuiteMask = SuiteMask;
356 
357  ret = TRUE;
358 
359 cleanup:
360  MyFree(Section);
361  return ret;
362 }
363 
364 static BOOL
366  IN LPCWSTR SectionName,
367  IN PVOID Context)
368 {
370  DWORD Score1, Score2, Score3, Score4, Score5;
371  BOOL ret;
372 
373  if (SectionName[info->PrefixLength] != '.')
374  return TRUE;
375 
377  &SectionName[info->PrefixLength],
378  info->PlatformInfo,
379  info->ProductType,
380  info->SuiteMask,
381  &Score1, &Score2, &Score3, &Score4, &Score5);
382  if (!ret)
383  {
384  TRACE("Section %s not compatible\n", debugstr_w(SectionName));
385  return TRUE;
386  }
387  if (Score1 > info->BestScore1) goto done;
388  if (Score1 < info->BestScore1) goto bettersection;
389  if (Score2 > info->BestScore2) goto done;
390  if (Score2 < info->BestScore2) goto bettersection;
391  if (Score3 > info->BestScore3) goto done;
392  if (Score3 < info->BestScore3) goto bettersection;
393  if (Score4 > info->BestScore4) goto done;
394  if (Score4 < info->BestScore4) goto bettersection;
395  if (Score5 > info->BestScore5) goto done;
396  if (Score5 < info->BestScore5) goto bettersection;
397  goto done;
398 
399 bettersection:
400  strcpyW(info->BestSection, SectionName);
401  info->BestScore1 = Score1;
402  info->BestScore2 = Score2;
403  info->BestScore3 = Score3;
404  info->BestScore4 = Score4;
405  info->BestScore5 = Score5;
406 
407 done:
408  return TRUE;
409 }
410 
411 /***********************************************************************
412  * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
413  */
414 BOOL WINAPI
416  IN HINF InfHandle,
417  IN PCWSTR InfSectionName,
418  IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
419  OUT PWSTR InfSectionWithExt OPTIONAL,
420  IN DWORD InfSectionWithExtSize,
423  IN PVOID Reserved)
424 {
425  BOOL ret = FALSE;
426 
427  TRACE("%s(%p %s %p %p %lu %p %p %p)\n", __FUNCTION__, InfHandle, debugstr_w(InfSectionName),
428  AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
430 
431  if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
433  else if (!InfSectionName)
435  else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
437  else if (Reserved != NULL)
439  else
440  {
441  static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
442  static BYTE CurrentProductType = 0;
443  static WORD CurrentSuiteMask = 0;
444  PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
445  struct GetSectionCallbackInfo CallbackInfo;
446  DWORD dwFullLength;
448  WORD SuiteMask;
449 
450  /* Fill platform info if needed */
451  if (AlternatePlatformInfo)
452  {
453  pPlatformInfo = AlternatePlatformInfo;
454  ProductType = 0;
455  SuiteMask = 0;
456  }
457  else
458  {
459  if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
460  {
461  /* That's the first time we go here. We need to fill in the structure */
462  SYSTEM_INFO SystemInfo;
463  GetSystemInfo(&SystemInfo);
464  CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
465  CurrentPlatform.Platform = OsVersionInfo.dwPlatformId;
466  CurrentPlatform.MajorVersion = OsVersionInfo.dwMajorVersion;
467  CurrentPlatform.MinorVersion = OsVersionInfo.dwMinorVersion;
468  CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
469  CurrentPlatform.Reserved = 0;
470  CurrentProductType = OsVersionInfo.wProductType;
471  CurrentSuiteMask = OsVersionInfo.wSuiteMask;
472  }
473  ProductType = CurrentProductType;
474  SuiteMask = CurrentSuiteMask;
475  }
476 
477  CallbackInfo.PlatformInfo = pPlatformInfo;
478  CallbackInfo.ProductType = ProductType;
479  CallbackInfo.SuiteMask = SuiteMask;
480  CallbackInfo.PrefixLength = strlenW(InfSectionName);
481  CallbackInfo.BestScore1 = ULONG_MAX;
482  CallbackInfo.BestScore2 = ULONG_MAX;
483  CallbackInfo.BestScore3 = ULONG_MAX;
484  CallbackInfo.BestScore4 = ULONG_MAX;
485  CallbackInfo.BestScore5 = ULONG_MAX;
486  strcpyW(CallbackInfo.BestSection, InfSectionName);
487  TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName);
489  InfHandle,
490  InfSectionName,
492  &CallbackInfo))
493  {
495  goto done;
496  }
497  TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo.BestSection);
498 
499  dwFullLength = lstrlenW(CallbackInfo.BestSection);
500  if (RequiredSize != NULL)
501  *RequiredSize = dwFullLength + 1;
502 
503  if (InfSectionWithExtSize > 0)
504  {
505  if (InfSectionWithExtSize < dwFullLength + 1)
506  {
508  goto done;
509  }
510  strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
511  if (Extension)
512  {
513  DWORD dwLength = lstrlenW(InfSectionName);
514  *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
515  }
516  }
517 
518  ret = TRUE;
519  }
520 
521 done:
522  TRACE("Returning %d\n", ret);
523  return ret;
524 }
525 
526 
527 BOOL
529  IN struct DeviceInfoSet *list,
530  IN LPCWSTR InstancePath,
531  IN LPCGUID pClassGuid,
532  OUT struct DeviceInfo **pDeviceInfo)
533 {
534  DWORD size;
535  CONFIGRET cr;
536  struct DeviceInfo *deviceInfo;
537 
538  *pDeviceInfo = NULL;
539 
540  size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
541  deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
542  if (!deviceInfo)
543  {
545  return FALSE;
546  }
547  ZeroMemory(deviceInfo, size);
548 
549  cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
550  if (cr != CR_SUCCESS)
551  {
553  return FALSE;
554  }
555 
556  deviceInfo->set = list;
557  deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
558  strcpyW(deviceInfo->Data, InstancePath);
559  deviceInfo->instanceId = deviceInfo->Data;
560  deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
561  deviceInfo->DeviceDescription = NULL;
562  memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
563  deviceInfo->CreationFlags = 0;
564  InitializeListHead(&deviceInfo->DriverListHead);
566 
567  *pDeviceInfo = deviceInfo;
568  return TRUE;
569 }
570 
571 
572 static BOOL
574 {
575  HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
576  HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
577  return TRUE;
578 }
579 
580 static BOOL
581 DestroyDeviceInfo(struct DeviceInfo *deviceInfo)
582 {
584  struct DriverInfoElement *driverInfo;
585  struct DeviceInterface *deviceInterface;
586 
587  while (!IsListEmpty(&deviceInfo->DriverListHead))
588  {
589  ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
591  if (!DestroyDriverInfoElement(driverInfo))
592  return FALSE;
593  }
594  while (!IsListEmpty(&deviceInfo->InterfaceListHead))
595  {
597  deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
598  if (!DestroyDeviceInterface(deviceInterface))
599  return FALSE;
600  }
602  if (deviceInfo->hmodDevicePropPageProvider)
604  return HeapFree(GetProcessHeap(), 0, deviceInfo);
605 }
606 
607 static BOOL
609 {
611  struct DeviceInfo *deviceInfo;
612 
613  while (!IsListEmpty(&list->ListHead))
614  {
615  ListEntry = RemoveHeadList(&list->ListHead);
616  deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry);
617  if (!DestroyDeviceInfo(deviceInfo))
618  return FALSE;
619  }
620  if (list->HKLM != HKEY_LOCAL_MACHINE)
621  RegCloseKey(list->HKLM);
622  CM_Disconnect_Machine(list->hMachine);
623  DestroyClassInstallParams(&list->ClassInstallParams);
624  if (list->hmodClassPropPageProvider)
625  FreeLibrary(list->hmodClassPropPageProvider);
626  return HeapFree(GetProcessHeap(), 0, list);
627 }
628 
629 /***********************************************************************
630  * SetupDiBuildClassInfoList (SETUPAPI.@)
631  *
632  * Returns a list of setup class GUIDs that identify the classes
633  * that are installed on a local machine.
634  *
635  * PARAMS
636  * Flags [I] control exclusion of classes from the list.
637  * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
638  * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
639  * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
640  *
641  * RETURNS
642  * Success: TRUE.
643  * Failure: FALSE.
644  */
646  DWORD Flags,
647  LPGUID ClassGuidList,
650 {
651  TRACE("\n");
652  return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
654  NULL, NULL);
655 }
656 
657 /***********************************************************************
658  * SetupDiBuildClassInfoListExA (SETUPAPI.@)
659  *
660  * Returns a list of setup class GUIDs that identify the classes
661  * that are installed on a local or remote machine.
662  *
663  * PARAMS
664  * Flags [I] control exclusion of classes from the list.
665  * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
666  * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
667  * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
668  * MachineName [I] name of a remote machine.
669  * Reserved [I] must be NULL.
670  *
671  * RETURNS
672  * Success: TRUE.
673  * Failure: FALSE.
674  */
676  DWORD Flags,
677  LPGUID ClassGuidList,
681  PVOID Reserved)
682 {
683  LPWSTR MachineNameW = NULL;
684  BOOL bResult;
685 
686  TRACE("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__, Flags, ClassGuidList,
688 
689  if (MachineName)
690  {
692  if (MachineNameW == NULL) return FALSE;
693  }
694 
695  bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
697  MachineNameW, Reserved);
698 
699  MyFree(MachineNameW);
700 
701  return bResult;
702 }
703 
704 /***********************************************************************
705  * SetupDiBuildClassInfoListExW (SETUPAPI.@)
706  *
707  * Returns a list of setup class GUIDs that identify the classes
708  * that are installed on a local or remote machine.
709  *
710  * PARAMS
711  * Flags [I] control exclusion of classes from the list.
712  * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
713  * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
714  * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
715  * MachineName [I] name of a remote machine.
716  * Reserved [I] must be NULL.
717  *
718  * RETURNS
719  * Success: TRUE.
720  * Failure: FALSE.
721  */
723  DWORD Flags,
724  LPGUID ClassGuidList,
728  PVOID Reserved)
729 {
730  GUID CurrentClassGuid;
731  HKEY hClassKey;
732  DWORD dwIndex;
733  DWORD dwGuidListIndex = 0;
734  HMACHINE hMachine = NULL;
735  CONFIGRET cr;
736 
737  TRACE("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__, Flags, ClassGuidList,
739 
740  if (!RequiredSize)
741  {
743  return FALSE;
744  }
745  else if (!ClassGuidList && ClassGuidListSize > 0)
746  {
748  return FALSE;
749  }
750 
751  if (MachineName)
752  {
753  cr = CM_Connect_MachineW(MachineName, &hMachine);
754  if (cr != CR_SUCCESS)
755  {
757  return FALSE;
758  }
759  }
760 
761  for (dwIndex = 0; ; dwIndex++)
762  {
763  cr = CM_Enumerate_Classes_Ex(dwIndex,
764  &CurrentClassGuid,
765  0,
766  hMachine);
767  if (cr == CR_SUCCESS)
768  {
769  TRACE("Guid: %s\n", debugstr_guid(&CurrentClassGuid));
770  if (CM_Open_Class_Key_ExW(&CurrentClassGuid,
771  NULL,
774  &hClassKey,
776  hMachine) != CR_SUCCESS)
777  {
779  if (hMachine)
780  CM_Disconnect_Machine(hMachine);
781  return FALSE;
782  }
783 
786  NULL,
787  NULL,
788  NULL,
789  NULL))
790  {
791  TRACE("'NoUseClass' value found!\n");
793  continue;
794  }
795 
796  if ((Flags & DIBCI_NOINSTALLCLASS) &&
799  NULL,
800  NULL,
801  NULL,
802  NULL)))
803  {
804  TRACE("'NoInstallClass' value found!\n");
806  continue;
807  }
808 
809  if ((Flags & DIBCI_NODISPLAYCLASS) &&
812  NULL,
813  NULL,
814  NULL,
815  NULL)))
816  {
817  TRACE("'NoDisplayClass' value found!\n");
819  continue;
820  }
821 
823 
824  if (dwGuidListIndex < ClassGuidListSize)
825  {
826  ClassGuidList[dwGuidListIndex] = CurrentClassGuid;
827  }
828 
829  dwGuidListIndex++;
830  }
831 
832  if (cr != ERROR_SUCCESS)
833  break;
834  }
835 
836  if (hMachine)
837  CM_Disconnect_Machine(hMachine);
838 
839  if (RequiredSize != NULL)
840  *RequiredSize = dwGuidListIndex;
841 
842  if (ClassGuidListSize < dwGuidListIndex)
843  {
845  return FALSE;
846  }
847 
848  return TRUE;
849 }
850 
851 /***********************************************************************
852  * SetupDiClassGuidsFromNameA (SETUPAPI.@)
853  */
855  LPCSTR ClassName,
856  LPGUID ClassGuidList,
859 {
860  return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
862  NULL, NULL);
863 }
864 
865 /***********************************************************************
866  * SetupDiClassGuidsFromNameW (SETUPAPI.@)
867  */
869  LPCWSTR ClassName,
870  LPGUID ClassGuidList,
873 {
874  return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
876  NULL, NULL);
877 }
878 
879 /***********************************************************************
880  * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
881  */
883  LPCSTR ClassName,
884  LPGUID ClassGuidList,
888  PVOID Reserved)
889 {
890  LPWSTR ClassNameW = NULL;
891  LPWSTR MachineNameW = NULL;
892  BOOL bResult;
893 
894  TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__, debugstr_a(ClassName), ClassGuidList,
896 
897  if (!ClassName)
898  {
900  return FALSE;
901  }
902 
903  ClassNameW = pSetupMultiByteToUnicode(ClassName, CP_ACP);
904  if (ClassNameW == NULL)
905  return FALSE;
906 
907  if (MachineName)
908  {
910  if (MachineNameW == NULL)
911  {
912  MyFree(ClassNameW);
913  return FALSE;
914  }
915  }
916 
917  bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
919  MachineNameW, Reserved);
920 
921  MyFree(MachineNameW);
922  MyFree(ClassNameW);
923 
924  return bResult;
925 }
926 
927 /***********************************************************************
928  * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
929  */
931  LPCWSTR ClassName,
932  LPGUID ClassGuidList,
936  PVOID Reserved)
937 {
938  WCHAR szKeyName[40];
940  HKEY hClassesKey;
941  HKEY hClassKey;
942  DWORD dwLength;
943  DWORD dwIndex;
944  LONG lError;
945  DWORD dwGuidListIndex = 0;
946 
947  TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__, debugstr_w(ClassName), ClassGuidList,
949 
950  if (!ClassName || !RequiredSize)
951  {
953  return FALSE;
954  }
955  if (!ClassGuidList && ClassGuidListSize > 0)
956  {
958  return FALSE;
959  }
960  *RequiredSize = 0;
961 
962  hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
965  MachineName,
966  Reserved);
967  if (hClassesKey == INVALID_HANDLE_VALUE)
968  {
969  return FALSE;
970  }
971 
972  for (dwIndex = 0; ; dwIndex++)
973  {
974  dwLength = 40;
975  lError = RegEnumKeyExW(hClassesKey,
976  dwIndex,
977  szKeyName,
978  &dwLength,
979  NULL,
980  NULL,
981  NULL,
982  NULL);
983  TRACE("RegEnumKeyExW() returns %d\n", lError);
984  if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
985  {
986  TRACE("Key name: %p\n", szKeyName);
987 
988  if (RegOpenKeyExW(hClassesKey,
989  szKeyName,
990  0,
992  &hClassKey))
993  {
994  RegCloseKey(hClassesKey);
995  return FALSE;
996  }
997 
998  dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR);
1001  NULL,
1002  NULL,
1004  &dwLength))
1005  {
1006  TRACE("Class name: %p\n", szClassName);
1007 
1008  if (strcmpiW(szClassName, ClassName) == 0)
1009  {
1010  TRACE("Found matching class name\n");
1011 
1012  TRACE("Guid: %p\n", szKeyName);
1013  if (dwGuidListIndex < ClassGuidListSize)
1014  {
1015  if (szKeyName[0] == '{' && szKeyName[37] == '}')
1016  {
1017  szKeyName[37] = 0;
1018  }
1019  TRACE("Guid: %p\n", &szKeyName[1]);
1020 
1021  UuidFromStringW(&szKeyName[1],
1022  &ClassGuidList[dwGuidListIndex]);
1023  }
1024 
1025  dwGuidListIndex++;
1026  }
1027  }
1028 
1030  }
1031 
1032  if (lError != ERROR_SUCCESS)
1033  break;
1034  }
1035 
1036  RegCloseKey(hClassesKey);
1037 
1038  if (RequiredSize != NULL)
1039  *RequiredSize = dwGuidListIndex;
1040 
1041  if (ClassGuidListSize < dwGuidListIndex)
1042  {
1044  return FALSE;
1045  }
1046 
1047  return TRUE;
1048 }
1049 
1050 /***********************************************************************
1051  * SetupDiClassNameFromGuidA (SETUPAPI.@)
1052  */
1054  const GUID* ClassGuid,
1055  PSTR ClassName,
1056  DWORD ClassNameSize,
1058 {
1059  return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
1060  ClassNameSize, RequiredSize,
1061  NULL, NULL);
1062 }
1063 
1064 /***********************************************************************
1065  * SetupDiClassNameFromGuidW (SETUPAPI.@)
1066  */
1068  const GUID* ClassGuid,
1069  PWSTR ClassName,
1070  DWORD ClassNameSize,
1072 {
1073  return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1074  ClassNameSize, RequiredSize,
1075  NULL, NULL);
1076 }
1077 
1078 /***********************************************************************
1079  * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1080  */
1082  const GUID* ClassGuid,
1083  PSTR ClassName,
1084  DWORD ClassNameSize,
1087  PVOID Reserved)
1088 {
1089  WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1090  LPWSTR MachineNameW = NULL;
1091  BOOL ret;
1092 
1093  if (MachineName)
1094  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1096  RequiredSize, MachineNameW, Reserved);
1097  if (ret)
1098  {
1099  int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1100  ClassNameSize, NULL, NULL);
1101  if (len == 0 || len > ClassNameSize)
1102  {
1104  ret = FALSE;
1105  }
1106  }
1107  MyFree(MachineNameW);
1108  return ret;
1109 }
1110 
1111 /***********************************************************************
1112  * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1113  */
1115  const GUID* ClassGuid,
1116  PWSTR ClassName,
1117  DWORD ClassNameSize,
1120  PVOID Reserved)
1121 {
1122  HKEY hKey;
1123  DWORD dwLength;
1124  DWORD dwRegType;
1125  LONG rc;
1126  PWSTR Buffer;
1127 
1128  TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), ClassName,
1129  ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
1130 
1131  /* Make sure there's a GUID */
1132  if (ClassGuid == NULL)
1133  {
1134  SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */
1135  return FALSE;
1136  }
1137 
1138  /* Make sure there's a real buffer when there's a size */
1139  if ((ClassNameSize > 0) && (ClassName == NULL))
1140  {
1141  SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */
1142  return FALSE;
1143  }
1144 
1145  /* Open the key for the GUID */
1147 
1148  if (hKey == INVALID_HANDLE_VALUE)
1149  return FALSE;
1150 
1151  /* Retrieve the class name data and close the key */
1152  rc = QueryRegistryValue(hKey, REGSTR_VAL_CLASS, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
1153  RegCloseKey(hKey);
1154 
1155  /* Make sure we got the data */
1156  if (rc != ERROR_SUCCESS)
1157  {
1158  SetLastError(rc);
1159  return FALSE;
1160  }
1161 
1162  /* Make sure the data is a string */
1163  if (dwRegType != REG_SZ)
1164  {
1165  MyFree(Buffer);
1167  return FALSE;
1168  }
1169 
1170  /* Determine the length of the class name */
1171  dwLength /= sizeof(WCHAR);
1172 
1173  if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
1174  /* Count the null-terminator */
1175  dwLength++;
1176 
1177  /* Inform the caller about the class name */
1178  if ((ClassName != NULL) && (dwLength <= ClassNameSize))
1179  {
1180  memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR));
1181  ClassName[dwLength - 1] = UNICODE_NULL;
1182  }
1183 
1184  /* Inform the caller about the required size */
1185  if (RequiredSize != NULL)
1187 
1188  /* Clean up the buffer */
1189  MyFree(Buffer);
1190 
1191  /* Make sure the buffer was large enough */
1192  if ((ClassName == NULL) || (dwLength > ClassNameSize))
1193  {
1195  return FALSE;
1196  }
1197 
1198  return TRUE;
1199 }
1200 
1201 /***********************************************************************
1202  * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1203  */
1206  HWND hwndParent)
1207 {
1209 }
1210 
1211 /***********************************************************************
1212  * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1213  */
1216  HWND hwndParent,
1218  PVOID Reserved)
1219 {
1220  LPWSTR MachineNameW = NULL;
1221  HDEVINFO hDevInfo;
1222 
1223  TRACE("%s(%s %p %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), hwndParent,
1225 
1226  if (MachineName)
1227  {
1228  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1229  if (MachineNameW == NULL)
1230  return INVALID_HANDLE_VALUE;
1231  }
1232 
1234  MachineNameW, Reserved);
1235 
1236  MyFree(MachineNameW);
1237 
1238  return hDevInfo;
1239 }
1240 
1241 /***********************************************************************
1242  * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1243  *
1244  * Create an empty DeviceInfoSet list.
1245  *
1246  * PARAMS
1247  * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1248  * with this list.
1249  * hwndParent [I] hwnd needed for interface related actions.
1250  * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1251  * local registry will be used.
1252  * Reserved [I] must be NULL
1253  *
1254  * RETURNS
1255  * Success: empty list.
1256  * Failure: INVALID_HANDLE_VALUE.
1257  */
1260  HWND hwndParent,
1262  PVOID Reserved)
1263 {
1264  struct DeviceInfoSet *list = NULL;
1266  DWORD rc;
1267  CONFIGRET cr;
1269 
1270  TRACE("%s(%s %p %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), hwndParent,
1272 
1273  if (MachineName != NULL)
1274  {
1276  if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
1277  {
1279  goto cleanup;
1280  }
1281  if(len > 0)
1282  size += (len + 3) * sizeof(WCHAR);
1283  else
1284  MachineName = NULL;
1285  }
1286 
1287  if (Reserved != NULL)
1288  {
1290  return INVALID_HANDLE_VALUE;
1291  }
1292 
1293  list = MyMalloc(size);
1294  if (!list)
1295  {
1297  return INVALID_HANDLE_VALUE;
1298  }
1300 
1302  memcpy(&list->ClassGuid,
1304  sizeof(list->ClassGuid));
1305  list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1306  list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
1307  list->InstallParams.hwndParent = hwndParent;
1308  if (MachineName)
1309  {
1311  if (rc != ERROR_SUCCESS)
1312  {
1314  goto cleanup;
1315  }
1316 
1317  list->szData[0] = list->szData[1] = '\\';
1318  strcpyW(list->szData + 2, MachineName);
1319  list->MachineName = list->szData;
1320  }
1321  else
1322  {
1323  list->HKLM = HKEY_LOCAL_MACHINE;
1324  list->MachineName = NULL;
1325  }
1326  cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
1327  if (cr != CR_SUCCESS)
1328  {
1330  goto cleanup;
1331  }
1332  InitializeListHead(&list->DriverListHead);
1333  InitializeListHead(&list->ListHead);
1334 
1335  return (HDEVINFO)list;
1336 
1337 cleanup:
1338  if (ret == INVALID_HANDLE_VALUE)
1339  {
1340  if (list)
1341  {
1342  if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
1343  RegCloseKey(list->HKLM);
1344  MyFree(list);
1345  }
1346  }
1347  return ret;
1348 }
1349 
1350 /***********************************************************************
1351  * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1352  */
1356  DWORD Scope,
1357  DWORD HwProfile,
1358  DWORD KeyType,
1359  HINF InfHandle,
1360  PCSTR InfSectionName)
1361 {
1362  PWSTR InfSectionNameW = NULL;
1363  HKEY key;
1364 
1365  TRACE("%s(%p %p %d %d %d %p %s)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Scope,
1366  HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1367 
1368  if (InfHandle)
1369  {
1370  if (!InfSectionName)
1371  {
1373  return INVALID_HANDLE_VALUE;
1374  }
1375  else
1376  {
1377  InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
1378  if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1379  }
1380  }
1382  HwProfile, KeyType, InfHandle, InfSectionNameW);
1383  MyFree(InfSectionNameW);
1384  return key;
1385 }
1386 
1387 static HKEY
1389  IN HKEY HKLM,
1390  IN DWORD HwProfile,
1391  IN DWORD samDesired);
1392 
1393 /***********************************************************************
1394  * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1395  */
1399  DWORD Scope,
1400  DWORD HwProfile,
1401  DWORD KeyType,
1402  HINF InfHandle,
1403  PCWSTR InfSectionName)
1404 {
1405  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1406  struct DeviceInfo *deviceInfo;
1408  DWORD rc;
1409  HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
1410  HKEY hKey = NULL;
1411  HKEY RootKey;
1412 
1413  TRACE("%s(%p %p %lu %lu %lu %p %s)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Scope,
1414  HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1415 
1417  {
1419  return INVALID_HANDLE_VALUE;
1420  }
1421  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1422  {
1424  return INVALID_HANDLE_VALUE;
1425  }
1427  || !DeviceInfoData->Reserved)
1428  {
1430  return INVALID_HANDLE_VALUE;
1431  }
1432  if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1433  {
1435  return INVALID_HANDLE_VALUE;
1436  }
1437  if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1438  {
1440  return INVALID_HANDLE_VALUE;
1441  }
1442  if (InfHandle && !InfSectionName)
1443  {
1445  return INVALID_HANDLE_VALUE;
1446  }
1447  if (!InfHandle && InfSectionName)
1448  {
1450  return INVALID_HANDLE_VALUE;
1451  }
1452 
1453  deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1454 
1455  if (Scope == DICS_FLAG_GLOBAL)
1456  RootKey = set->HKLM;
1457  else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1458  {
1459  hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
1460  if (hHWProfileKey == INVALID_HANDLE_VALUE)
1461  goto cleanup;
1462  RootKey = hHWProfileKey;
1463  }
1464 
1465  if (KeyType == DIREG_DEV)
1466  {
1467 #if _WIN32_WINNT >= 0x502
1469 #else
1471 #endif
1472  if (hKey == INVALID_HANDLE_VALUE)
1473  goto cleanup;
1474 
1475  if (Scope == DICS_FLAG_GLOBAL)
1476  {
1477  HKEY hTempKey = hKey;
1478 
1479  rc = RegCreateKeyExW(hTempKey,
1480  L"Device Parameters",
1481  0,
1482  NULL,
1484 #if _WIN32_WINNT >= 0x502
1485  KEY_READ | KEY_WRITE,
1486 #else
1488 #endif
1489  NULL,
1490  &hKey,
1491  NULL);
1492  if (rc == ERROR_SUCCESS)
1493  RegCloseKey(hTempKey);
1494  }
1495  }
1496  else /* KeyType == DIREG_DRV */
1497  {
1498 #if _WIN32_WINNT >= 0x502
1500 #else
1502 #endif
1503  if (hKey == INVALID_HANDLE_VALUE)
1504  goto cleanup;
1505  }
1506 
1507  /* Do installation of the specified section */
1508  if (InfHandle)
1509  {
1510  FIXME("Need to install section %s in file %p\n",
1511  debugstr_w(InfSectionName), InfHandle);
1512  }
1513  key = hKey;
1514 
1515 cleanup:
1516  if (hHWProfileKey != INVALID_HANDLE_VALUE)
1517  RegCloseKey(hHWProfileKey);
1518  if (hKey != NULL && hKey != key)
1519  RegCloseKey(hKey);
1520 
1521  TRACE("Returning 0x%p\n", key);
1522  return key;
1523 }
1524 
1525 /***********************************************************************
1526  * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1527  */
1530  PCSTR DeviceName,
1531  CONST GUID *ClassGuid,
1533  HWND hwndParent,
1536 {
1537  BOOL ret;
1538  LPWSTR DeviceNameW = NULL;
1539  LPWSTR DeviceDescriptionW = NULL;
1540 
1541  TRACE("\n");
1542 
1543  if (DeviceName)
1544  {
1545  DeviceNameW = pSetupMultiByteToUnicode(DeviceName, CP_ACP);
1546  if (DeviceNameW == NULL) return FALSE;
1547  }
1548  if (DeviceDescription)
1549  {
1550  DeviceDescriptionW = pSetupMultiByteToUnicode(DeviceDescription, CP_ACP);
1551  if (DeviceDescriptionW == NULL)
1552  {
1553  MyFree(DeviceNameW);
1554  return FALSE;
1555  }
1556  }
1557 
1558  ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1560 
1561  MyFree(DeviceNameW);
1562  MyFree(DeviceDescriptionW);
1563 
1564  return ret;
1565 }
1566 
1567 /***********************************************************************
1568  * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1569  */
1573  CONST GUID *ClassGuid,
1575  HWND hwndParent,
1578 {
1579  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1580  struct DeviceInfo *deviceInfo = NULL;
1581  BOOL ret = FALSE;
1582  CONFIGRET cr;
1583  DEVINST RootDevInst;
1584  DEVINST DevInst;
1585  WCHAR GenInstanceId[MAX_DEVICE_ID_LEN];
1586 
1587  TRACE("%s(%p %s %s %s %p %x %p)\n", __FUNCTION__, DeviceInfoSet, debugstr_w(DeviceName),
1590 
1591  if (!DeviceName)
1592  {
1594  return FALSE;
1595  }
1597  {
1599  return FALSE;
1600  }
1601  if (!ClassGuid)
1602  {
1604  return FALSE;
1605  }
1606  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1607  {
1609  return FALSE;
1610  }
1611  if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1612  !IsEqualGUID(ClassGuid, &set->ClassGuid))
1613  {
1615  return FALSE;
1616  }
1618  {
1619  TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
1621  return FALSE;
1622  }
1623 
1624  /* Get the root device instance */
1625  cr = CM_Locate_DevInst_ExW(&RootDevInst,
1626  NULL,
1628  set->hMachine);
1629  if (cr != CR_SUCCESS)
1630  {
1632  return FALSE;
1633  }
1634 
1635  /* Create the new device instance */
1636  cr = CM_Create_DevInst_ExW(&DevInst,
1638  RootDevInst,
1641  set->hMachine);
1642  if (cr != CR_SUCCESS)
1643  {
1645  return FALSE;
1646  }
1647 
1649  {
1650  /* Grab the actual instance ID that was created */
1651  cr = CM_Get_Device_ID_Ex(DevInst,
1652  GenInstanceId,
1654  0,
1655  set->hMachine);
1656  if (cr != CR_SUCCESS)
1657  {
1659  return FALSE;
1660  }
1661 
1662  DeviceName = GenInstanceId;
1663  TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName));
1664  }
1665 
1666  if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
1667  {
1668  InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
1669 
1670  if (!DeviceInfoData)
1671  ret = TRUE;
1672  else
1673  {
1674  if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1675  {
1677  }
1678  else
1679  {
1681  DeviceInfoData->DevInst = deviceInfo->dnDevInst;
1682  DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
1683  ret = TRUE;
1684  }
1685  }
1686  }
1687 
1688  if (ret == FALSE)
1689  {
1690  if (deviceInfo != NULL)
1691  {
1692  /* Remove deviceInfo from List */
1693  RemoveEntryList(&deviceInfo->ListEntry);
1694 
1695  /* Destroy deviceInfo */
1696  DestroyDeviceInfo(deviceInfo);
1697  }
1698  }
1699 
1700  TRACE("Returning %d\n", ret);
1701  return ret;
1702 }
1703 
1704 /***********************************************************************
1705  * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1706  */
1710  DWORD Flags,
1711  PSP_DETSIG_CMPPROC CompareProc,
1712  PVOID CompareContext,
1713  PSP_DEVINFO_DATA DupDeviceInfoData)
1714 {
1715  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1716  WCHAR DevInstId[MAX_DEVICE_ID_LEN];
1717  DEVINST ParentDevInst;
1718  CONFIGRET cr;
1719  DWORD dwError = ERROR_SUCCESS;
1720 
1721  TRACE("%s(%p %p %08x %p %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Flags,
1722  CompareProc, CompareContext, DupDeviceInfoData);
1723 
1725  {
1727  return FALSE;
1728  }
1729  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1730  {
1732  return FALSE;
1733  }
1735  || !DeviceInfoData->Reserved)
1736  {
1738  return FALSE;
1739  }
1740 
1741  if (Flags & ~SPRDI_FIND_DUPS)
1742  {
1743  TRACE("Unknown flags: 0x%08lx\n", Flags & ~SPRDI_FIND_DUPS);
1745  return FALSE;
1746  }
1747 
1748  if (Flags & SPRDI_FIND_DUPS)
1749  {
1750  FIXME("Unimplemented codepath!\n");
1751  }
1752 
1754  DevInstId,
1756  0,
1757  set->hMachine);
1758 
1759  CM_Get_Parent_Ex(&ParentDevInst,
1761  0,
1762  set->hMachine);
1763 
1765  DevInstId,
1766  ParentDevInst,
1768  set->hMachine);
1769  if (cr != CR_SUCCESS &&
1771  {
1772  dwError = ERROR_NO_SUCH_DEVINST;
1773  }
1774 
1775  SetLastError(dwError);
1776 
1777  return (dwError == ERROR_SUCCESS);
1778 }
1779 
1780 /***********************************************************************
1781  * SetupDiEnumDeviceInfo (SETUPAPI.@)
1782  */
1784  HDEVINFO devinfo,
1785  DWORD index,
1787 {
1788  BOOL ret = FALSE;
1789 
1790  TRACE("%s(%p %d %p)\n", __FUNCTION__, devinfo, index, info);
1791 
1792  if(info==NULL)
1793  {
1795  return FALSE;
1796  }
1797  if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1798  {
1799  struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1800  if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1801  {
1802  if (info->cbSize != sizeof(SP_DEVINFO_DATA))
1804  else
1805  {
1806  PLIST_ENTRY ItemList = list->ListHead.Flink;
1807  while (ItemList != &list->ListHead && index-- > 0)
1808  ItemList = ItemList->Flink;
1809  if (ItemList == &list->ListHead)
1811  else
1812  {
1813  struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
1814  memcpy(&info->ClassGuid,
1815  &DevInfo->ClassGuid,
1816  sizeof(GUID));
1817  info->DevInst = DevInfo->dnDevInst;
1818  info->Reserved = (ULONG_PTR)DevInfo;
1819  ret = TRUE;
1820  }
1821  }
1822  }
1823  else
1825  }
1826  else
1828  return ret;
1829 }
1830 
1831 /***********************************************************************
1832  * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1833  */
1837  PSTR DeviceInstanceId,
1838  DWORD DeviceInstanceIdSize,
1840 {
1841  BOOL ret = FALSE;
1842  DWORD size;
1843  PWSTR instanceId;
1844 
1845  TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1846  DeviceInstanceIdSize, RequiredSize);
1847 
1848  if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1849  {
1851  return FALSE;
1852  }
1853 
1856  NULL,
1857  0,
1858  &size);
1860  return FALSE;
1861  instanceId = MyMalloc(size * sizeof(WCHAR));
1862  if (instanceId)
1863  {
1866  instanceId,
1867  size,
1868  &size);
1869  if (ret)
1870  {
1871  int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1872  DeviceInstanceId,
1873  DeviceInstanceIdSize, NULL, NULL);
1874 
1875  if (!len)
1876  ret = FALSE;
1877  else
1878  {
1879  if (len > DeviceInstanceIdSize)
1880  {
1882  ret = FALSE;
1883  }
1884  if (RequiredSize)
1885  *RequiredSize = len;
1886  }
1887  }
1888  MyFree(instanceId);
1889  }
1890  else
1891  {
1892  if (RequiredSize)
1893  *RequiredSize = size;
1895  ret = FALSE;
1896  }
1897  return ret;
1898 }
1899 
1900 /***********************************************************************
1901  * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1902  */
1906  PWSTR DeviceInstanceId,
1907  DWORD DeviceInstanceIdSize,
1909 {
1910  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1911  struct DeviceInfo *devInfo;
1912 
1913  TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1914  DeviceInstanceIdSize, RequiredSize);
1915 
1917  {
1919  return FALSE;
1920  }
1921  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1922  {
1924  return FALSE;
1925  }
1927  || !DeviceInfoData->Reserved)
1928  {
1930  return FALSE;
1931  }
1932  devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1933  if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1934  {
1936  return FALSE;
1937  }
1938  if (DeviceInstanceId && DeviceInstanceIdSize == 0)
1939  {
1941  return FALSE;
1942  }
1943  TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1944  if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1945  {
1947  if (RequiredSize)
1948  *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1949  return FALSE;
1950  }
1951  lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1952  if (RequiredSize)
1953  *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1954  return TRUE;
1955 }
1956 
1957 /***********************************************************************
1958  * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1959  */
1961  HINF InfHandle,
1962  PCSTR InfSectionName,
1963  PSTR InfSectionWithExt,
1964  DWORD InfSectionWithExtSize,
1966  PSTR *Extension)
1967 {
1968  return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
1969  NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1970  Extension, NULL);
1971 }
1972 
1973 /***********************************************************************
1974  * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1975  */
1977  HINF InfHandle,
1978  PCWSTR InfSectionName,
1979  PWSTR InfSectionWithExt,
1980  DWORD InfSectionWithExtSize,
1982  PWSTR *Extension)
1983 {
1984  return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
1985  NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1986  Extension, NULL);
1987 }
1988 
1989 /***********************************************************************
1990  * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
1991  */
1992 BOOL WINAPI
1994  IN HINF InfHandle,
1995  IN PCSTR InfSectionName,
1996  IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
1997  OUT PSTR InfSectionWithExt OPTIONAL,
1998  IN DWORD InfSectionWithExtSize,
2001  IN PVOID Reserved)
2002 {
2003  LPWSTR InfSectionNameW = NULL;
2004  LPWSTR InfSectionWithExtW = NULL;
2005  PWSTR ExtensionW;
2006  BOOL bResult = FALSE;
2007 
2008  TRACE("%s()\n", __FUNCTION__);
2009 
2010  if (InfSectionName)
2011  {
2012  InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2013  if (InfSectionNameW == NULL)
2014  goto cleanup;
2015  }
2016  if (InfSectionWithExt)
2017  {
2018  InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
2019  if (InfSectionWithExtW == NULL)
2020  goto cleanup;
2021  }
2022 
2024  InfHandle, InfSectionNameW, AlternatePlatformInfo,
2025  InfSectionWithExt ? InfSectionWithExtW : NULL,
2026  InfSectionWithExtSize,
2027  RequiredSize,
2028  Extension ? &ExtensionW : NULL,
2029  Reserved);
2030 
2031  if (bResult && InfSectionWithExt)
2032  {
2033  bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
2034  InfSectionWithExtSize, NULL, NULL) != 0;
2035  }
2036  if (bResult && Extension)
2037  {
2038  if (ExtensionW == NULL)
2039  *Extension = NULL;
2040  else
2041  *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
2042  }
2043 
2044 cleanup:
2045  MyFree(InfSectionNameW);
2046  MyFree(InfSectionWithExtW);
2047 
2048  return bResult;
2049 }
2050 
2051 /***********************************************************************
2052  * SetupDiGetClassDescriptionA (SETUPAPI.@)
2053  */
2055  const GUID* ClassGuid,
2056  PSTR ClassDescription,
2057  DWORD ClassDescriptionSize,
2059 {
2060  return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
2061  ClassDescriptionSize,
2062  RequiredSize, NULL, NULL);
2063 }
2064 
2065 /***********************************************************************
2066  * SetupDiGetClassDescriptionW (SETUPAPI.@)
2067  */
2069  const GUID* ClassGuid,
2070  PWSTR ClassDescription,
2071  DWORD ClassDescriptionSize,
2073 {
2074  return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
2075  ClassDescriptionSize,
2076  RequiredSize, NULL, NULL);
2077 }
2078 
2079 /***********************************************************************
2080  * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2081  */
2083  const GUID* ClassGuid,
2084  PSTR ClassDescription,
2085  DWORD ClassDescriptionSize,
2088  PVOID Reserved)
2089 {
2090  PWCHAR ClassDescriptionW = NULL;
2091  LPWSTR MachineNameW = NULL;
2092  BOOL ret = FALSE;
2093 
2094  TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), ClassDescription,
2095  ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
2096 
2097  if (ClassDescriptionSize > 0)
2098  {
2099  ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
2100  if (!ClassDescriptionW)
2101  {
2103  goto cleanup;
2104  }
2105  }
2106 
2107  if (MachineName)
2108  {
2109  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
2110  if (!MachineNameW)
2111  {
2113  goto cleanup;
2114  }
2115  }
2116 
2117  ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
2118  ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
2119  if (ret)
2120  {
2121  DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
2122  ClassDescriptionSize, NULL, NULL);
2123  if (len == 0 || len > ClassDescriptionSize)
2124  {
2126  ret = FALSE;
2127  }
2128  }
2129 
2130 cleanup:
2131  MyFree(ClassDescriptionW);
2132  MyFree(MachineNameW);
2133  return ret;
2134 }
2135 
2136 /***********************************************************************
2137  * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2138  */
2140  const GUID* ClassGuid,
2141  PWSTR ClassDescription,
2142  DWORD ClassDescriptionSize,
2145  PVOID Reserved)
2146 {
2147  HKEY hKey;
2148  DWORD dwLength;
2149  DWORD dwRegType;
2150  LONG rc;
2151  PWSTR Buffer;
2152 
2153  TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), ClassDescription,
2154  ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
2155 
2156  /* Make sure there's a GUID */
2157  if (!ClassGuid)
2158  {
2160  return FALSE;
2161  }
2162 
2163  /* Make sure there's a real buffer when there's a size */
2164  if (!ClassDescription && ClassDescriptionSize > 0)
2165  {
2167  return FALSE;
2168  }
2169 
2170  /* Open the key for the GUID */
2174  MachineName,
2175  Reserved);
2176  if (hKey == INVALID_HANDLE_VALUE)
2177  return FALSE;
2178 
2179  /* Retrieve the class description data and close the key */
2180  rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
2181  RegCloseKey(hKey);
2182 
2183  /* Make sure we got the data */
2184  if (rc != ERROR_SUCCESS)
2185  {
2186  SetLastError(rc);
2187  return FALSE;
2188  }
2189 
2190  /* Make sure the data is a string */
2191  if (dwRegType != REG_SZ)
2192  {
2193  MyFree(Buffer);
2195  return FALSE;
2196  }
2197 
2198  /* Determine the length of the class description */
2199  dwLength /= sizeof(WCHAR);
2200 
2201  /* Count the null-terminator if none is present */
2202  if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
2203  dwLength++;
2204 
2205  /* Inform the caller about the class description */
2206  if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize))
2207  {
2208  memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR));
2209  ClassDescription[dwLength - 1] = UNICODE_NULL;
2210  }
2211 
2212  /* Inform the caller about the required size */
2213  if (RequiredSize != NULL)
2215 
2216  /* Clean up the buffer */
2217  MyFree(Buffer);
2218 
2219  /* Make sure the buffer was large enough */
2220  if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize))
2221  {
2223  return FALSE;
2224  }
2225 
2226  return TRUE;
2227 }
2228 
2229 /***********************************************************************
2230  * SetupDiGetClassDevsA (SETUPAPI.@)
2231  */
2233  CONST GUID *class,
2234  LPCSTR enumstr,
2235  HWND parent,
2236  DWORD flags)
2237 {
2238  return SetupDiGetClassDevsExA(class, enumstr, parent,
2239  flags, NULL, NULL, NULL);
2240 }
2241 
2242 /***********************************************************************
2243  * SetupDiGetClassDevsExA (SETUPAPI.@)
2244  */
2246  const GUID *class,
2247  PCSTR enumstr,
2248  HWND parent,
2249  DWORD flags,
2250  HDEVINFO deviceset,
2251  PCSTR machine,
2252  PVOID reserved)
2253 {
2254  HDEVINFO ret;
2255  LPWSTR enumstrW = NULL, machineW = NULL;
2256 
2257  if (enumstr)
2258  {
2259  enumstrW = pSetupMultiByteToUnicode(enumstr, CP_ACP);
2260  if (!enumstrW)
2261  {
2263  goto end;
2264  }
2265  }
2266  if (machine)
2267  {
2269  if (!machineW)
2270  {
2271  MyFree(enumstrW);
2273  goto end;
2274  }
2275  }
2276  ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
2277  machineW, reserved);
2278  MyFree(enumstrW);
2279  MyFree(machineW);
2280 
2281 end:
2282  return ret;
2283 }
2284 
2285 /***********************************************************************
2286  * SetupDiGetClassDevsW (SETUPAPI.@)
2287  */
2289  CONST GUID *class,
2290  LPCWSTR enumstr,
2291  HWND parent,
2292  DWORD flags)
2293 {
2294  return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2295  NULL);
2296 }
2297 
2298 /***********************************************************************
2299  * SetupDiGetClassDevsExW (SETUPAPI.@)
2300  */
2302  CONST GUID *class,
2303  PCWSTR enumstr,
2304  HWND parent,
2305  DWORD flags,
2306  HDEVINFO deviceset,
2307  PCWSTR machine,
2308  PVOID reserved)
2309 {
2310  HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2311  struct DeviceInfoSet *list;
2312  CONST GUID *pClassGuid;
2313  LONG rc;
2315 
2316  TRACE("%s(%s %s %p 0x%08x %p %s %p)\n", __FUNCTION__, debugstr_guid(class),
2317  debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2318  reserved);
2319 
2320  if (!(flags & DIGCF_ALLCLASSES) && !class)
2321  {
2323  return INVALID_HANDLE_VALUE;
2324  }
2325 
2326  /* Create the deviceset if not set */
2327  if (deviceset)
2328  {
2329  list = (struct DeviceInfoSet *)deviceset;
2330  if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2331  {
2333  goto cleanup;
2334  }
2335  hDeviceInfo = deviceset;
2336  }
2337  else
2338  {
2339  hDeviceInfo = SetupDiCreateDeviceInfoListExW(
2341  NULL, machine, NULL);
2342  if (hDeviceInfo == INVALID_HANDLE_VALUE)
2343  goto cleanup;
2344  list = (struct DeviceInfoSet *)hDeviceInfo;
2345  }
2346 
2347  if (flags & DIGCF_PROFILE)
2348  FIXME(": flag DIGCF_PROFILE ignored\n");
2349 
2351  {
2352  if (!class)
2353  {
2355  goto cleanup;
2356  }
2357  rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
2358  }
2359  else
2360  {
2361  /* Determine which class(es) should be included in the deviceset */
2362  if (flags & DIGCF_ALLCLASSES)
2363  {
2364  /* The caller wants all classes. Check if
2365  * the deviceset limits us to one class */
2366  if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2367  pClassGuid = NULL;
2368  else
2369  pClassGuid = &list->ClassGuid;
2370  }
2371  else if (class)
2372  {
2373  /* The caller wants one class. Check if it matches deviceset class */
2374  if (IsEqualIID(&list->ClassGuid, class)
2375  || IsEqualIID(&list->ClassGuid, &GUID_NULL))
2376  {
2377  pClassGuid = class;
2378  }
2379  else
2380  {
2382  goto cleanup;
2383  }
2384  }
2385  else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
2386  {
2387  /* No class specified. Try to use the one of the deviceset */
2388  if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2389  pClassGuid = &list->ClassGuid;
2390  else
2391  {
2393  goto cleanup;
2394  }
2395  }
2396  else
2397  {
2399  goto cleanup;
2400  }
2401  rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
2402  }
2403  if (rc != ERROR_SUCCESS)
2404  {
2405  SetLastError(rc);
2406  goto cleanup;
2407  }
2408  set = hDeviceInfo;
2409 
2410 cleanup:
2411  if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
2412  SetupDiDestroyDeviceInfoList(hDeviceInfo);
2413  return set;
2414 }
2415 
2416 /***********************************************************************
2417  * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2418  */
2421  PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2422 {
2423  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2424 
2425  TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DevInfoData);
2426 
2428  {
2430  return FALSE;
2431  }
2432  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2433  {
2435  return FALSE;
2436  }
2437  if (!DevInfoData ||
2438  DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2439  {
2441  return FALSE;
2442  }
2443  memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2444  DevInfoData->RemoteMachineHandle = set->hMachine;
2445  if (set->MachineName)
2446  {
2447  FIXME("Stub\n");
2449  return FALSE;
2450  }
2451  else
2452  DevInfoData->RemoteMachineName[0] = 0;
2453 
2454  return TRUE;
2455 }
2456 
2457 /***********************************************************************
2458  * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2459  */
2462  PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2463 {
2464  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2465 
2466  TRACE("%s(%p %p)\n", __FUNCTION__, DeviceInfoSet, DevInfoData);
2467 
2469  {
2471  return FALSE;
2472  }
2473  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2474  {
2476  return FALSE;
2477  }
2478  if (!DevInfoData ||
2479  DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2480  {
2482  return FALSE;
2483  }
2484  memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2485  DevInfoData->RemoteMachineHandle = set->hMachine;
2486  if (set->MachineName)
2487  strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
2488  else
2489  DevInfoData->RemoteMachineName[0] = 0;
2490 
2491  return TRUE;
2492 }
2493 
2494 /***********************************************************************
2495  * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2496  */
2500  const GUID *InterfaceClassGuid,
2502  DWORD CreationFlags,
2503  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2504 {
2505  BOOL ret;
2506  LPWSTR ReferenceStringW = NULL;
2507 
2508  TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData,
2510  CreationFlags, DeviceInterfaceData);
2511 
2512  if (ReferenceString)
2513  {
2514  ReferenceStringW = pSetupMultiByteToUnicode(ReferenceString, CP_ACP);
2515  if (ReferenceStringW == NULL) return FALSE;
2516  }
2517 
2519  InterfaceClassGuid, ReferenceStringW, CreationFlags,
2520  DeviceInterfaceData);
2521 
2522  MyFree(ReferenceStringW);
2523 
2524  return ret;
2525 }
2526 
2527 /***********************************************************************
2528  * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2529  */
2533  const GUID *InterfaceClassGuid,
2535  DWORD CreationFlags,
2536  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2537 {
2538  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2539  TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData,
2541  CreationFlags, DeviceInterfaceData);
2542 
2544  {
2546  return FALSE;
2547  }
2548  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2549  {
2551  return FALSE;
2552  }
2554  || !DeviceInfoData->Reserved)
2555  {
2557  return FALSE;
2558  }
2559  if (!InterfaceClassGuid)
2560  {
2562  return FALSE;
2563  }
2564 
2565  FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2567  CreationFlags, DeviceInterfaceData);
2569  return FALSE;
2570 }
2571 
2572 /***********************************************************************
2573  * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2574  */
2577  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2578  DWORD Reserved,
2579  REGSAM samDesired,
2580  HINF InfHandle,
2581  PCSTR InfSectionName)
2582 {
2583  HKEY key;
2584  PWSTR InfSectionNameW = NULL;
2585 
2586  TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInterfaceData, Reserved,
2587  samDesired, InfHandle, InfSectionName);
2588  if (InfHandle)
2589  {
2590  if (!InfSectionName)
2591  {
2593  return INVALID_HANDLE_VALUE;
2594  }
2595  InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2596  if (!InfSectionNameW)
2597  return INVALID_HANDLE_VALUE;
2598  }
2600  DeviceInterfaceData, Reserved, samDesired, InfHandle,
2601  InfSectionNameW);
2602  MyFree(InfSectionNameW);
2603  return key;
2604 }
2605 
2606 /***********************************************************************
2607  * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2608  */
2611  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2612  DWORD Reserved,
2613  REGSAM samDesired,
2614  HINF InfHandle,
2615  PCWSTR InfSectionName)
2616 {
2617  HKEY hKey, hDevKey;
2619  DWORD Length, Index;
2620  LONG rc;
2621  WCHAR bracedGuidString[39];
2622  struct DeviceInterface *DevItf;
2623  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2624 
2625  TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInterfaceData, Reserved,
2626  samDesired, InfHandle, InfSectionName);
2627 
2629  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2630  {
2632  return INVALID_HANDLE_VALUE;
2633  }
2634  if (!DeviceInterfaceData ||
2635  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2636  !DeviceInterfaceData->Reserved)
2637  {
2639  return INVALID_HANDLE_VALUE;
2640  }
2641  if (InfHandle && !InfSectionName)
2642  {
2644  return INVALID_HANDLE_VALUE;
2645  }
2646 
2647  hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL);
2648  if (hKey == INVALID_HANDLE_VALUE)
2649  {
2651  if (hKey == INVALID_HANDLE_VALUE)
2652  {
2654  return INVALID_HANDLE_VALUE;
2655  }
2656  SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString);
2657 
2658  if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS)
2659  {
2661  return INVALID_HANDLE_VALUE;
2662  }
2663  RegCloseKey(hKey);
2664  hKey = hDevKey;
2665  }
2666 
2667  DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2668 
2669  Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR);
2671  if (!SymbolicLink)
2672  {
2673  RegCloseKey(hKey);
2675  return INVALID_HANDLE_VALUE;
2676  }
2677 
2678  wcscpy(SymbolicLink, DevItf->SymbolicLink);
2679 
2680  Index = 0;
2681  while(SymbolicLink[Index])
2682  {
2683  if (SymbolicLink[Index] == L'\\')
2684  {
2685  SymbolicLink[Index] = L'#';
2686  }
2687  Index++;
2688  }
2689 
2690  rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL);
2691 
2692  RegCloseKey(hKey);
2694 
2695  if (rc == ERROR_SUCCESS)
2696  {
2697  if (InfHandle && InfSectionName)
2698  {
2699  if (!SetupInstallFromInfSection(NULL /*FIXME */,
2700  InfHandle,
2701  InfSectionName,
2703  hDevKey,
2704  NULL,
2705  0,
2706  set->SelectedDevice->InstallParams.InstallMsgHandler,
2707  set->SelectedDevice->InstallParams.InstallMsgHandlerContext,
2709  NULL))
2710  {
2711  RegCloseKey(hDevKey);
2712  return INVALID_HANDLE_VALUE;
2713  }
2714  }
2715  }
2716 
2717  SetLastError(rc);
2718  return hDevKey;
2719 }
2720 
2721 /***********************************************************************
2722  * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2723  */
2726  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2727  DWORD Reserved)
2728 {
2729  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2730  BOOL ret = FALSE;
2731 
2732  TRACE("%s(%p %p %d)\n", __FUNCTION__, DeviceInfoSet, DeviceInterfaceData, Reserved);
2733 
2735  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2736  {
2738  return FALSE;
2739  }
2740  if (!DeviceInterfaceData ||
2741  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2742  !DeviceInterfaceData->Reserved)
2743  {
2745  return FALSE;
2746  }
2747 
2748  FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2750  return ret;
2751 }
2752 
2753 /***********************************************************************
2754  * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2755  *
2756  * PARAMS
2757  * DeviceInfoSet [I] Set of devices from which to enumerate
2758  * interfaces
2759  * DeviceInfoData [I] (Optional) If specified, a specific device
2760  * instance from which to enumerate interfaces.
2761  * If it isn't specified, all interfaces for all
2762  * devices in the set are enumerated.
2763  * InterfaceClassGuid [I] The interface class to enumerate.
2764  * MemberIndex [I] An index of the interface instance to enumerate.
2765  * A caller should start with MemberIndex set to 0,
2766  * and continue until the function fails with
2767  * ERROR_NO_MORE_ITEMS.
2768  * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2769  * member must be set to
2770  * sizeof(SP_DEVICE_INTERFACE_DATA).
2771  *
2772  * RETURNS
2773  * Success: non-zero value.
2774  * Failure: FALSE. Call GetLastError() for more info.
2775  */
2780  DWORD MemberIndex,
2781  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2782 {
2783  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2784  BOOL ret = FALSE;
2785 
2786  TRACE("%s(%p, %p, %s, %d, %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData,
2787  debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2788 
2790  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2791  {
2793  return FALSE;
2794  }
2795  if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2797  {
2799  return FALSE;
2800  }
2801  if (!DeviceInterfaceData ||
2802  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2803  {
2805  return FALSE;
2806  }
2807  if (DeviceInfoData)
2808  {
2809  struct DeviceInfo *devInfo =
2810  (struct DeviceInfo *)DeviceInfoData->Reserved;
2811  BOOL found = FALSE;
2812  PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2813  while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2814  {
2815  struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2817  {
2818  InterfaceListEntry = InterfaceListEntry->Flink;
2819  continue;
2820  }
2821  if (MemberIndex-- == 0)
2822  {
2823  /* return this item */
2824  memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2825  &DevItf->InterfaceClassGuid,
2826  sizeof(GUID));
2827  DeviceInterfaceData->Flags = DevItf->Flags;
2828  DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2829  found = TRUE;
2830  ret = TRUE;
2831  }
2832  InterfaceListEntry = InterfaceListEntry->Flink;
2833  }
2834  if (!found)
2836  }
2837  else
2838  {
2839  BOOL found = FALSE;
2840  PLIST_ENTRY ItemList = set->ListHead.Flink;
2841  while (ItemList != &set->ListHead && !found)
2842  {
2843  PLIST_ENTRY InterfaceListEntry;
2844  struct DeviceInfo *devInfo =
2845  CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
2846  InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2847  while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2848  {
2849  struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2851  {
2852  InterfaceListEntry = InterfaceListEntry->Flink;
2853  continue;
2854  }
2855  if (MemberIndex-- == 0)
2856  {
2857  /* return this item */
2858  memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2859  &DevItf->InterfaceClassGuid,
2860  sizeof(GUID));
2861  DeviceInterfaceData->Flags = DevItf->Flags;
2862  DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2863  found = TRUE;
2864  ret = TRUE;
2865  }
2866  InterfaceListEntry = InterfaceListEntry->Flink;
2867  }
2868  ItemList = ItemList->Flink;
2869 
2870  }
2871  if (!found)
2873  }
2874  return ret;
2875 }
2876 
2877 /***********************************************************************
2878  * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2879  *
2880  * Destroy a DeviceInfoList and free all used memory of the list.
2881  *
2882  * PARAMS
2883  * devinfo [I] DeviceInfoList pointer to list to destroy
2884  *
2885  * RETURNS
2886  * Success: non zero value.
2887  * Failure: zero value.
2888  */
2890 {
2891  BOOL ret = FALSE;
2892 
2893  TRACE("%s(%p)\n", __FUNCTION__, devinfo);
2894  if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2895  {
2896  struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2897 
2898  if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2899  {
2901  }
2902  }
2903 
2904  if (ret == FALSE)
2906 
2907  return ret;
2908 }
2909 
2910 /***********************************************************************
2911  * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2912  */
2915  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2916  PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2917  DWORD DeviceInterfaceDetailDataSize,
2920 {
2921  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2922  PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2923  DWORD sizeW = 0, bytesNeeded;
2924  BOOL ret = FALSE;
2925 
2926  TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__, DeviceInfoSet,
2927  DeviceInterfaceData, DeviceInterfaceDetailData,
2928  DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2929 
2931  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2932  {
2934  return FALSE;
2935  }
2936  if (!DeviceInterfaceData ||
2937  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2938  !DeviceInterfaceData->Reserved)
2939  {
2941  return FALSE;
2942  }
2943  if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2944  {
2946  return FALSE;
2947  }
2948 
2949  if((DeviceInterfaceDetailDataSize != 0) &&
2950  (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(CHAR))))
2951  {
2953  return FALSE;
2954  }
2955 
2956  if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2957  {
2959  return FALSE;
2960  }
2961 
2962 
2963  if (DeviceInterfaceDetailData != NULL)
2964  {
2966  + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2967  DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
2968  if (!DeviceInterfaceDetailDataW)
2969  {
2971  }
2972  DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2973  }
2974  if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2975  {
2977  DeviceInfoSet,
2978  DeviceInterfaceData,
2979  DeviceInterfaceDetailDataW,
2980  sizeW,
2981  &sizeW,
2982  DeviceInfoData);
2983  bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2985  if (RequiredSize)
2986  *RequiredSize = bytesNeeded;
2987  if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize >= bytesNeeded)
2988  {
2989  if (!WideCharToMultiByte(
2990  CP_ACP, 0,
2991  DeviceInterfaceDetailDataW->DevicePath, -1,
2992  DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2993  NULL, NULL))
2994  {
2995  ret = FALSE;
2996  }
2997  }
2998  }
2999  MyFree(DeviceInterfaceDetailDataW);
3000 
3001  return ret;
3002 }
3003 
3004 /***********************************************************************
3005  * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3006  */
3009  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
3010  PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
3011  DWORD DeviceInterfaceDetailDataSize,
3014 {
3015  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3016  BOOL ret = FALSE;
3017 
3018  TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__, DeviceInfoSet,
3019  DeviceInterfaceData, DeviceInterfaceDetailData,
3020  DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3021 
3023  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3024  {
3026  return FALSE;
3027  }
3028  if (!DeviceInterfaceData ||
3029  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3030  !DeviceInterfaceData->Reserved)
3031  {
3033  return FALSE;
3034  }
3035  if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
3036  {
3038  return FALSE;
3039  }
3040  if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3041  {
3043  return FALSE;
3044  }
3046  {
3048  return FALSE;
3049  }
3050  if ((DeviceInterfaceDetailData != NULL)
3051  && (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) + sizeof(WCHAR)))
3052  {
3054  return FALSE;
3055  }
3056  else
3057  {
3058  struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
3059  LPCWSTR devName = deviceInterface->SymbolicLink;
3060  DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
3061  (lstrlenW(devName) + 1) * sizeof(WCHAR);
3062 
3063  if (sizeRequired > DeviceInterfaceDetailDataSize)
3064  {
3066  if (RequiredSize)
3067  *RequiredSize = sizeRequired;
3068  }
3069  else
3070  {
3071  strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
3072  TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
3073  if (DeviceInfoData)
3074  {
3076  &deviceInterface->DeviceInfo->ClassGuid,
3077  sizeof(GUID));
3078  DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
3079  DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
3080  }
3081  ret = TRUE;
3082  }
3083  }
3084  return ret;
3085 }
3086 
3088 {
3092 };
3093 
3094 static struct PropertyMapEntry PropertyMap[] = {
3095  { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
3096  { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
3097  { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
3098  { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3099  { REG_SZ, "Service", REGSTR_VAL_SERVICE },
3100  { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3101  { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3102  { REG_SZ, "Class", REGSTR_VAL_CLASS },
3103  { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
3104  { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
3105  { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
3106  { REG_SZ, "Mfg", REGSTR_VAL_MFG },
3107  { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
3108  { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
3109  { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3110  { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
3111  { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
3112  { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
3113  { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
3114  { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
3115  { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
3116  { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
3117  { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
3118  { REG_BINARY, "Security", REGSTR_SECURITY },
3119  { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
3120  { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
3121  { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
3122  { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
3123  { 0, NULL, NULL }, /* SPDRP_ADDRESS */
3124  { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
3125  { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
3126  { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
3127  { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3128  { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3129  { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
3130 };
3131 
3132 /***********************************************************************
3133  * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3134  */
3138  DWORD Property,
3143 {
3144  BOOL ret;
3145  BOOL bIsStringProperty;
3146  DWORD RegType;
3147  DWORD RequiredSizeA, RequiredSizeW;
3148  DWORD PropertyBufferSizeW = 0;
3149  PBYTE PropertyBufferW = NULL;
3150 
3151  TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData,
3153  RequiredSize);
3154 
3155  if (PropertyBufferSize != 0)
3156  {
3157  PropertyBufferSizeW = PropertyBufferSize * 2;
3158  PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
3159  if (!PropertyBufferW)
3160  {
3162  return FALSE;
3163  }
3164  }
3165 
3168  Property,
3169  &RegType,
3170  PropertyBufferW,
3171  PropertyBufferSizeW,
3172  &RequiredSizeW);
3173 
3175  {
3176  bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
3177 
3178  if (bIsStringProperty)
3179  RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
3180  else
3181  RequiredSizeA = RequiredSizeW;
3182  if (RequiredSize)
3183  *RequiredSize = RequiredSizeA;
3184  if (PropertyRegDataType)
3185  *PropertyRegDataType = RegType;
3186  }
3187 
3188  if (!ret)
3189  {
3190  HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3191  return ret;
3192  }
3193 
3194  if (RequiredSizeA <= PropertyBufferSize)
3195  {
3196  if (bIsStringProperty && PropertyBufferSize > 0)
3197  {
3198  if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
3199  {
3200  /* Last error is already set by WideCharToMultiByte */
3201  ret = FALSE;
3202  }
3203  }
3204  else
3205  memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
3206  }
3207  else
3208  {
3210  ret = FALSE;
3211  }
3212 
3213  HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3214  return ret;
3215 }
3216 
3217 /***********************************************************************
3218  * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3219  */
3223  DWORD Property,
3228 {
3229  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3230  struct DeviceInfo *devInfo;
3231  CONFIGRET cr;
3232  LONG lError = ERROR_SUCCESS;
3233  DWORD size;
3234 
3235  TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData,
3237  RequiredSize);
3238 
3240  {
3242  return FALSE;
3243  }
3244  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3245  {
3247  return FALSE;
3248  }
3250  || !DeviceInfoData->Reserved)
3251  {
3253  return FALSE;
3254  }
3255 
3257  {
3259  return FALSE;
3260  }
3261 
3262  devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3263 
3264  if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3266  {
3267  HKEY hKey;
3269  hKey = SETUPDI_OpenDevKey(set->HKLM, devInfo, KEY_QUERY_VALUE);
3270  if (hKey == INVALID_HANDLE_VALUE)
3271  return FALSE;
3274  RegCloseKey(hKey);
3275 
3276  if (RequiredSize)
3277  *RequiredSize = size;
3278 
3279  switch (lError)
3280  {
3281  case ERROR_SUCCESS:
3282  if (PropertyBuffer == NULL && size != 0)
3283  lError = ERROR_INSUFFICIENT_BUFFER;
3284  break;
3285  case ERROR_MORE_DATA:
3286  lError = ERROR_INSUFFICIENT_BUFFER;
3287  break;
3288  default:
3289  break;
3290  }
3291  }
3293  {
3294  size = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR);
3295 
3296  if (PropertyRegDataType)
3298  if (RequiredSize)
3299  *RequiredSize = size;
3300  if (PropertyBufferSize >= size)
3301  {
3302  strcpyW((LPWSTR)PropertyBuffer, devInfo->Data);
3303  }
3304  else
3305  lError = ERROR_INSUFFICIENT_BUFFER;
3306  }
3307  else
3308  {
3310 
3315  &size,
3316  0,
3317  set->hMachine);
3318  if ((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL))
3319  {
3320  if (RequiredSize)
3321  *RequiredSize = size;
3322  }
3323 
3324  if (cr != CR_SUCCESS)
3325  {
3326  switch (cr)
3327  {
3328  case CR_INVALID_DEVINST:
3329  lError = ERROR_NO_SUCH_DEVINST;
3330  break;
3331 
3332  case CR_INVALID_PROPERTY:
3333  lError = ERROR_INVALID_REG_PROPERTY;
3334  break;
3335 
3336  case CR_BUFFER_SMALL:
3337  lError = ERROR_INSUFFICIENT_BUFFER;
3338  break;
3339 
3340  default :
3341  lError = ERROR_INVALID_DATA;
3342  break;
3343  }
3344  }
3345  }
3346 
3347  SetLastError(lError);
3348  return (lError == ERROR_SUCCESS);
3349 }
3350 
3351 /***********************************************************************
3352  * Internal for SetupDiSetDeviceRegistryPropertyA/W
3353  */
3357  DWORD Property,
3358  const BYTE *PropertyBuffer,
3360  BOOL isAnsi)
3361 {
3362  BOOL ret = FALSE;
3363  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3364  struct DeviceInfo *deviceInfo;
3365 
3366  TRACE("%s(%p %p %d %p %d)\n", __FUNCTION__, DeviceInfoSet, DeviceInfoData, Property,
3368 
3370  {
3372  return FALSE;
3373  }
3374  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3375  {
3377  return FALSE;
3378  }
3380  || !DeviceInfoData->Reserved)
3381  {
3383  return FALSE;
3384  }
3385 
3386  deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3387 
3388  if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3390  && PropertyMap[Property].nameA)
3391  {
3392  HKEY hKey;
3393  LONG l;
3394  hKey = SETUPDI_OpenDevKey(set->HKLM, deviceInfo, KEY_SET_VALUE);
3395  if (hKey == INVALID_HANDLE_VALUE)
3396  return FALSE;
3397  /* Write new data */
3398  if (isAnsi)
3399  {
3400  l = RegSetValueExA(
3401  hKey, PropertyMap[Property].nameA, 0,
3404  }
3405  else
3406  {
3407  l = RegSetValueExW(
3411  }
3412  if (!l)
3413  ret = TRUE;
3414  else
3415  SetLastError(l);
3416  RegCloseKey(hKey);
3417  }
3418  else
3419  {
3420  ERR("Property 0x%lx not implemented\n", Property);
3422  }
3423 
3424  TRACE("Returning %d\n", ret);
3425  return ret;
3426 }
3427 /***********************************************************************
3428  * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3429  */
3433  DWORD Property,
3434  const BYTE *PropertyBuffer,
3436 {
3439  Property,
3442  TRUE);
3443 }
3444 
3445 /***********************************************************************
3446  * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3447  */
3451  DWORD Property,
3452  const BYTE *PropertyBuffer,
3454 {
3457  Property,
3460  FALSE);
3461 }
3462 
3463 /***********************************************************************
3464  * SetupDiInstallClassA (SETUPAPI.@)
3465  */
3467  HWND hwndParent,
3468  PCSTR InfFileName,
3469  DWORD Flags,
3470  HSPFILEQ FileQueue)
3471 {
3472  return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3473 }
3474 
3475 /***********************************************************************
3476  * SetupDiInstallClassExA (SETUPAPI.@)
3477  */
3478 BOOL WINAPI
3481  IN PCSTR InfFileName OPTIONAL,
3482  IN DWORD Flags,
3483  IN HSPFILEQ FileQueue OPTIONAL,
3485  IN PVOID Reserved1,
3486  IN PVOID Reserved2)
3487 {
3488  PWSTR InfFileNameW = NULL;
3489  BOOL Result;
3490 
3491  if (!InfFileName)
3492  {
3494  return FALSE;
3495  }
3496  else
3497  {
3498  InfFileNameW = pSetupMultiByteToUnicode(InfFileName, CP_ACP);
3499  if (InfFileNameW == NULL)
3500  {
3502  return FALSE;
3503  }
3504  }
3505 
3506  Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
3507  FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
3508 
3509  MyFree(InfFileNameW);
3510 
3511  return Result;
3512 }
3513 
3515 {
3516  WCHAR FullBuffer[MAX_PATH];
3519  HKEY hClassKey;
3521 
3522  /* Obtain the Class GUID for this class */
3523  if (!SetupGetLineTextW(NULL,
3524  hInf,
3525  Version,
3527  Buffer,
3528  sizeof(Buffer) / sizeof(WCHAR),
3529  &RequiredSize))
3530  {
3531  return INVALID_HANDLE_VALUE;
3532  }
3533 
3534  /* Build the corresponding registry key name */
3535  lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
3536  lstrcatW(FullBuffer, BackSlash);
3537  lstrcatW(FullBuffer, Buffer);
3538 
3539  /* Obtain the Class name for this class */
3540  if (!SetupGetLineTextW(NULL,
3541  hInf,
3542  Version,
3544  Buffer,
3545  sizeof(Buffer) / sizeof(WCHAR),
3546  &RequiredSize))
3547  {
3548  return INVALID_HANDLE_VALUE;
3549  }
3550 
3551  /* Try to open or create the registry key */
3552  TRACE("Opening class key %s\n", debugstr_w(FullBuffer));
3553 #if 0 // I keep this for reference...
3555  FullBuffer,
3556  0,
3557  KEY_SET_VALUE,
3558  &hClassKey))
3559  {
3560  /* Use RegCreateKeyExW */
3561  }
3562 #endif
3564  FullBuffer,
3565  0,
3566  NULL,
3568  KEY_SET_VALUE,
3569  NULL,
3570  &hClassKey,
3571  &Disposition))
3572  {
3573  ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer));
3574  return INVALID_HANDLE_VALUE;
3575  }
3577  TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer));
3578  else
3579  TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer));
3580 
3581  TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS), debugstr_w(Buffer) );
3584  0,
3585  REG_SZ,
3586  (LPBYTE)Buffer,
3587  RequiredSize * sizeof(WCHAR)))
3588  {
3591  FullBuffer);
3592  return INVALID_HANDLE_VALUE;
3593  }
3594 
3595  return hClassKey;
3596 }
3597 
3598 /***********************************************************************
3599  * SetupDiInstallClassW (SETUPAPI.@)
3600  */
3602  HWND hwndParent,
3603  PCWSTR InfFileName,
3604  DWORD Flags,
3605  HSPFILEQ FileQueue)
3606 {
3607  return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3608 }
3609 
3610 
3611 /***********************************************************************
3612  * SetupDiOpenClassRegKey (SETUPAPI.@)
3613  */
3615  const GUID* ClassGuid,
3616  REGSAM samDesired)
3617 {
3618  return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3620 }
3621 
3622 
3623 /***********************************************************************
3624  * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3625  */
3627  const GUID* ClassGuid,
3628  REGSAM samDesired,
3629  DWORD Flags,
3631  PVOID Reserved)
3632 {
3633  PWSTR MachineNameW = NULL;
3634  HKEY hKey;
3635 
3636  TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), samDesired,
3638 
3639  if (MachineName)
3640  {
3641  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
3642  if (MachineNameW == NULL)
3643  return INVALID_HANDLE_VALUE;
3644  }
3645 
3647  Flags, MachineNameW, Reserved);
3648 
3649  MyFree(MachineNameW);
3650 
3651  return hKey;
3652 }
3653 
3654 
3655 /***********************************************************************
3656  * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3657  */
3659  const GUID* ClassGuid,
3660  REGSAM samDesired,
3661  DWORD Flags,
3663  PVOID Reserved)
3664 {
3665  HKEY HKLM;
3666  HKEY hClassesKey;
3667  HKEY key;
3668  LPCWSTR lpKeyName;
3669  LONG l;
3670 
3671  TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__, debugstr_guid(ClassGuid), samDesired,
3673 
3674  if (MachineName != NULL)
3675  {
3677  if (l != ERROR_SUCCESS)
3678  {
3679  SetLastError(l);
3680  return INVALID_HANDLE_VALUE;
3681  }
3682  }
3683  else
3685 
3686  if (Flags == DIOCR_INSTALLER)
3687  {
3688  lpKeyName = REGSTR_PATH_CLASS_NT;
3689  }
3690  else if (Flags == DIOCR_INTERFACE)
3691  {
3692  lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
3693  }
3694  else
3695  {
3696  ERR("Invalid Flags parameter!\n");
3698  if (MachineName != NULL) RegCloseKey(HKLM);
3699  return INVALID_HANDLE_VALUE;
3700  }
3701 
3702  if (!ClassGuid)
3703  {
3704  if ((l = RegOpenKeyExW(HKLM,
3705  lpKeyName,
3706  0,
3707  samDesired,
3708  &hClassesKey)))
3709  {
3711  hClassesKey = INVALID_HANDLE_VALUE;
3712  }
3713  if (MachineName != NULL)
3714  RegCloseKey(HKLM);
3715  key = hClassesKey;
3716  }
3717  else
3718  {
3719  WCHAR bracedGuidString[39];
3720 
3721  SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3722 
3723  if (!(l = RegOpenKeyExW(HKLM,
3724  lpKeyName,
3725  0,
3726  samDesired,
3727  &hClassesKey)))
3728  {
3729  if (MachineName != NULL)
3730  RegCloseKey(HKLM);
3731 
3732  if ((l = RegOpenKeyExW(hClassesKey,
3733  bracedGuidString,
3734  0,
3735  samDesired,
3736  &key)))
3737  {
3738  SetLastError(l);
3740  }
3741  RegCloseKey(hClassesKey);
3742  }
3743  else
3744  {
3745  if (MachineName != NULL) RegCloseKey(HKLM);
3746  SetLastError(l);
3748  }
3749  }
3750 
3751  return key;
3752 }
3753 
3754 /***********************************************************************
3755  * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3756  */
3759  PCWSTR DevicePath,
3760  DWORD OpenFlags,
3761  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3762 {
3763  struct DeviceInfoSet * list;
3764  PCWSTR pEnd;
3765  DWORD dwLength, dwError, dwIndex, dwKeyName, dwSubIndex;
3766  CLSID ClassId;
3767  WCHAR Buffer[MAX_PATH + 1];
3768  WCHAR SymBuffer[MAX_PATH + 1];
3769  WCHAR InstancePath[MAX_PATH + 1];
3770  HKEY hKey, hDevKey, hSymKey;
3771  struct DeviceInfo * deviceInfo;
3772  struct DeviceInterface *deviceInterface;
3773  BOOL Ret;
3774  PLIST_ENTRY ItemList;
3775  PLIST_ENTRY InterfaceListEntry;
3776 
3777  TRACE("%s(%p %s %08x %p)\n", __FUNCTION__,
3778  DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3779 
3780 
3781  if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
3782  {
3784  return FALSE;
3785  }
3786 
3788  {
3790  return FALSE;
3791  }
3792 
3793  list = (struct DeviceInfoSet * )DeviceInfoSet;
3794 
3795  dwLength = wcslen(DevicePath);
3796  if (dwLength < 39)
3797  {
3798  /* path must be at least a guid length + L'\0' */
3800  return FALSE;
3801  }
3802 
3803  if (DevicePath[0] != L'\\' ||
3804  DevicePath[1] != L'\\' ||
3805  (DevicePath[2] != L'?' && DevicePath[2] != L'.') ||
3806  DevicePath[3] != L'\\')
3807  {
3808  /* invalid formatted path */
3810  return FALSE;
3811  }
3812 
3813  /* check for reference strings */
3814  pEnd = wcschr(&DevicePath[4], L'\\');
3815  if (!pEnd)
3816  {
3817  /* no reference string */
3818  pEnd = DevicePath + dwLength;
3819  }
3820 
3821  /* copy guid */
3822  wcscpy(Buffer, pEnd - 37);
3823  Buffer[36] = L'\0';
3824 
3825  dwError = UuidFromStringW(Buffer, &ClassId);
3826  if (dwError != NOERROR)
3827  {
3828  /* invalid formatted path */
3830  return FALSE;
3831  }
3832 
3833  hKey = SetupDiOpenClassRegKeyExW(&ClassId, KEY_READ, DIOCR_INTERFACE, list->MachineName, NULL);
3834 
3835  if (hKey == INVALID_HANDLE_VALUE)
3836  {
3837  /* invalid device class */
3838  return FALSE;
3839  }
3840 
3841  ItemList = list->ListHead.Flink;
3842  while (ItemList != &list->ListHead)
3843  {
3844  deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
3845  InterfaceListEntry = deviceInfo->InterfaceListHead.Flink;
3846  while (InterfaceListEntry != &deviceInfo->InterfaceListHead)
3847  {
3848  deviceInterface = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
3849  if (!IsEqualIID(&deviceInterface->InterfaceClassGuid, &ClassId))
3850  {
3851  InterfaceListEntry = InterfaceListEntry->Flink;
3852  continue;
3853  }
3854 
3855  if (!wcsicmp(deviceInterface->SymbolicLink, DevicePath))
3856  {
3857  if (DeviceInterfaceData)
3858  {
3859  DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
3860  DeviceInterfaceData->Flags = deviceInterface->Flags;
3861  CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
3862  }
3863 
3864  return TRUE;
3865  }
3866 
3867  }
3868  }
3869 
3870 
3871  dwIndex = 0;
3872  do
3873  {
3874  Buffer[0] = 0;
3875  dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
3876  dwError = RegEnumKeyExW(hKey, dwIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
3877 
3878  if (dwError != ERROR_SUCCESS)
3879  break;
3880 
3881  if (RegOpenKeyExW(hKey, Buffer, 0, KEY_READ, &hDevKey) != ERROR_SUCCESS)
3882  break;
3883 
3884  dwSubIndex = 0;
3885  InstancePath[0] = 0;
3886  dwKeyName = sizeof(InstancePath);
3887 
3888  dwError = RegQueryValueExW(hDevKey, L"DeviceInstance", NULL, NULL, (LPBYTE)InstancePath, &dwKeyName);
3889 
3890  while(TRUE)
3891  {
3892  Buffer[0] = 0;
3893  dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
3894  dwError = RegEnumKeyExW(hDevKey, dwSubIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
3895 
3896  if (dwError != ERROR_SUCCESS)
3897  break;
3898 
3899  dwError = RegOpenKeyExW(hDevKey, Buffer, 0, KEY_READ, &hSymKey);
3900  if (dwError != ERROR_SUCCESS)
3901  break;
3902 
3903  /* query for symbolic link */
3904  dwKeyName = sizeof(SymBuffer);
3905  SymBuffer[0] = L'\0';
3906  dwError = RegQueryValueExW(hSymKey, L"SymbolicLink", NULL, NULL, (LPBYTE)SymBuffer, &dwKeyName);
3907 
3908  if (dwError != ERROR_SUCCESS)
3909  {
3910  RegCloseKey(hSymKey);
3911  break;
3912  }
3913 
3914  if (!wcsicmp(SymBuffer, DevicePath))
3915  {
3916  Ret = CreateDeviceInfo(list, InstancePath, &ClassId, &deviceInfo);
3917  RegCloseKey(hSymKey);
3918  RegCloseKey(hDevKey);
3919  RegCloseKey(hKey);
3920 
3921  if (Ret)
3922  {
3923  deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymBuffer) + 1) * sizeof(WCHAR));
3924  if (deviceInterface)
3925  {
3926 
3927  CopyMemory(&deviceInterface->InterfaceClassGuid, &ClassId, sizeof(GUID));
3928  deviceInterface->DeviceInfo = deviceInfo;
3929  deviceInterface->Flags = SPINT_ACTIVE; //FIXME
3930 
3931  wcscpy(deviceInterface->SymbolicLink, SymBuffer);
3932 
3933  InsertTailList(&deviceInfo->InterfaceListHead, &deviceInterface->ListEntry);
3934  InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
3935 
3936 
3937  if (DeviceInterfaceData)
3938  {
3939  DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
3940  DeviceInterfaceData->Flags = deviceInterface->Flags;
3941  CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
3942  }
3943  else
3944  {
3945  Ret = FALSE;
3947  }
3948  }
3949  }
3950  else
3951  {
3952  HeapFree(GetProcessHeap(), 0, deviceInfo);
3953  Ret = FALSE;
3954  }
3955  return Ret;
3956  }
3957  RegCloseKey(hSymKey);
3958  dwSubIndex++;
3959  }
3960 
3961  RegCloseKey(hDevKey);
3962  dwIndex++;
3963  } while(TRUE);
3964 
3965  RegCloseKey(hKey);
3966  return FALSE;
3967 }
3968 
3969 /***********************************************************************
3970  * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3971  */
3974  PCSTR DevicePath,
3975  DWORD OpenFlags,
3976  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3977 {
3978  LPWSTR DevicePathW = NULL;
3979  BOOL bResult;
3980 
3981  TRACE("%s(%p %s %08lx %p)\n", __FUNCTION__, DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3982 
3983  DevicePathW = pSetupMultiByteToUnicode(DevicePath, CP_ACP);
3984  if (DevicePathW == NULL)
3985  return FALSE;
3986 
3988  DevicePathW, OpenFlags, DeviceInterfaceData);
3989 
3990  MyFree(DevicePathW);
3991 
3992  return bResult;
3993 }
3994 
3995 /***********************************************************************
3996  * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3997  */
4003 {
4004  FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
4005  ClassInstallParams->InstallFunction, ClassInstallParamsSize);
4006  return FALSE;
4007 }
4008 
4009 static BOOL WINAPI
4013 {
4015 }
4016 
4017 /***********************************************************************
4018  * SetupDiCallClassInstaller (SETUPAPI.@)
4019  */
4021  DI_FUNCTION InstallFunction,
4024 {
4025  BOOL ret = FALSE;
4026 
4027  TRACE("%s(%u %p %p)\n", __FUNCTION__, InstallFunction, DeviceInfoSet, DeviceInfoData);
4028 
4029  if (!DeviceInfoSet)
4035  else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
4037  else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4039  else
4040  {
4042 #define CLASS_COINSTALLER 0x1
4043 #define DEVICE_COINSTALLER 0x2
4044 #define CLASS_INSTALLER 0x4
4045  UCHAR CanHandle = 0;
4047 
4048  switch (InstallFunction)
4049  {
4052  break;
4055  break;
4056  case DIF_ALLOW_INSTALL:
4057  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4058  break;
4059  case DIF_DETECT:
4060  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4061  break;
4063  CanHandle = CLASS_INSTALLER;
4064  break;
4065  case DIF_INSTALLDEVICE:
4068  break;
4070  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4072  break;
4073  case DIF_INSTALLINTERFACES:
4076  break;
4079  break;
4081  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4082  break;
4084  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4085  break;
4087  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4088  break;
4090  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4091  break;
4092  case DIF_POWERMESSAGEWAKE:
4094  break;
4095  case DIF_PROPERTYCHANGE:
4098  break;
4100  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4102  break;
4103  case DIF_REGISTERDEVICE:
4104  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4106  break;
4107  case DIF_REMOVE:
4110  break;
4112  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4114  break;
4115  case DIF_SELECTDEVICE:
4116  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4118  break;
4119  case DIF_TROUBLESHOOTER:
4121  break;
4122  case DIF_UNREMOVE:
4125  break;
4126  default:
4127  ERR("Install function %u not supported\n", InstallFunction);
4129  }
4130 
4133  /* Don't process this call, as a parameter is invalid */
4134  CanHandle = 0;
4135 
4136  if (CanHandle != 0)
4137  {
4138  LIST_ENTRY ClassCoInstallersListHead;
4139  LIST_ENTRY DeviceCoInstallersListHead;
4140  HMODULE ClassInstallerLibrary = NULL;
4141  CLASS_INSTALL_PROC ClassInstaller = NULL;
4143  PLIST_ENTRY ListEntry;
4144  HKEY hKey;
4145  DWORD dwRegType, dwLength;
4146  DWORD rc = NO_ERROR;
4147 
4148  InitializeListHead(&ClassCoInstallersListHead);
4149  InitializeListHead(&DeviceCoInstallersListHead);
4150 
4151  if (CanHandle & DEVICE_COINSTALLER)
4152  {
4154  if (hKey != INVALID_HANDLE_VALUE)
4155  {
4157  if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4158  {
4159  LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4160  if (KeyBuffer != NULL)
4161  {
4163  if (rc == ERROR_SUCCESS)
4164  {
4165  LPWSTR ptr;
4166  for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4167  {
4168  /* Add coinstaller to DeviceCoInstallersListHead list */
4169  struct CoInstallerElement *coinstaller;
4170  TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
4171  coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4172  if (!coinstaller)
4173  continue;
4174  ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4175  if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4176  InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
4177  else
4178  HeapFree(GetProcessHeap(), 0, coinstaller);
4179  }
4180  }
4181  HeapFree(GetProcessHeap(), 0, KeyBuffer);
4182  }
4183  }
4184  RegCloseKey(hKey);
4185  }
4186  }
4187  if (CanHandle & CLASS_COINSTALLER)
4188  {
4189  rc = RegOpenKeyExW(
4192  0, /* Options */
4194  &hKey);
4195  if (rc == ERROR_SUCCESS)
4196  {
4197  WCHAR szGuidString[40];
4198  if (pSetupStringFromGuid(&DeviceInfoData->ClassGuid, szGuidString, ARRAYSIZE(szGuidString)) == ERROR_SUCCESS)
4199  {
4200  rc = RegQueryValueExW(hKey, szGuidString, NULL, &dwRegType, NULL, &dwLength);
4201  if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4202  {
4203  LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4204  if (KeyBuffer != NULL)
4205  {
4206  rc = RegQueryValueExW(hKey, szGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4207  if (rc == ERROR_SUCCESS)
4208  {
4209  LPWSTR ptr;
4210  for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4211  {
4212  /* Add coinstaller to ClassCoInstallersListHead list */
4213  struct CoInstallerElement *coinstaller;
4214  TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
4215  coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4216  if (!coinstaller)
4217  continue;
4218  ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4219  if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4220  InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
4221  else
4222  HeapFree(GetProcessHeap(), 0, coinstaller);
4223  }
4224  }
4225  HeapFree(GetProcessHeap(), 0, KeyBuffer);
4226  }
4227  }
4228  }
4229  RegCloseKey(hKey);
4230  }
4231  }
4232  if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
4233  {
4235  if (hKey != INVALID_HANDLE_VALUE)
4236  {
4238  if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
4239  {
4240  LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4241  if (KeyBuffer != NULL)
4242  {
4244  if (rc == ERROR_SUCCESS)
4245  {
4246  /* Get ClassInstaller function pointer */
4247  TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
4248  if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
4249  {
4250  InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
4252  }
4253  }
4254  HeapFree(GetProcessHeap(), 0, KeyBuffer);
4255  }
4256  }
4257  RegCloseKey(hKey);
4258  }
4259  }
4260 
4261  /* Call Class co-installers */
4262  Context.PostProcessing = FALSE;
4263  rc = NO_ERROR;
4264  ListEntry = ClassCoInstallersListHead.Flink;
4265  while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
4266  {
4267  struct CoInstallerElement *coinstaller;
4268  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4269  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4270  coinstaller->PrivateData = Context.PrivateData;
4272  {
4273  coinstaller->DoPostProcessing = TRUE;
4274  rc = NO_ERROR;
4275  }
4277  }
4278 
4279  /* Call Device co-installers */
4280  ListEntry = DeviceCoInstallersListHead.Flink;
4281  while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
4282  {
4283  struct CoInstallerElement *coinstaller;
4284  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4285  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4286  coinstaller->PrivateData = Context.PrivateData;
4288  {
4289  coinstaller->DoPostProcessing = TRUE;
4290  rc = NO_ERROR;
4291  }
4293  }
4294 
4295  /* Call Class installer */
4296  if (ClassInstaller)
4297  {
4298  rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
4299  FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
4300  }
4301  else
4302  rc = ERROR_DI_DO_DEFAULT;
4303 
4304  /* Call default handler */
4305  if (rc == ERROR_DI_DO_DEFAULT)
4306  {
4307  if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
4308  {
4310  rc = NO_ERROR;
4311  else
4312  rc = GetLastError();
4313  }
4314  else
4315  rc = NO_ERROR;
4316  }
4317 
4318  /* Call Class co-installers that required postprocessing */
4319  Context.PostProcessing = TRUE;
4320  ListEntry = ClassCoInstallersListHead.Flink;
4321  while (ListEntry != &ClassCoInstallersListHead)
4322  {
4323  struct CoInstallerElement *coinstaller;
4324  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4325  if (coinstaller->DoPostProcessing)
4326  {
4327  Context.InstallResult = rc;
4328  Context.PrivateData = coinstaller->PrivateData;
4329  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4330  }
4331  FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4333  }
4334 
4335  /* Call Device co-installers that required postprocessing */
4336  ListEntry = DeviceCoInstallersListHead.Flink;
4337  while (ListEntry != &DeviceCoInstallersListHead)
4338  {
4339  struct CoInstallerElement *coinstaller;
4340  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4341  if (coinstaller->DoPostProcessing)
4342  {
4343  Context.InstallResult = rc;
4344  Context.PrivateData = coinstaller->PrivateData;
4345  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4346  }
4347  FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4349  }
4350 
4351  /* Free allocated memory */
4352  while (!IsListEmpty(&ClassCoInstallersListHead))
4353  {
4354  ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
4356  }
4357  while (!IsListEmpty(&DeviceCoInstallersListHead))
4358  {
4359  ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
4361  }
4362 
4363  ret = (rc == NO_ERROR);
4364  }
4365  }
4366 
4367  TRACE("Returning %d\n", ret);
4368  return ret;
4369 }
4370 
4371 /***********************************************************************
4372  * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4373  */
4378 {
4379  SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4380  BOOL ret = FALSE;
4381 
4383 
4384  if (DeviceInstallParams == NULL)
4386  else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
4388  else
4389  {
4390  deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4392 
4393  if (ret)
4394  {
4395  /* Do W->A conversion */
4396  memcpy(
4398  &deviceInstallParamsW,
4399  FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
4400  if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
4401  DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
4402  {