ReactOS  0.4.12-dev-685-gf36cbf7
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 /* Unicode constants */
25 static const WCHAR BackSlash[] = {'\\',0};
26 static const WCHAR DateFormat[] = {'%','u','-','%','u','-','%','u',0};
27 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
28 static const WCHAR DotHW[] = {'.','H','W',0};
29 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
30 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
31 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
32 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
33 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
34 
35 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
39 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
40 
41 typedef DWORD
43  IN DI_FUNCTION InstallFunction,
46 typedef BOOL
50 typedef DWORD
52  IN DI_FUNCTION InstallFunction,
56 
58 {
60 
65 };
66 
68 {
75 };
76 
77 
78 
80 {
81  static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
82  '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
83  'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
84  '0','2','X','}',0};
85 
86  sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
87  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
88  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
89 }
90 
91 static DWORD
93 {
94  switch (cr)
95  {
99  case CR_FAILURE: return ERROR_GEN_FAILURE;
113  case CR_SUCCESS: return ERROR_SUCCESS;
114  default: return ERROR_GEN_FAILURE;
115  }
116 
117  /* Does not happen */
118 }
119 
120 /* Lower scores are best ones */
121 static BOOL
123  IN LPCWSTR SectionName,
124  IN PSP_ALTPLATFORM_INFO PlatformInfo,
125  IN BYTE ProductType,
126  IN WORD SuiteMask,
127  OUT PDWORD ScorePlatform,
128  OUT PDWORD ScoreMajorVersion,
129  OUT PDWORD ScoreMinorVersion,
130  OUT PDWORD ScoreProductType,
131  OUT PDWORD ScoreSuiteMask)
132 {
133  LPWSTR Section = NULL;
134  //LPCWSTR pExtensionPlatform;
135  LPCWSTR pExtensionArchitecture;
136  LPWSTR Fields[6];
137  DWORD i;
138  BOOL ret = FALSE;
139 
140  //static const WCHAR ExtensionPlatformNone[] = {'.',0};
141  static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
142  static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
143 
144  static const WCHAR ExtensionArchitectureNone[] = {0};
145  static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
146  static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
147  static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
148  static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
149  static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
150  static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
151 
152  TRACE("%s %p 0x%x 0x%x\n",
153  debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
154 
155  *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
156 
157  Section = pSetupDuplicateString(SectionName);
158  if (!Section)
159  {
160  TRACE("pSetupDuplicateString() failed\n");
161  goto cleanup;
162  }
163 
164  /* Set various extensions values */
165  switch (PlatformInfo->Platform)
166  {
168  //pExtensionPlatform = ExtensionPlatformWindows;
169  break;
171  //pExtensionPlatform = ExtensionPlatformNT;
172  break;
173  default:
174  ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform);
175  //pExtensionPlatform = ExtensionPlatformNone;
176  break;
177  }
178  switch (PlatformInfo->ProcessorArchitecture)
179  {
181  pExtensionArchitecture = ExtensionArchitecturealpha;
182  break;
184  pExtensionArchitecture = ExtensionArchitectureamd64;
185  break;
187  pExtensionArchitecture = ExtensionArchitectureia64;
188  break;
190  pExtensionArchitecture = ExtensionArchitecturex86;
191  break;
193  pExtensionArchitecture = ExtensionArchitecturemips;
194  break;
196  pExtensionArchitecture = ExtensionArchitectureppc;
197  break;
198  default:
199  ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
201  pExtensionArchitecture = ExtensionArchitectureNone;
202  break;
203  }
204 
205  /*
206  * Field[0] Platform
207  * Field[1] Architecture
208  * Field[2] Major version
209  * Field[3] Minor version
210  * Field[4] Product type
211  * Field[5] Suite mask
212  * Remark: these fields may be NULL if the information is not provided
213  */
214  Fields[0] = Section;
215  if (Fields[0] == NULL)
216  {
217  TRACE("No extension found\n");
218  *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
219  ret = TRUE;
220  goto cleanup;
221  }
222  Fields[1] = Fields[0] + 1;
223  Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
224  for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
225  {
226  Fields[i] = wcschr(Fields[i - 1], '.');
227  if (Fields[i])
228  {
229  Fields[i]++;
230  *(Fields[i] - 1) = UNICODE_NULL;
231  }
232  }
233  /* Take care of first 2 fields */
234  if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
235  {
236  if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
237  {
238  TRACE("Mismatch on platform field\n");
239  goto cleanup;
240  }
241  Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
242  }
243  else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
244  {
245  if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
246  {
247  TRACE("Mismatch on platform field\n");
248  goto cleanup;
249  }
250  Fields[1] += wcslen(ExtensionPlatformNT) - 1;
251  }
252  else
253  {
254  /* No platform specified */
255  *ScorePlatform |= 0x02;
256  }
257  if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
258  {
259  /* No architecture specified */
260  *ScorePlatform |= 0x01;
261  }
262  else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
263  {
264  TRACE("Mismatch on architecture field ('%s' and '%s')\n",
265  debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
266  goto cleanup;
267  }
268 
269  /* Check if informations are matching */
270  if (Fields[2] && *Fields[2])
271  {
273  MajorVersion = strtoulW(Fields[2], NULL, 0);
274  if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
275  (errno == ERANGE || errno == EINVAL))
276  {
277  TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
278  goto cleanup;
279  }
280  if (Fields[3] && *Fields[3])
281  {
282  MinorVersion = strtoulW(Fields[3], NULL, 0);
283  if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
284  (errno == ERANGE || errno == EINVAL))
285  {
286  TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
287  goto cleanup;
288  }
289  }
290  if (PlatformInfo->MajorVersion < MajorVersion ||
291  (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
292  {
293  TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
294  MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
295  goto cleanup;
296  }
297  *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
298  if (MajorVersion == PlatformInfo->MajorVersion)
299  *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
300  else
301  *ScoreMinorVersion = MinorVersion;
302  }
303  else if (Fields[3] && *Fields[3])
304  {
305  TRACE("Minor version found without major version\n");
306  goto cleanup;
307  }
308  else
309  {
310  *ScoreMajorVersion = PlatformInfo->MajorVersion;
311  *ScoreMinorVersion = PlatformInfo->MinorVersion;
312  }
313 
314  if (Fields[4] && *Fields[4])
315  {
316  DWORD CurrentProductType;
317  CurrentProductType = strtoulW(Fields[4], NULL, 0);
318  if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
319  (errno == ERANGE || errno == EINVAL))
320  {
321  TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
322  goto cleanup;
323  }
324  if (CurrentProductType != ProductType)
325  {
326  TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
327  CurrentProductType, ProductType);
328  goto cleanup;
329  }
330  }
331  else
332  *ScoreProductType = 1;
333 
334  if (Fields[5] && *Fields[5])
335  {
336  DWORD CurrentSuiteMask;
337  CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
338  if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
339  (errno == ERANGE || errno == EINVAL))
340  {
341  TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
342  goto cleanup;
343  }
344  if ((CurrentSuiteMask & ~SuiteMask) != 0)
345  {
346  TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
347  CurrentSuiteMask, SuiteMask);
348  goto cleanup;
349  }
350  *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
351  }
352  else
353  *ScoreSuiteMask = SuiteMask;
354 
355  ret = TRUE;
356 
357 cleanup:
358  MyFree(Section);
359  return ret;
360 }
361 
362 static BOOL
364  IN LPCWSTR SectionName,
365  IN PVOID Context)
366 {
368  DWORD Score1, Score2, Score3, Score4, Score5;
369  BOOL ret;
370 
371  if (SectionName[info->PrefixLength] != '.')
372  return TRUE;
373 
375  &SectionName[info->PrefixLength],
376  info->PlatformInfo,
377  info->ProductType,
378  info->SuiteMask,
379  &Score1, &Score2, &Score3, &Score4, &Score5);
380  if (!ret)
381  {
382  TRACE("Section %s not compatible\n", debugstr_w(SectionName));
383  return TRUE;
384  }
385  if (Score1 > info->BestScore1) goto done;
386  if (Score1 < info->BestScore1) goto bettersection;
387  if (Score2 > info->BestScore2) goto done;
388  if (Score2 < info->BestScore2) goto bettersection;
389  if (Score3 > info->BestScore3) goto done;
390  if (Score3 < info->BestScore3) goto bettersection;
391  if (Score4 > info->BestScore4) goto done;
392  if (Score4 < info->BestScore4) goto bettersection;
393  if (Score5 > info->BestScore5) goto done;
394  if (Score5 < info->BestScore5) goto bettersection;
395  goto done;
396 
397 bettersection:
398  strcpyW(info->BestSection, SectionName);
399  info->BestScore1 = Score1;
400  info->BestScore2 = Score2;
401  info->BestScore3 = Score3;
402  info->BestScore4 = Score4;
403  info->BestScore5 = Score5;
404 
405 done:
406  return TRUE;
407 }
408 
409 /***********************************************************************
410  * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
411  */
412 BOOL WINAPI
414  IN HINF InfHandle,
415  IN PCWSTR InfSectionName,
416  IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
417  OUT PWSTR InfSectionWithExt OPTIONAL,
418  IN DWORD InfSectionWithExtSize,
421  IN PVOID Reserved)
422 {
423  BOOL ret = FALSE;
424 
425  TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
426  AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
428 
429  if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
431  else if (!InfSectionName)
433  else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
435  else if (Reserved != NULL)
437  else
438  {
439  static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
440  static BYTE CurrentProductType = 0;
441  static WORD CurrentSuiteMask = 0;
442  PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
443  struct GetSectionCallbackInfo CallbackInfo;
444  DWORD dwFullLength;
446  WORD SuiteMask;
447 
448  /* Fill platform info if needed */
449  if (AlternatePlatformInfo)
450  {
451  pPlatformInfo = AlternatePlatformInfo;
452  ProductType = 0;
453  SuiteMask = 0;
454  }
455  else
456  {
457  if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
458  {
459  /* That's the first time we go here. We need to fill in the structure */
460  SYSTEM_INFO SystemInfo;
461  GetSystemInfo(&SystemInfo);
462  CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
463  CurrentPlatform.Platform = OsVersionInfo.dwPlatformId;
464  CurrentPlatform.MajorVersion = OsVersionInfo.dwMajorVersion;
465  CurrentPlatform.MinorVersion = OsVersionInfo.dwMinorVersion;
466  CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
467  CurrentPlatform.Reserved = 0;
468  CurrentProductType = OsVersionInfo.wProductType;
469  CurrentSuiteMask = OsVersionInfo.wSuiteMask;
470  }
471  ProductType = CurrentProductType;
472  SuiteMask = CurrentSuiteMask;
473  }
474 
475  CallbackInfo.PlatformInfo = pPlatformInfo;
476  CallbackInfo.ProductType = ProductType;
477  CallbackInfo.SuiteMask = SuiteMask;
478  CallbackInfo.PrefixLength = strlenW(InfSectionName);
479  CallbackInfo.BestScore1 = ULONG_MAX;
480  CallbackInfo.BestScore2 = ULONG_MAX;
481  CallbackInfo.BestScore3 = ULONG_MAX;
482  CallbackInfo.BestScore4 = ULONG_MAX;
483  CallbackInfo.BestScore5 = ULONG_MAX;
484  strcpyW(CallbackInfo.BestSection, InfSectionName);
485  TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName);
487  InfHandle,
488  InfSectionName,
490  &CallbackInfo))
491  {
493  goto done;
494  }
495  TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo.BestSection);
496 
497  dwFullLength = lstrlenW(CallbackInfo.BestSection);
498  if (RequiredSize != NULL)
499  *RequiredSize = dwFullLength + 1;
500 
501  if (InfSectionWithExtSize > 0)
502  {
503  if (InfSectionWithExtSize < dwFullLength + 1)
504  {
506  goto done;
507  }
508  strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
509  if (Extension)
510  {
511  DWORD dwLength = lstrlenW(InfSectionName);
512  *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
513  }
514  }
515 
516  ret = TRUE;
517  }
518 
519 done:
520  TRACE("Returning %d\n", ret);
521  return ret;
522 }
523 
524 
525 BOOL
527  IN struct DeviceInfoSet *list,
528  IN LPCWSTR InstancePath,
529  IN LPCGUID pClassGuid,
530  OUT struct DeviceInfo **pDeviceInfo)
531 {
532  DWORD size;
533  CONFIGRET cr;
534  struct DeviceInfo *deviceInfo;
535 
536  *pDeviceInfo = NULL;
537 
538  size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
539  deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
540  if (!deviceInfo)
541  {
543  return FALSE;
544  }
545  ZeroMemory(deviceInfo, size);
546 
547  cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
548  if (cr != CR_SUCCESS)
549  {
551  return FALSE;
552  }
553 
554  deviceInfo->set = list;
555  deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
556  strcpyW(deviceInfo->Data, InstancePath);
557  deviceInfo->instanceId = deviceInfo->Data;
558  deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
559  deviceInfo->DeviceDescription = NULL;
560  memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
561  deviceInfo->CreationFlags = 0;
562  InitializeListHead(&deviceInfo->DriverListHead);
564 
565  *pDeviceInfo = deviceInfo;
566  return TRUE;
567 }
568 
569 
570 static BOOL
572 {
573  HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
574  HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
575  return TRUE;
576 }
577 
578 static BOOL
579 DestroyDeviceInfo(struct DeviceInfo *deviceInfo)
580 {
582  struct DriverInfoElement *driverInfo;
583  struct DeviceInterface *deviceInterface;
584 
585  while (!IsListEmpty(&deviceInfo->DriverListHead))
586  {
587  ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
589  if (!DestroyDriverInfoElement(driverInfo))
590  return FALSE;
591  }
592  while (!IsListEmpty(&deviceInfo->InterfaceListHead))
593  {
595  deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
596  if (!DestroyDeviceInterface(deviceInterface))
597  return FALSE;
598  }
600  if (deviceInfo->hmodDevicePropPageProvider)
602  return HeapFree(GetProcessHeap(), 0, deviceInfo);
603 }
604 
605 static BOOL
607 {
609  struct DeviceInfo *deviceInfo;
610 
611  while (!IsListEmpty(&list->ListHead))
612  {
613  ListEntry = RemoveHeadList(&list->ListHead);
614  deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry);
615  if (!DestroyDeviceInfo(deviceInfo))
616  return FALSE;
617  }
618  if (list->HKLM != HKEY_LOCAL_MACHINE)
619  RegCloseKey(list->HKLM);
620  CM_Disconnect_Machine(list->hMachine);
621  DestroyClassInstallParams(&list->ClassInstallParams);
622  if (list->hmodClassPropPageProvider)
623  FreeLibrary(list->hmodClassPropPageProvider);
624  return HeapFree(GetProcessHeap(), 0, list);
625 }
626 
627 /***********************************************************************
628  * SetupDiBuildClassInfoList (SETUPAPI.@)
629  *
630  * Returns a list of setup class GUIDs that identify the classes
631  * that are installed on a local machine.
632  *
633  * PARAMS
634  * Flags [I] control exclusion of classes from the list.
635  * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
636  * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
637  * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
638  *
639  * RETURNS
640  * Success: TRUE.
641  * Failure: FALSE.
642  */
644  DWORD Flags,
645  LPGUID ClassGuidList,
648 {
649  TRACE("\n");
650  return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
652  NULL, NULL);
653 }
654 
655 /***********************************************************************
656  * SetupDiBuildClassInfoListExA (SETUPAPI.@)
657  *
658  * Returns a list of setup class GUIDs that identify the classes
659  * that are installed on a local or remote machine.
660  *
661  * PARAMS
662  * Flags [I] control exclusion of classes from the list.
663  * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
664  * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
665  * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
666  * MachineName [I] name of a remote machine.
667  * Reserved [I] must be NULL.
668  *
669  * RETURNS
670  * Success: TRUE.
671  * Failure: FALSE.
672  */
674  DWORD Flags,
675  LPGUID ClassGuidList,
679  PVOID Reserved)
680 {
681  LPWSTR MachineNameW = NULL;
682  BOOL bResult;
683 
684  TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
686 
687  if (MachineName)
688  {
690  if (MachineNameW == NULL) return FALSE;
691  }
692 
693  bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
695  MachineNameW, Reserved);
696 
697  MyFree(MachineNameW);
698 
699  return bResult;
700 }
701 
702 /***********************************************************************
703  * SetupDiBuildClassInfoListExW (SETUPAPI.@)
704  *
705  * Returns a list of setup class GUIDs that identify the classes
706  * that are installed on a local or remote machine.
707  *
708  * PARAMS
709  * Flags [I] control exclusion of classes from the list.
710  * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
711  * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
712  * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
713  * MachineName [I] name of a remote machine.
714  * Reserved [I] must be NULL.
715  *
716  * RETURNS
717  * Success: TRUE.
718  * Failure: FALSE.
719  */
721  DWORD Flags,
722  LPGUID ClassGuidList,
726  PVOID Reserved)
727 {
728  WCHAR szKeyName[40];
729  HKEY hClassesKey = INVALID_HANDLE_VALUE;
730  HKEY hClassKey;
731  DWORD dwLength;
732  DWORD dwIndex;
733  LONG lError;
734  DWORD dwGuidListIndex = 0;
735 
736  TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
738 
739  if (!RequiredSize)
740  {
742  return FALSE;
743  }
744  else if (!ClassGuidList && ClassGuidListSize > 0)
745  {
747  return FALSE;
748  }
749 
750  hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
753  MachineName,
754  Reserved);
755  if (hClassesKey == INVALID_HANDLE_VALUE)
756  {
757  return FALSE;
758  }
759 
760  for (dwIndex = 0; ; dwIndex++)
761  {
762  dwLength = 40;
763  lError = RegEnumKeyExW(hClassesKey,
764  dwIndex,
765  szKeyName,
766  &dwLength,
767  NULL,
768  NULL,
769  NULL,
770  NULL);
771  TRACE("RegEnumKeyExW() returns %d\n", lError);
772  if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
773  {
774  TRACE("Key name: %s\n", debugstr_w(szKeyName));
775 
776  if (RegOpenKeyExW(hClassesKey,
777  szKeyName,
778  0,
780  &hClassKey))
781  {
782  RegCloseKey(hClassesKey);
783  return FALSE;
784  }
785 
788  NULL,
789  NULL,
790  NULL,
791  NULL))
792  {
793  TRACE("'NoUseClass' value found!\n");
795  continue;
796  }
797 
798  if ((Flags & DIBCI_NOINSTALLCLASS) &&
801  NULL,
802  NULL,
803  NULL,
804  NULL)))
805  {
806  TRACE("'NoInstallClass' value found!\n");
808  continue;
809  }
810 
811  if ((Flags & DIBCI_NODISPLAYCLASS) &&
814  NULL,
815  NULL,
816  NULL,
817  NULL)))
818  {
819  TRACE("'NoDisplayClass' value found!\n");
821  continue;
822  }
823 
825 
826  TRACE("Guid: %s\n", debugstr_w(szKeyName));
827  if (dwGuidListIndex < ClassGuidListSize)
828  {
829  if (szKeyName[0] == '{' && szKeyName[37] == '}')
830  {
831  szKeyName[37] = 0;
832  }
833  TRACE("Guid: %p\n", &szKeyName[1]);
834 
835  UuidFromStringW(&szKeyName[1],
836  &ClassGuidList[dwGuidListIndex]);
837  }
838 
839  dwGuidListIndex++;
840  }
841 
842  if (lError != ERROR_SUCCESS)
843  break;
844  }
845 
846  RegCloseKey(hClassesKey);
847 
848  if (RequiredSize != NULL)
849  *RequiredSize = dwGuidListIndex;
850 
851  if (ClassGuidListSize < dwGuidListIndex)
852  {
854  return FALSE;
855  }
856 
857  return TRUE;
858 }
859 
860 /***********************************************************************
861  * SetupDiClassGuidsFromNameA (SETUPAPI.@)
862  */
864  LPCSTR ClassName,
865  LPGUID ClassGuidList,
868 {
869  return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
871  NULL, NULL);
872 }
873 
874 /***********************************************************************
875  * SetupDiClassGuidsFromNameW (SETUPAPI.@)
876  */
878  LPCWSTR ClassName,
879  LPGUID ClassGuidList,
882 {
883  return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
885  NULL, NULL);
886 }
887 
888 /***********************************************************************
889  * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
890  */
892  LPCSTR ClassName,
893  LPGUID ClassGuidList,
897  PVOID Reserved)
898 {
899  LPWSTR ClassNameW = NULL;
900  LPWSTR MachineNameW = NULL;
901  BOOL bResult;
902 
903  TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList,
905 
906  if (!ClassName)
907  {
909  return FALSE;
910  }
911 
912  ClassNameW = pSetupMultiByteToUnicode(ClassName, CP_ACP);
913  if (ClassNameW == NULL)
914  return FALSE;
915 
916  if (MachineName)
917  {
919  if (MachineNameW == NULL)
920  {
921  MyFree(ClassNameW);
922  return FALSE;
923  }
924  }
925 
926  bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
928  MachineNameW, Reserved);
929 
930  MyFree(MachineNameW);
931  MyFree(ClassNameW);
932 
933  return bResult;
934 }
935 
936 /***********************************************************************
937  * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
938  */
940  LPCWSTR ClassName,
941  LPGUID ClassGuidList,
945  PVOID Reserved)
946 {
947  WCHAR szKeyName[40];
949  HKEY hClassesKey;
950  HKEY hClassKey;
951  DWORD dwLength;
952  DWORD dwIndex;
953  LONG lError;
954  DWORD dwGuidListIndex = 0;
955 
956  TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
958 
959  if (!ClassName || !RequiredSize)
960  {
962  return FALSE;
963  }
964  if (!ClassGuidList && ClassGuidListSize > 0)
965  {
967  return FALSE;
968  }
969  *RequiredSize = 0;
970 
971  hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
974  MachineName,
975  Reserved);
976  if (hClassesKey == INVALID_HANDLE_VALUE)
977  {
978  return FALSE;
979  }
980 
981  for (dwIndex = 0; ; dwIndex++)
982  {
983  dwLength = 40;
984  lError = RegEnumKeyExW(hClassesKey,
985  dwIndex,
986  szKeyName,
987  &dwLength,
988  NULL,
989  NULL,
990  NULL,
991  NULL);
992  TRACE("RegEnumKeyExW() returns %d\n", lError);
993  if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
994  {
995  TRACE("Key name: %p\n", szKeyName);
996 
997  if (RegOpenKeyExW(hClassesKey,
998  szKeyName,
999  0,
1001  &hClassKey))
1002  {
1003  RegCloseKey(hClassesKey);
1004  return FALSE;
1005  }
1006 
1007  dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR);
1010  NULL,
1011  NULL,
1013  &dwLength))
1014  {
1015  TRACE("Class name: %p\n", szClassName);
1016 
1017  if (strcmpiW(szClassName, ClassName) == 0)
1018  {
1019  TRACE("Found matching class name\n");
1020 
1021  TRACE("Guid: %p\n", szKeyName);
1022  if (dwGuidListIndex < ClassGuidListSize)
1023  {
1024  if (szKeyName[0] == '{' && szKeyName[37] == '}')
1025  {
1026  szKeyName[37] = 0;
1027  }
1028  TRACE("Guid: %p\n", &szKeyName[1]);
1029 
1030  UuidFromStringW(&szKeyName[1],
1031  &ClassGuidList[dwGuidListIndex]);
1032  }
1033 
1034  dwGuidListIndex++;
1035  }
1036  }
1037 
1039  }
1040 
1041  if (lError != ERROR_SUCCESS)
1042  break;
1043  }
1044 
1045  RegCloseKey(hClassesKey);
1046 
1047  if (RequiredSize != NULL)
1048  *RequiredSize = dwGuidListIndex;
1049 
1050  if (ClassGuidListSize < dwGuidListIndex)
1051  {
1053  return FALSE;
1054  }
1055 
1056  return TRUE;
1057 }
1058 
1059 /***********************************************************************
1060  * SetupDiClassNameFromGuidA (SETUPAPI.@)
1061  */
1063  const GUID* ClassGuid,
1064  PSTR ClassName,
1065  DWORD ClassNameSize,
1067 {
1068  return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
1069  ClassNameSize, RequiredSize,
1070  NULL, NULL);
1071 }
1072 
1073 /***********************************************************************
1074  * SetupDiClassNameFromGuidW (SETUPAPI.@)
1075  */
1077  const GUID* ClassGuid,
1078  PWSTR ClassName,
1079  DWORD ClassNameSize,
1081 {
1082  return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1083  ClassNameSize, RequiredSize,
1084  NULL, NULL);
1085 }
1086 
1087 /***********************************************************************
1088  * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1089  */
1091  const GUID* ClassGuid,
1092  PSTR ClassName,
1093  DWORD ClassNameSize,
1096  PVOID Reserved)
1097 {
1098  WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1099  LPWSTR MachineNameW = NULL;
1100  BOOL ret;
1101 
1102  if (MachineName)
1103  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1105  RequiredSize, MachineNameW, Reserved);
1106  if (ret)
1107  {
1108  int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1109  ClassNameSize, NULL, NULL);
1110  if (len == 0 || len > ClassNameSize)
1111  {
1113  ret = FALSE;
1114  }
1115  }
1116  MyFree(MachineNameW);
1117  return ret;
1118 }
1119 
1120 /***********************************************************************
1121  * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1122  */
1124  const GUID* ClassGuid,
1125  PWSTR ClassName,
1126  DWORD ClassNameSize,
1129  PVOID Reserved)
1130 {
1131  HKEY hKey;
1132  DWORD dwLength;
1133  DWORD dwRegType;
1134  LONG rc;
1135  PWSTR Buffer;
1136 
1137  TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
1138  ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
1139 
1140  /* Make sure there's a GUID */
1141  if (ClassGuid == NULL)
1142  {
1143  SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */
1144  return FALSE;
1145  }
1146 
1147  /* Make sure there's a real buffer when there's a size */
1148  if ((ClassNameSize > 0) && (ClassName == NULL))
1149  {
1150  SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */
1151  return FALSE;
1152  }
1153 
1154  /* Open the key for the GUID */
1156 
1157  if (hKey == INVALID_HANDLE_VALUE)
1158  return FALSE;
1159 
1160  /* Retrieve the class name data and close the key */
1161  rc = QueryRegistryValue(hKey, REGSTR_VAL_CLASS, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
1162  RegCloseKey(hKey);
1163 
1164  /* Make sure we got the data */
1165  if (rc != ERROR_SUCCESS)
1166  {
1167  SetLastError(rc);
1168  return FALSE;
1169  }
1170 
1171  /* Make sure the data is a string */
1172  if (dwRegType != REG_SZ)
1173  {
1174  MyFree(Buffer);
1176  return FALSE;
1177  }
1178 
1179  /* Determine the length of the class name */
1180  dwLength /= sizeof(WCHAR);
1181 
1182  if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
1183  /* Count the null-terminator */
1184  dwLength++;
1185 
1186  /* Inform the caller about the class name */
1187  if ((ClassName != NULL) && (dwLength <= ClassNameSize))
1188  {
1189  memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR));
1190  ClassName[dwLength - 1] = UNICODE_NULL;
1191  }
1192 
1193  /* Inform the caller about the required size */
1194  if (RequiredSize != NULL)
1196 
1197  /* Clean up the buffer */
1198  MyFree(Buffer);
1199 
1200  /* Make sure the buffer was large enough */
1201  if ((ClassName == NULL) || (dwLength > ClassNameSize))
1202  {
1204  return FALSE;
1205  }
1206 
1207  return TRUE;
1208 }
1209 
1210 /***********************************************************************
1211  * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1212  */
1215  HWND hwndParent)
1216 {
1218 }
1219 
1220 /***********************************************************************
1221  * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1222  */
1225  HWND hwndParent,
1227  PVOID Reserved)
1228 {
1229  LPWSTR MachineNameW = NULL;
1230  HDEVINFO hDevInfo;
1231 
1232  TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1234 
1235  if (MachineName)
1236  {
1237  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1238  if (MachineNameW == NULL)
1239  return INVALID_HANDLE_VALUE;
1240  }
1241 
1243  MachineNameW, Reserved);
1244 
1245  MyFree(MachineNameW);
1246 
1247  return hDevInfo;
1248 }
1249 
1250 /***********************************************************************
1251  * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1252  *
1253  * Create an empty DeviceInfoSet list.
1254  *
1255  * PARAMS
1256  * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1257  * with this list.
1258  * hwndParent [I] hwnd needed for interface related actions.
1259  * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1260  * local registry will be used.
1261  * Reserved [I] must be NULL
1262  *
1263  * RETURNS
1264  * Success: empty list.
1265  * Failure: INVALID_HANDLE_VALUE.
1266  */
1269  HWND hwndParent,
1271  PVOID Reserved)
1272 {
1273  struct DeviceInfoSet *list = NULL;
1275  DWORD rc;
1276  CONFIGRET cr;
1278 
1279  TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1281 
1282  if (MachineName != NULL)
1283  {
1285  if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
1286  {
1288  goto cleanup;
1289  }
1290  if(len > 0)
1291  size += (len + 3) * sizeof(WCHAR);
1292  else
1293  MachineName = NULL;
1294  }
1295 
1296  if (Reserved != NULL)
1297  {
1299  return INVALID_HANDLE_VALUE;
1300  }
1301 
1302  list = MyMalloc(size);
1303  if (!list)
1304  {
1306  return INVALID_HANDLE_VALUE;
1307  }
1309 
1311  memcpy(&list->ClassGuid,
1313  sizeof(list->ClassGuid));
1314  list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1315  list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
1316  list->InstallParams.hwndParent = hwndParent;
1317  if (MachineName)
1318  {
1320  if (rc != ERROR_SUCCESS)
1321  {
1323  goto cleanup;
1324  }
1325 
1326  list->szData[0] = list->szData[1] = '\\';
1327  strcpyW(list->szData + 2, MachineName);
1328  list->MachineName = list->szData;
1329  }
1330  else
1331  {
1332  list->HKLM = HKEY_LOCAL_MACHINE;
1333  list->MachineName = NULL;
1334  }
1335  cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
1336  if (cr != CR_SUCCESS)
1337  {
1339  goto cleanup;
1340  }
1341  InitializeListHead(&list->DriverListHead);
1342  InitializeListHead(&list->ListHead);
1343 
1344  return (HDEVINFO)list;
1345 
1346 cleanup:
1347  if (ret == INVALID_HANDLE_VALUE)
1348  {
1349  if (list)
1350  {
1351  if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
1352  RegCloseKey(list->HKLM);
1353  MyFree(list);
1354  }
1355  }
1356  return ret;
1357 }
1358 
1359 /***********************************************************************
1360  * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1361  */
1365  DWORD Scope,
1366  DWORD HwProfile,
1367  DWORD KeyType,
1368  HINF InfHandle,
1369  PCSTR InfSectionName)
1370 {
1371  PWSTR InfSectionNameW = NULL;
1372  HKEY key;
1373 
1374  TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1375  HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1376 
1377  if (InfHandle)
1378  {
1379  if (!InfSectionName)
1380  {
1382  return INVALID_HANDLE_VALUE;
1383  }
1384  else
1385  {
1386  InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
1387  if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1388  }
1389  }
1391  HwProfile, KeyType, InfHandle, InfSectionNameW);
1392  MyFree(InfSectionNameW);
1393  return key;
1394 }
1395 
1396 static HKEY
1398  IN HKEY HKLM,
1399  IN DWORD HwProfile,
1400  IN DWORD samDesired);
1401 
1402 /***********************************************************************
1403  * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1404  */
1408  DWORD Scope,
1409  DWORD HwProfile,
1410  DWORD KeyType,
1411  HINF InfHandle,
1412  PCWSTR InfSectionName)
1413 {
1414  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1415  struct DeviceInfo *deviceInfo;
1417  DWORD rc;
1418  HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
1419  HKEY hKey = NULL;
1420  HKEY RootKey;
1421 
1422  TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1423  HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1424 
1426  {
1428  return INVALID_HANDLE_VALUE;
1429  }
1430  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1431  {
1433  return INVALID_HANDLE_VALUE;
1434  }
1436  || !DeviceInfoData->Reserved)
1437  {
1439  return INVALID_HANDLE_VALUE;
1440  }
1441  if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1442  {
1444  return INVALID_HANDLE_VALUE;
1445  }
1446  if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1447  {
1449  return INVALID_HANDLE_VALUE;
1450  }
1451  if (InfHandle && !InfSectionName)
1452  {
1454  return INVALID_HANDLE_VALUE;
1455  }
1456  if (!InfHandle && InfSectionName)
1457  {
1459  return INVALID_HANDLE_VALUE;
1460  }
1461 
1462  deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1463 
1464  if (Scope == DICS_FLAG_GLOBAL)
1465  RootKey = set->HKLM;
1466  else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1467  {
1468  hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
1469  if (hHWProfileKey == INVALID_HANDLE_VALUE)
1470  goto cleanup;
1471  RootKey = hHWProfileKey;
1472  }
1473 
1474  if (KeyType == DIREG_DEV)
1475  {
1476 #if _WIN32_WINNT >= 0x502
1477  hKey = SETUPDI_CreateDevKey(RootKey, deviceInfo, KEY_READ | KEY_WRITE);
1478 #else
1479  hKey = SETUPDI_CreateDevKey(RootKey, deviceInfo, KEY_ALL_ACCESS);
1480 #endif
1481  if (hKey == INVALID_HANDLE_VALUE)
1482  goto cleanup;
1483 
1484  if (Scope == DICS_FLAG_GLOBAL)
1485  {
1486  HKEY hTempKey = hKey;
1487 
1488  rc = RegCreateKeyExW(hTempKey,
1489  L"Device Parameters",
1490  0,
1491  NULL,
1493 #if _WIN32_WINNT >= 0x502
1494  KEY_READ | KEY_WRITE,
1495 #else
1497 #endif
1498  NULL,
1499  &hKey,
1500  NULL);
1501  if (rc == ERROR_SUCCESS)
1502  RegCloseKey(hTempKey);
1503  }
1504  }
1505  else /* KeyType == DIREG_DRV */
1506  {
1507 #if _WIN32_WINNT >= 0x502
1509 #else
1511 #endif
1512  if (hKey == INVALID_HANDLE_VALUE)
1513  goto cleanup;
1514  }
1515 
1516  /* Do installation of the specified section */
1517  if (InfHandle)
1518  {
1519  FIXME("Need to install section %s in file %p\n",
1520  debugstr_w(InfSectionName), InfHandle);
1521  }
1522  key = hKey;
1523 
1524 cleanup:
1525  if (hHWProfileKey != INVALID_HANDLE_VALUE)
1526  RegCloseKey(hHWProfileKey);
1527  if (hKey != NULL && hKey != key)
1528  RegCloseKey(hKey);
1529 
1530  TRACE("Returning 0x%p\n", key);
1531  return key;
1532 }
1533 
1534 /***********************************************************************
1535  * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1536  */
1539  PCSTR DeviceName,
1540  CONST GUID *ClassGuid,
1542  HWND hwndParent,
1545 {
1546  BOOL ret;
1547  LPWSTR DeviceNameW = NULL;
1548  LPWSTR DeviceDescriptionW = NULL;
1549 
1550  TRACE("\n");
1551 
1552  if (DeviceName)
1553  {
1554  DeviceNameW = pSetupMultiByteToUnicode(DeviceName, CP_ACP);
1555  if (DeviceNameW == NULL) return FALSE;
1556  }
1557  if (DeviceDescription)
1558  {
1559  DeviceDescriptionW = pSetupMultiByteToUnicode(DeviceDescription, CP_ACP);
1560  if (DeviceDescriptionW == NULL)
1561  {
1562  MyFree(DeviceNameW);
1563  return FALSE;
1564  }
1565  }
1566 
1567  ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1569 
1570  MyFree(DeviceNameW);
1571  MyFree(DeviceDescriptionW);
1572 
1573  return ret;
1574 }
1575 
1576 /***********************************************************************
1577  * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1578  */
1582  CONST GUID *ClassGuid,
1584  HWND hwndParent,
1587 {
1588  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1589  struct DeviceInfo *deviceInfo = NULL;
1590  BOOL ret = FALSE;
1591  CONFIGRET cr;
1592  DEVINST RootDevInst;
1593  DEVINST DevInst;
1594  WCHAR GenInstanceId[MAX_DEVICE_ID_LEN];
1595 
1596  TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1599 
1600  if (!DeviceName)
1601  {
1603  return FALSE;
1604  }
1606  {
1608  return FALSE;
1609  }
1610  if (!ClassGuid)
1611  {
1613  return FALSE;
1614  }
1615  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1616  {
1618  return FALSE;
1619  }
1620  if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1621  !IsEqualGUID(ClassGuid, &set->ClassGuid))
1622  {
1624  return FALSE;
1625  }
1627  {
1628  TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
1630  return FALSE;
1631  }
1632 
1633  /* Get the root device instance */
1634  cr = CM_Locate_DevInst_ExW(&RootDevInst,
1635  NULL,
1637  set->hMachine);
1638  if (cr != CR_SUCCESS)
1639  {
1641  return FALSE;
1642  }
1643 
1644  /* Create the new device instance */
1645  cr = CM_Create_DevInst_ExW(&DevInst,
1647  RootDevInst,
1650  set->hMachine);
1651  if (cr != CR_SUCCESS)
1652  {
1654  return FALSE;
1655  }
1656 
1658  {
1659  /* Grab the actual instance ID that was created */
1660  cr = CM_Get_Device_ID_Ex(DevInst,
1661  GenInstanceId,
1663  0,
1664  set->hMachine);
1665  if (cr != CR_SUCCESS)
1666  {
1668  return FALSE;
1669  }
1670 
1671  DeviceName = GenInstanceId;
1672  TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName));
1673  }
1674 
1675  if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
1676  {
1677  InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
1678 
1679  if (!DeviceInfoData)
1680  ret = TRUE;
1681  else
1682  {
1683  if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1684  {
1686  }
1687  else
1688  {
1690  DeviceInfoData->DevInst = deviceInfo->dnDevInst;
1691  DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
1692  ret = TRUE;
1693  }
1694  }
1695  }
1696 
1697  if (ret == FALSE)
1698  {
1699  if (deviceInfo != NULL)
1700  {
1701  /* Remove deviceInfo from List */
1702  RemoveEntryList(&deviceInfo->ListEntry);
1703 
1704  /* Destroy deviceInfo */
1705  DestroyDeviceInfo(deviceInfo);
1706  }
1707  }
1708 
1709  TRACE("Returning %d\n", ret);
1710  return ret;
1711 }
1712 
1713 /***********************************************************************
1714  * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1715  */
1719  DWORD Flags,
1720  PSP_DETSIG_CMPPROC CompareProc,
1721  PVOID CompareContext,
1722  PSP_DEVINFO_DATA DupDeviceInfoData)
1723 {
1724  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1725  WCHAR DevInstId[MAX_DEVICE_ID_LEN];
1726  DEVINST ParentDevInst;
1727  CONFIGRET cr;
1728  DWORD dwError = ERROR_SUCCESS;
1729 
1730  TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1731  CompareProc, CompareContext, DupDeviceInfoData);
1732 
1734  {
1736  return FALSE;
1737  }
1738  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1739  {
1741  return FALSE;
1742  }
1744  || !DeviceInfoData->Reserved)
1745  {
1747  return FALSE;
1748  }
1749 
1750  if (Flags & ~SPRDI_FIND_DUPS)
1751  {
1752  TRACE("Unknown flags: 0x%08lx\n", Flags & ~SPRDI_FIND_DUPS);
1754  return FALSE;
1755  }
1756 
1757  if (Flags & SPRDI_FIND_DUPS)
1758  {
1759  FIXME("Unimplemented codepath!\n");
1760  }
1761 
1763  DevInstId,
1765  0,
1766  set->hMachine);
1767 
1768  CM_Get_Parent_Ex(&ParentDevInst,
1770  0,
1771  set->hMachine);
1772 
1774  DevInstId,
1775  ParentDevInst,
1777  set->hMachine);
1778  if (cr != CR_SUCCESS &&
1780  {
1781  dwError = ERROR_NO_SUCH_DEVINST;
1782  }
1783 
1784  SetLastError(dwError);
1785 
1786  return (dwError == ERROR_SUCCESS);
1787 }
1788 
1789 /***********************************************************************
1790  * SetupDiEnumDeviceInfo (SETUPAPI.@)
1791  */
1793  HDEVINFO devinfo,
1794  DWORD index,
1796 {
1797  BOOL ret = FALSE;
1798 
1799  TRACE("%p %d %p\n", devinfo, index, info);
1800 
1801  if(info==NULL)
1802  {
1804  return FALSE;
1805  }
1806  if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1807  {
1808  struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1809  if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1810  {
1811  if (info->cbSize != sizeof(SP_DEVINFO_DATA))
1813  else
1814  {
1815  PLIST_ENTRY ItemList = list->ListHead.Flink;
1816  while (ItemList != &list->ListHead && index-- > 0)
1817  ItemList = ItemList->Flink;
1818  if (ItemList == &list->ListHead)
1820  else
1821  {
1822  struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
1823  memcpy(&info->ClassGuid,
1824  &DevInfo->ClassGuid,
1825  sizeof(GUID));
1826  info->DevInst = DevInfo->dnDevInst;
1827  info->Reserved = (ULONG_PTR)DevInfo;
1828  ret = TRUE;
1829  }
1830  }
1831  }
1832  else
1834  }
1835  else
1837  return ret;
1838 }
1839 
1840 /***********************************************************************
1841  * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1842  */
1846  PSTR DeviceInstanceId,
1847  DWORD DeviceInstanceIdSize,
1849 {
1850  BOOL ret = FALSE;
1851  DWORD size;
1852  PWSTR instanceId;
1853 
1854  TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1855  DeviceInstanceIdSize, RequiredSize);
1856 
1857  if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1858  {
1860  return FALSE;
1861  }
1862 
1865  NULL,
1866  0,
1867  &size);
1869  return FALSE;
1870  instanceId = MyMalloc(size * sizeof(WCHAR));
1871  if (instanceId)
1872  {
1875  instanceId,
1876  size,
1877  &size);
1878  if (ret)
1879  {
1880  int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1881  DeviceInstanceId,
1882  DeviceInstanceIdSize, NULL, NULL);
1883 
1884  if (!len)
1885  ret = FALSE;
1886  else
1887  {
1888  if (len > DeviceInstanceIdSize)
1889  {
1891  ret = FALSE;
1892  }
1893  if (RequiredSize)
1894  *RequiredSize = len;
1895  }
1896  }
1897  MyFree(instanceId);
1898  }
1899  else
1900  {
1901  if (RequiredSize)
1902  *RequiredSize = size;
1904  ret = FALSE;
1905  }
1906  return ret;
1907 }
1908 
1909 /***********************************************************************
1910  * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1911  */
1915  PWSTR DeviceInstanceId,
1916  DWORD DeviceInstanceIdSize,
1918 {
1919  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1920  struct DeviceInfo *devInfo;
1921 
1922  TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1923  DeviceInstanceIdSize, RequiredSize);
1924 
1926  {
1928  return FALSE;
1929  }
1930  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1931  {
1933  return FALSE;
1934  }
1936  || !DeviceInfoData->Reserved)
1937  {
1939  return FALSE;
1940  }
1941  devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1942  if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1943  {
1945  return FALSE;
1946  }
1947  if (DeviceInstanceId && DeviceInstanceIdSize == 0)
1948  {
1950  return FALSE;
1951  }
1952  TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1953  if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1954  {
1956  if (RequiredSize)
1957  *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1958  return FALSE;
1959  }
1960  lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1961  if (RequiredSize)
1962  *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1963  return TRUE;
1964 }
1965 
1966 /***********************************************************************
1967  * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1968  */
1970  HINF InfHandle,
1971  PCSTR InfSectionName,
1972  PSTR InfSectionWithExt,
1973  DWORD InfSectionWithExtSize,
1975  PSTR *Extension)
1976 {
1977  return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
1978  NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1979  Extension, NULL);
1980 }
1981 
1982 /***********************************************************************
1983  * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1984  */
1986  HINF InfHandle,
1987  PCWSTR InfSectionName,
1988  PWSTR InfSectionWithExt,
1989  DWORD InfSectionWithExtSize,
1991  PWSTR *Extension)
1992 {
1993  return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
1994  NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1995  Extension, NULL);
1996 }
1997 
1998 /***********************************************************************
1999  * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2000  */
2001 BOOL WINAPI
2003  IN HINF InfHandle,
2004  IN PCSTR InfSectionName,
2005  IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
2006  OUT PSTR InfSectionWithExt OPTIONAL,
2007  IN DWORD InfSectionWithExtSize,
2010  IN PVOID Reserved)
2011 {
2012  LPWSTR InfSectionNameW = NULL;
2013  LPWSTR InfSectionWithExtW = NULL;
2014  PWSTR ExtensionW;
2015  BOOL bResult = FALSE;
2016 
2017  TRACE("\n");
2018 
2019  if (InfSectionName)
2020  {
2021  InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2022  if (InfSectionNameW == NULL)
2023  goto cleanup;
2024  }
2025  if (InfSectionWithExt)
2026  {
2027  InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
2028  if (InfSectionWithExtW == NULL)
2029  goto cleanup;
2030  }
2031 
2033  InfHandle, InfSectionNameW, AlternatePlatformInfo,
2034  InfSectionWithExt ? InfSectionWithExtW : NULL,
2035  InfSectionWithExtSize,
2036  RequiredSize,
2037  Extension ? &ExtensionW : NULL,
2038  Reserved);
2039 
2040  if (bResult && InfSectionWithExt)
2041  {
2042  bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
2043  InfSectionWithExtSize, NULL, NULL) != 0;
2044  }
2045  if (bResult && Extension)
2046  {
2047  if (ExtensionW == NULL)
2048  *Extension = NULL;
2049  else
2050  *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
2051  }
2052 
2053 cleanup:
2054  MyFree(InfSectionNameW);
2055  MyFree(InfSectionWithExtW);
2056 
2057  return bResult;
2058 }
2059 
2060 /***********************************************************************
2061  * SetupDiGetClassDescriptionA (SETUPAPI.@)
2062  */
2064  const GUID* ClassGuid,
2065  PSTR ClassDescription,
2066  DWORD ClassDescriptionSize,
2068 {
2069  return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
2070  ClassDescriptionSize,
2071  RequiredSize, NULL, NULL);
2072 }
2073 
2074 /***********************************************************************
2075  * SetupDiGetClassDescriptionW (SETUPAPI.@)
2076  */
2078  const GUID* ClassGuid,
2079  PWSTR ClassDescription,
2080  DWORD ClassDescriptionSize,
2082 {
2083  return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
2084  ClassDescriptionSize,
2085  RequiredSize, NULL, NULL);
2086 }
2087 
2088 /***********************************************************************
2089  * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2090  */
2092  const GUID* ClassGuid,
2093  PSTR ClassDescription,
2094  DWORD ClassDescriptionSize,
2097  PVOID Reserved)
2098 {
2099  PWCHAR ClassDescriptionW = NULL;
2100  LPWSTR MachineNameW = NULL;
2101  BOOL ret = FALSE;
2102 
2103  TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2104  ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
2105 
2106  if (ClassDescriptionSize > 0)
2107  {
2108  ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
2109  if (!ClassDescriptionW)
2110  {
2112  goto cleanup;
2113  }
2114  }
2115 
2116  if (MachineName)
2117  {
2118  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
2119  if (!MachineNameW)
2120  {
2122  goto cleanup;
2123  }
2124  }
2125 
2126  ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
2127  ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
2128  if (ret)
2129  {
2130  DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
2131  ClassDescriptionSize, NULL, NULL);
2132  if (len == 0 || len > ClassDescriptionSize)
2133  {
2135  ret = FALSE;
2136  }
2137  }
2138 
2139 cleanup:
2140  MyFree(ClassDescriptionW);
2141  MyFree(MachineNameW);
2142  return ret;
2143 }
2144 
2145 /***********************************************************************
2146  * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2147  */
2149  const GUID* ClassGuid,
2150  PWSTR ClassDescription,
2151  DWORD ClassDescriptionSize,
2154  PVOID Reserved)
2155 {
2156  HKEY hKey;
2157  DWORD dwLength;
2158  DWORD dwRegType;
2159  LONG rc;
2160  PWSTR Buffer;
2161 
2162  TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2163  ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
2164 
2165  /* Make sure there's a GUID */
2166  if (!ClassGuid)
2167  {
2169  return FALSE;
2170  }
2171 
2172  /* Make sure there's a real buffer when there's a size */
2173  if (!ClassDescription && ClassDescriptionSize > 0)
2174  {
2176  return FALSE;
2177  }
2178 
2179  /* Open the key for the GUID */
2183  MachineName,
2184  Reserved);
2185  if (hKey == INVALID_HANDLE_VALUE)
2186  return FALSE;
2187 
2188  /* Retrieve the class description data and close the key */
2189  rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
2190  RegCloseKey(hKey);
2191 
2192  /* Make sure we got the data */
2193  if (rc != ERROR_SUCCESS)
2194  {
2195  SetLastError(rc);
2196  return FALSE;
2197  }
2198 
2199  /* Make sure the data is a string */
2200  if (dwRegType != REG_SZ)
2201  {
2202  MyFree(Buffer);
2204  return FALSE;
2205  }
2206 
2207  /* Determine the length of the class description */
2208  dwLength /= sizeof(WCHAR);
2209 
2210  /* Count the null-terminator if none is present */
2211  if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
2212  dwLength++;
2213 
2214  /* Inform the caller about the class description */
2215  if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize))
2216  {
2217  memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR));
2218  ClassDescription[dwLength - 1] = UNICODE_NULL;
2219  }
2220 
2221  /* Inform the caller about the required size */
2222  if (RequiredSize != NULL)
2224 
2225  /* Clean up the buffer */
2226  MyFree(Buffer);
2227 
2228  /* Make sure the buffer was large enough */
2229  if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize))
2230  {
2232  return FALSE;
2233  }
2234 
2235  return TRUE;
2236 }
2237 
2238 /***********************************************************************
2239  * SetupDiGetClassDevsA (SETUPAPI.@)
2240  */
2242  CONST GUID *class,
2243  LPCSTR enumstr,
2244  HWND parent,
2245  DWORD flags)
2246 {
2247  return SetupDiGetClassDevsExA(class, enumstr, parent,
2248  flags, NULL, NULL, NULL);
2249 }
2250 
2251 /***********************************************************************
2252  * SetupDiGetClassDevsExA (SETUPAPI.@)
2253  */
2255  const GUID *class,
2256  PCSTR enumstr,
2257  HWND parent,
2258  DWORD flags,
2259  HDEVINFO deviceset,
2260  PCSTR machine,
2261  PVOID reserved)
2262 {
2263  HDEVINFO ret;
2264  LPWSTR enumstrW = NULL, machineW = NULL;
2265 
2266  if (enumstr)
2267  {
2268  enumstrW = pSetupMultiByteToUnicode(enumstr, CP_ACP);
2269  if (!enumstrW)
2270  {
2272  goto end;
2273  }
2274  }
2275  if (machine)
2276  {
2278  if (!machineW)
2279  {
2280  MyFree(enumstrW);
2282  goto end;
2283  }
2284  }
2285  ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
2286  machineW, reserved);
2287  MyFree(enumstrW);
2288  MyFree(machineW);
2289 
2290 end:
2291  return ret;
2292 }
2293 
2294 /***********************************************************************
2295  * SetupDiGetClassDevsW (SETUPAPI.@)
2296  */
2298  CONST GUID *class,
2299  LPCWSTR enumstr,
2300  HWND parent,
2301  DWORD flags)
2302 {
2303  return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2304  NULL);
2305 }
2306 
2307 /***********************************************************************
2308  * SetupDiGetClassDevsExW (SETUPAPI.@)
2309  */
2311  CONST GUID *class,
2312  PCWSTR enumstr,
2313  HWND parent,
2314  DWORD flags,
2315  HDEVINFO deviceset,
2316  PCWSTR machine,
2317  PVOID reserved)
2318 {
2319  HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2320  struct DeviceInfoSet *list;
2321  CONST GUID *pClassGuid;
2322  LONG rc;
2324 
2325  TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2326  debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2327  reserved);
2328 
2329  if (!(flags & DIGCF_ALLCLASSES) && !class)
2330  {
2332  return INVALID_HANDLE_VALUE;
2333  }
2334 
2335  /* Create the deviceset if not set */
2336  if (deviceset)
2337  {
2338  list = (struct DeviceInfoSet *)deviceset;
2339  if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2340  {
2342  goto cleanup;
2343  }
2344  hDeviceInfo = deviceset;
2345  }
2346  else
2347  {
2348  hDeviceInfo = SetupDiCreateDeviceInfoListExW(
2350  NULL, machine, NULL);
2351  if (hDeviceInfo == INVALID_HANDLE_VALUE)
2352  goto cleanup;
2353  list = (struct DeviceInfoSet *)hDeviceInfo;
2354  }
2355 
2356  if (flags & DIGCF_PROFILE)
2357  FIXME(": flag DIGCF_PROFILE ignored\n");
2358 
2360  {
2361  if (!class)
2362  {
2364  goto cleanup;
2365  }
2366  rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
2367  }
2368  else
2369  {
2370  /* Determine which class(es) should be included in the deviceset */
2371  if (flags & DIGCF_ALLCLASSES)
2372  {
2373  /* The caller wants all classes. Check if
2374  * the deviceset limits us to one class */
2375  if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2376  pClassGuid = NULL;
2377  else
2378  pClassGuid = &list->ClassGuid;
2379  }
2380  else if (class)
2381  {
2382  /* The caller wants one class. Check if it matches deviceset class */
2383  if (IsEqualIID(&list->ClassGuid, class)
2384  || IsEqualIID(&list->ClassGuid, &GUID_NULL))
2385  {
2386  pClassGuid = class;
2387  }
2388  else
2389  {
2391  goto cleanup;
2392  }
2393  }
2394  else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
2395  {
2396  /* No class specified. Try to use the one of the deviceset */
2397  if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2398  pClassGuid = &list->ClassGuid;
2399  else
2400  {
2402  goto cleanup;
2403  }
2404  }
2405  else
2406  {
2408  goto cleanup;
2409  }
2410  rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
2411  }
2412  if (rc != ERROR_SUCCESS)
2413  {
2414  SetLastError(rc);
2415  goto cleanup;
2416  }
2417  set = hDeviceInfo;
2418 
2419 cleanup:
2420  if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
2421  SetupDiDestroyDeviceInfoList(hDeviceInfo);
2422  return set;
2423 }
2424 
2425 /***********************************************************************
2426  * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2427  */
2430  PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2431 {
2432  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2433 
2434  TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2435 
2437  {
2439  return FALSE;
2440  }
2441  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2442  {
2444  return FALSE;
2445  }
2446  if (!DevInfoData ||
2447  DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2448  {
2450  return FALSE;
2451  }
2452  memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2453  DevInfoData->RemoteMachineHandle = set->hMachine;
2454  if (set->MachineName)
2455  {
2456  FIXME("Stub\n");
2458  return FALSE;
2459  }
2460  else
2461  DevInfoData->RemoteMachineName[0] = 0;
2462 
2463  return TRUE;
2464 }
2465 
2466 /***********************************************************************
2467  * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2468  */
2471  PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2472 {
2473  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2474 
2475  TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2476 
2478  {
2480  return FALSE;
2481  }
2482  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2483  {
2485  return FALSE;
2486  }
2487  if (!DevInfoData ||
2488  DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2489  {
2491  return FALSE;
2492  }
2493  memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2494  DevInfoData->RemoteMachineHandle = set->hMachine;
2495  if (set->MachineName)
2496  strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
2497  else
2498  DevInfoData->RemoteMachineName[0] = 0;
2499 
2500  return TRUE;
2501 }
2502 
2503 /***********************************************************************
2504  * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2505  */
2509  const GUID *InterfaceClassGuid,
2511  DWORD CreationFlags,
2512  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2513 {
2514  BOOL ret;
2515  LPWSTR ReferenceStringW = NULL;
2516 
2517  TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2519  CreationFlags, DeviceInterfaceData);
2520 
2521  if (ReferenceString)
2522  {
2523  ReferenceStringW = pSetupMultiByteToUnicode(ReferenceString, CP_ACP);
2524  if (ReferenceStringW == NULL) return FALSE;
2525  }
2526 
2528  InterfaceClassGuid, ReferenceStringW, CreationFlags,
2529  DeviceInterfaceData);
2530 
2531  MyFree(ReferenceStringW);
2532 
2533  return ret;
2534 }
2535 
2536 /***********************************************************************
2537  * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2538  */
2542  const GUID *InterfaceClassGuid,
2544  DWORD CreationFlags,
2545  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2546 {
2547  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2548  TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2550  CreationFlags, DeviceInterfaceData);
2551 
2553  {
2555  return FALSE;
2556  }
2557  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2558  {
2560  return FALSE;
2561  }
2563  || !DeviceInfoData->Reserved)
2564  {
2566  return FALSE;
2567  }
2568  if (!InterfaceClassGuid)
2569  {
2571  return FALSE;
2572  }
2573 
2574  FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2576  CreationFlags, DeviceInterfaceData);
2578  return FALSE;
2579 }
2580 
2581 /***********************************************************************
2582  * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2583  */
2586  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2587  DWORD Reserved,
2588  REGSAM samDesired,
2589  HINF InfHandle,
2590  PCSTR InfSectionName)
2591 {
2592  HKEY key;
2593  PWSTR InfSectionNameW = NULL;
2594 
2595  TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2596  samDesired, InfHandle, InfSectionName);
2597  if (InfHandle)
2598  {
2599  if (!InfSectionName)
2600  {
2602  return INVALID_HANDLE_VALUE;
2603  }
2604  InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2605  if (!InfSectionNameW)
2606  return INVALID_HANDLE_VALUE;
2607  }
2609  DeviceInterfaceData, Reserved, samDesired, InfHandle,
2610  InfSectionNameW);
2611  MyFree(InfSectionNameW);
2612  return key;
2613 }
2614 
2615 /***********************************************************************
2616  * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2617  */
2620  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2621  DWORD Reserved,
2622  REGSAM samDesired,
2623  HINF InfHandle,
2624  PCWSTR InfSectionName)
2625 {
2626  HKEY hKey, hDevKey;
2628  DWORD Length, Index;
2629  LONG rc;
2630  WCHAR bracedGuidString[39];
2631  struct DeviceInterface *DevItf;
2632  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2633 
2634  TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2635  samDesired, InfHandle, InfSectionName);
2636 
2638  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2639  {
2641  return INVALID_HANDLE_VALUE;
2642  }
2643  if (!DeviceInterfaceData ||
2644  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2645  !DeviceInterfaceData->Reserved)
2646  {
2648  return INVALID_HANDLE_VALUE;
2649  }
2650  if (InfHandle && !InfSectionName)
2651  {
2653  return INVALID_HANDLE_VALUE;
2654  }
2655 
2656  hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL);
2657  if (hKey == INVALID_HANDLE_VALUE)
2658  {
2659  hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL);
2660  if (hKey == INVALID_HANDLE_VALUE)
2661  {
2663  return INVALID_HANDLE_VALUE;
2664  }
2665  SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString);
2666 
2667  if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS)
2668  {
2670  return INVALID_HANDLE_VALUE;
2671  }
2672  RegCloseKey(hKey);
2673  hKey = hDevKey;
2674  }
2675 
2676  DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2677 
2678  Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR);
2680  if (!SymbolicLink)
2681  {
2682  RegCloseKey(hKey);
2684  return INVALID_HANDLE_VALUE;
2685  }
2686 
2687  wcscpy(SymbolicLink, DevItf->SymbolicLink);
2688 
2689  Index = 0;
2690  while(SymbolicLink[Index])
2691  {
2692  if (SymbolicLink[Index] == L'\\')
2693  {
2694  SymbolicLink[Index] = L'#';
2695  }
2696  Index++;
2697  }
2698 
2699  rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL);
2700 
2701  RegCloseKey(hKey);
2703 
2704  if (rc == ERROR_SUCCESS)
2705  {
2706  if (InfHandle && InfSectionName)
2707  {
2708  if (!SetupInstallFromInfSection(NULL /*FIXME */,
2709  InfHandle,
2710  InfSectionName,
2712  hDevKey,
2713  NULL,
2714  0,
2715  set->SelectedDevice->InstallParams.InstallMsgHandler,
2716  set->SelectedDevice->InstallParams.InstallMsgHandlerContext,
2718  NULL))
2719  {
2720  RegCloseKey(hDevKey);
2721  return INVALID_HANDLE_VALUE;
2722  }
2723  }
2724  }
2725 
2726  SetLastError(rc);
2727  return hDevKey;
2728 }
2729 
2730 /***********************************************************************
2731  * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2732  */
2735  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2736  DWORD Reserved)
2737 {
2738  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2739  BOOL ret = FALSE;
2740 
2741  TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2742 
2744  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2745  {
2747  return FALSE;
2748  }
2749  if (!DeviceInterfaceData ||
2750  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2751  !DeviceInterfaceData->Reserved)
2752  {
2754  return FALSE;
2755  }
2756 
2757  FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2759  return ret;
2760 }
2761 
2762 /***********************************************************************
2763  * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2764  *
2765  * PARAMS
2766  * DeviceInfoSet [I] Set of devices from which to enumerate
2767  * interfaces
2768  * DeviceInfoData [I] (Optional) If specified, a specific device
2769  * instance from which to enumerate interfaces.
2770  * If it isn't specified, all interfaces for all
2771  * devices in the set are enumerated.
2772  * InterfaceClassGuid [I] The interface class to enumerate.
2773  * MemberIndex [I] An index of the interface instance to enumerate.
2774  * A caller should start with MemberIndex set to 0,
2775  * and continue until the function fails with
2776  * ERROR_NO_MORE_ITEMS.
2777  * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2778  * member must be set to
2779  * sizeof(SP_DEVICE_INTERFACE_DATA).
2780  *
2781  * RETURNS
2782  * Success: non-zero value.
2783  * Failure: FALSE. Call GetLastError() for more info.
2784  */
2789  DWORD MemberIndex,
2790  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2791 {
2792  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2793  BOOL ret = FALSE;
2794 
2795  TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2796  debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2797 
2799  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2800  {
2802  return FALSE;
2803  }
2804  if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2806  {
2808  return FALSE;
2809  }
2810  if (!DeviceInterfaceData ||
2811  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2812  {
2814  return FALSE;
2815  }
2816  if (DeviceInfoData)
2817  {
2818  struct DeviceInfo *devInfo =
2819  (struct DeviceInfo *)DeviceInfoData->Reserved;
2820  BOOL found = FALSE;
2821  PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2822  while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2823  {
2824  struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2826  {
2827  InterfaceListEntry = InterfaceListEntry->Flink;
2828  continue;
2829  }
2830  if (MemberIndex-- == 0)
2831  {
2832  /* return this item */
2833  memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2834  &DevItf->InterfaceClassGuid,
2835  sizeof(GUID));
2836  DeviceInterfaceData->Flags = DevItf->Flags;
2837  DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2838  found = TRUE;
2839  ret = TRUE;
2840  }
2841  InterfaceListEntry = InterfaceListEntry->Flink;
2842  }
2843  if (!found)
2845  }
2846  else
2847  {
2848  BOOL found = FALSE;
2849  PLIST_ENTRY ItemList = set->ListHead.Flink;
2850  while (ItemList != &set->ListHead && !found)
2851  {
2852  PLIST_ENTRY InterfaceListEntry;
2853  struct DeviceInfo *devInfo =
2854  CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
2855  InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2856  while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2857  {
2858  struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2860  {
2861  InterfaceListEntry = InterfaceListEntry->Flink;
2862  continue;
2863  }
2864  if (MemberIndex-- == 0)
2865  {
2866  /* return this item */
2867  memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2868  &DevItf->InterfaceClassGuid,
2869  sizeof(GUID));
2870  DeviceInterfaceData->Flags = DevItf->Flags;
2871  DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2872  found = TRUE;
2873  ret = TRUE;
2874  }
2875  InterfaceListEntry = InterfaceListEntry->Flink;
2876  }
2877  ItemList = ItemList->Flink;
2878 
2879  }
2880  if (!found)
2882  }
2883  return ret;
2884 }
2885 
2886 /***********************************************************************
2887  * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2888  *
2889  * Destroy a DeviceInfoList and free all used memory of the list.
2890  *
2891  * PARAMS
2892  * devinfo [I] DeviceInfoList pointer to list to destroy
2893  *
2894  * RETURNS
2895  * Success: non zero value.
2896  * Failure: zero value.
2897  */
2899 {
2900  BOOL ret = FALSE;
2901 
2902  TRACE("%p\n", devinfo);
2903  if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2904  {
2905  struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2906 
2907  if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2908  {
2910  }
2911  }
2912 
2913  if (ret == FALSE)
2915 
2916  return ret;
2917 }
2918 
2919 /***********************************************************************
2920  * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2921  */
2924  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2925  PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2926  DWORD DeviceInterfaceDetailDataSize,
2929 {
2930  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2931  PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2932  DWORD sizeW = 0, bytesNeeded;
2933  BOOL ret = FALSE;
2934 
2935  TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2936  DeviceInterfaceData, DeviceInterfaceDetailData,
2937  DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2938 
2940  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2941  {
2943  return FALSE;
2944  }
2945  if (!DeviceInterfaceData ||
2946  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2947  !DeviceInterfaceData->Reserved)
2948  {
2950  return FALSE;
2951  }
2952  if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2953  {
2955  return FALSE;
2956  }
2957 
2958  if((DeviceInterfaceDetailDataSize != 0) &&
2959  (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(CHAR))))
2960  {
2962  return FALSE;
2963  }
2964 
2965  if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2966  {
2968  return FALSE;
2969  }
2970 
2971 
2972  if (DeviceInterfaceDetailData != NULL)
2973  {
2975  + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2976  DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
2977  if (!DeviceInterfaceDetailDataW)
2978  {
2980  }
2981  DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2982  }
2983  if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2984  {
2986  DeviceInfoSet,
2987  DeviceInterfaceData,
2988  DeviceInterfaceDetailDataW,
2989  sizeW,
2990  &sizeW,
2991  DeviceInfoData);
2992  bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2994  if (RequiredSize)
2995  *RequiredSize = bytesNeeded;
2996  if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize >= bytesNeeded)
2997  {
2998  if (!WideCharToMultiByte(
2999  CP_ACP, 0,
3000  DeviceInterfaceDetailDataW->DevicePath, -1,
3001  DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
3002  NULL, NULL))
3003  {
3004  ret = FALSE;
3005  }
3006  }
3007  }
3008  MyFree(DeviceInterfaceDetailDataW);
3009 
3010  return ret;
3011 }
3012 
3013 /***********************************************************************
3014  * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3015  */
3018  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
3019  PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
3020  DWORD DeviceInterfaceDetailDataSize,
3023 {
3024  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3025  BOOL ret = FALSE;
3026 
3027  TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3028  DeviceInterfaceData, DeviceInterfaceDetailData,
3029  DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3030 
3032  set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3033  {
3035  return FALSE;
3036  }
3037  if (!DeviceInterfaceData ||
3038  DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3039  !DeviceInterfaceData->Reserved)
3040  {
3042  return FALSE;
3043  }
3044  if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
3045  {
3047  return FALSE;
3048  }
3049  if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3050  {
3052  return FALSE;
3053  }
3055  {
3057  return FALSE;
3058  }
3059  if ((DeviceInterfaceDetailData != NULL)
3060  && (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) + sizeof(WCHAR)))
3061  {
3063  return FALSE;
3064  }
3065  else
3066  {
3067  struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
3068  LPCWSTR devName = deviceInterface->SymbolicLink;
3069  DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
3070  (lstrlenW(devName) + 1) * sizeof(WCHAR);
3071 
3072  if (sizeRequired > DeviceInterfaceDetailDataSize)
3073  {
3075  if (RequiredSize)
3076  *RequiredSize = sizeRequired;
3077  }
3078  else
3079  {
3080  strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
3081  TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
3082  if (DeviceInfoData)
3083  {
3085  &deviceInterface->DeviceInfo->ClassGuid,
3086  sizeof(GUID));
3087  DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
3088  DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
3089  }
3090  ret = TRUE;
3091  }
3092  }
3093  return ret;
3094 }
3095 
3097 {
3101 };
3102 
3103 static struct PropertyMapEntry PropertyMap[] = {
3104  { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
3105  { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
3106  { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
3107  { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3108  { REG_SZ, "Service", REGSTR_VAL_SERVICE },
3109  { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3110  { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3111  { REG_SZ, "Class", REGSTR_VAL_CLASS },
3112  { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
3113  { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
3114  { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
3115  { REG_SZ, "Mfg", REGSTR_VAL_MFG },
3116  { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
3117  { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
3118  { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3119  { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
3120  { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
3121  { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
3122  { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
3123  { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
3124  { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
3125  { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
3126  { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
3127  { REG_BINARY, "Security", REGSTR_SECURITY },
3128  { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
3129  { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
3130  { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
3131  { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
3132  { 0, NULL, NULL }, /* SPDRP_ADDRESS */
3133  { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
3134  { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
3135  { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
3136  { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3137  { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3138  { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
3139 };
3140 
3141 /***********************************************************************
3142  * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3143  */
3147  DWORD Property,
3149  PBYTE PropertyBuffer,
3152 {
3153  BOOL ret;
3154  BOOL bIsStringProperty;
3155  DWORD RegType;
3156  DWORD RequiredSizeA, RequiredSizeW;
3157  DWORD PropertyBufferSizeW = 0;
3158  PBYTE PropertyBufferW = NULL;
3159 
3160  TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3162  RequiredSize);
3163 
3164  if (PropertyBufferSize != 0)
3165  {
3166  PropertyBufferSizeW = PropertyBufferSize * 2;
3167  PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
3168  if (!PropertyBufferW)
3169  {
3171  return FALSE;
3172  }
3173  }
3174 
3177  Property,
3178  &RegType,
3179  PropertyBufferW,
3180  PropertyBufferSizeW,
3181  &RequiredSizeW);
3182 
3184  {
3185  bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
3186 
3187  if (bIsStringProperty)
3188  RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
3189  else
3190  RequiredSizeA = RequiredSizeW;
3191  if (RequiredSize)
3192  *RequiredSize = RequiredSizeA;
3193  if (PropertyRegDataType)
3194  *PropertyRegDataType = RegType;
3195  }
3196 
3197  if (!ret)
3198  {
3199  HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3200  return ret;
3201  }
3202 
3203  if (RequiredSizeA <= PropertyBufferSize)
3204  {
3205  if (bIsStringProperty && PropertyBufferSize > 0)
3206  {
3207  if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
3208  {
3209  /* Last error is already set by WideCharToMultiByte */
3210  ret = FALSE;
3211  }
3212  }
3213  else
3214  memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
3215  }
3216  else
3217  {
3219  ret = FALSE;
3220  }
3221 
3222  HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3223  return ret;
3224 }
3225 
3226 /***********************************************************************
3227  * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3228  */
3232  DWORD Property,
3234  PBYTE PropertyBuffer,
3237 {
3238  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3239  struct DeviceInfo *devInfo;
3240  CONFIGRET cr;
3241  LONG lError = ERROR_SUCCESS;
3242  DWORD size;
3243 
3244  TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3246  RequiredSize);
3247 
3249  {
3251  return FALSE;
3252  }
3253  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3254  {
3256  return FALSE;
3257  }
3259  || !DeviceInfoData->Reserved)
3260  {
3262  return FALSE;
3263  }
3264 
3266  {
3268  return FALSE;
3269  }
3270 
3271  devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3272 
3273  if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3275  {
3276  HKEY hKey;
3278  hKey = SETUPDI_OpenDevKey(set->HKLM, devInfo, KEY_QUERY_VALUE);
3279  if (hKey == INVALID_HANDLE_VALUE)
3280  return FALSE;
3281  lError = RegQueryValueExW(hKey, PropertyMap[Property].nameW,
3282  NULL, PropertyRegDataType, PropertyBuffer, &size);
3283  RegCloseKey(hKey);
3284 
3285  if (RequiredSize)
3286  *RequiredSize = size;
3287 
3288  switch (lError)
3289  {
3290  case ERROR_SUCCESS:
3291  if (PropertyBuffer == NULL && size != 0)
3292  lError = ERROR_INSUFFICIENT_BUFFER;
3293  break;
3294  case ERROR_MORE_DATA:
3295  lError = ERROR_INSUFFICIENT_BUFFER;
3296  break;
3297  default:
3298  break;
3299  }
3300  }
3302  {
3303  size = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR);
3304 
3305  if (PropertyRegDataType)
3307  if (RequiredSize)
3308  *RequiredSize = size;
3309  if (PropertyBufferSize >= size)
3310  {
3311  strcpyW((LPWSTR)PropertyBuffer, devInfo->Data);
3312  }
3313  else
3314  lError = ERROR_INSUFFICIENT_BUFFER;
3315  }
3316  else
3317  {
3319 
3323  PropertyBuffer,
3324  &size,
3325  0,
3326  set->hMachine);
3327  if ((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL))
3328  {
3329  if (RequiredSize)
3330  *RequiredSize = size;
3331  }
3332 
3333  if (cr != CR_SUCCESS)
3334  {
3335  switch (cr)
3336  {
3337  case CR_INVALID_DEVINST:
3338  lError = ERROR_NO_SUCH_DEVINST;
3339  break;
3340 
3341  case CR_INVALID_PROPERTY:
3342  lError = ERROR_INVALID_REG_PROPERTY;
3343  break;
3344 
3345  case CR_BUFFER_SMALL:
3346  lError = ERROR_INSUFFICIENT_BUFFER;
3347  break;
3348 
3349  default :
3350  lError = ERROR_INVALID_DATA;
3351  break;
3352  }
3353  }
3354  }
3355 
3356  SetLastError(lError);
3357  return (lError == ERROR_SUCCESS);
3358 }
3359 
3360 /***********************************************************************
3361  * Internal for SetupDiSetDeviceRegistryPropertyA/W
3362  */
3366  DWORD Property,
3367  const BYTE *PropertyBuffer,
3369  BOOL isAnsi)
3370 {
3371  BOOL ret = FALSE;
3372  struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3373  struct DeviceInfo *deviceInfo;
3374 
3375  TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3376  PropertyBuffer, PropertyBufferSize);
3377 
3379  {
3381  return FALSE;
3382  }
3383  if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3384  {
3386  return FALSE;
3387  }
3389  || !DeviceInfoData->Reserved)
3390  {
3392  return FALSE;
3393  }
3394 
3395  deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3396 
3397  if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3399  && PropertyMap[Property].nameA)
3400  {
3401  HKEY hKey;
3402  LONG l;
3403  hKey = SETUPDI_OpenDevKey(set->HKLM, deviceInfo, KEY_SET_VALUE);
3404  if (hKey == INVALID_HANDLE_VALUE)
3405  return FALSE;
3406  /* Write new data */
3407  if (isAnsi)
3408  {
3409  l = RegSetValueExA(
3410  hKey, PropertyMap[Property].nameA, 0,
3411  PropertyMap[Property].regType, PropertyBuffer,
3413  }
3414  else
3415  {
3416  l = RegSetValueExW(
3417  hKey, PropertyMap[Property].nameW, 0,
3418  PropertyMap[Property].regType, PropertyBuffer,
3420  }
3421  if (!l)
3422  ret = TRUE;
3423  else
3424  SetLastError(l);
3425  RegCloseKey(hKey);
3426  }
3427  else
3428  {
3429  ERR("Property 0x%lx not implemented\n", Property);
3431  }
3432 
3433  TRACE("Returning %d\n", ret);
3434  return ret;
3435 }
3436 /***********************************************************************
3437  * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3438  */
3442  DWORD Property,
3443  const BYTE *PropertyBuffer,
3445 {
3448  Property,
3449  PropertyBuffer,
3451  TRUE);
3452 }
3453 
3454 /***********************************************************************
3455  * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3456  */
3460  DWORD Property,
3461  const BYTE *PropertyBuffer,
3463 {
3466  Property,
3467  PropertyBuffer,
3469  FALSE);
3470 }
3471 
3472 /***********************************************************************
3473  * SetupDiInstallClassA (SETUPAPI.@)
3474  */
3476  HWND hwndParent,
3477  PCSTR InfFileName,
3478  DWORD Flags,
3479  HSPFILEQ FileQueue)
3480 {
3481  return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3482 }
3483 
3484 /***********************************************************************
3485  * SetupDiInstallClassExA (SETUPAPI.@)
3486  */
3487 BOOL WINAPI
3490  IN PCSTR InfFileName OPTIONAL,
3491  IN DWORD Flags,
3492  IN HSPFILEQ FileQueue OPTIONAL,
3494  IN PVOID Reserved1,
3495  IN PVOID Reserved2)
3496 {
3497  PWSTR InfFileNameW = NULL;
3498  BOOL Result;
3499 
3500  if (!InfFileName)
3501  {
3503  return FALSE;
3504  }
3505  else
3506  {
3507  InfFileNameW = pSetupMultiByteToUnicode(InfFileName, CP_ACP);
3508  if (InfFileNameW == NULL)
3509  {
3511  return FALSE;
3512  }
3513  }
3514 
3515  Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
3516  FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
3517 
3518  MyFree(InfFileNameW);
3519 
3520  return Result;
3521 }
3522 
3524 {
3525  WCHAR FullBuffer[MAX_PATH];
3528  HKEY hClassKey;
3530 
3531  /* Obtain the Class GUID for this class */
3532  if (!SetupGetLineTextW(NULL,
3533  hInf,
3534  Version,
3536  Buffer,
3537  sizeof(Buffer) / sizeof(WCHAR),
3538  &RequiredSize))
3539  {
3540  return INVALID_HANDLE_VALUE;
3541  }
3542 
3543  /* Build the corresponding registry key name */
3544  lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
3545  lstrcatW(FullBuffer, BackSlash);
3546  lstrcatW(FullBuffer, Buffer);
3547 
3548  /* Obtain the Class name for this class */
3549  if (!SetupGetLineTextW(NULL,
3550  hInf,
3551  Version,
3553  Buffer,
3554  sizeof(Buffer) / sizeof(WCHAR),
3555  &RequiredSize))
3556  {
3557  return INVALID_HANDLE_VALUE;
3558  }
3559 
3560  /* Try to open or create the registry key */
3561  TRACE("Opening class key %s\n", debugstr_w(FullBuffer));
3562 #if 0 // I keep this for reference...
3564  FullBuffer,
3565  0,
3566  KEY_SET_VALUE,
3567  &hClassKey))
3568  {
3569  /* Use RegCreateKeyExW */
3570  }
3571 #endif
3573  FullBuffer,
3574  0,
3575  NULL,
3577  KEY_SET_VALUE,
3578  NULL,
3579  &hClassKey,
3580  &Disposition))
3581  {
3582  ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer));
3583  return INVALID_HANDLE_VALUE;
3584  }
3586  TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer));
3587  else
3588  TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer));
3589 
3590  TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS), debugstr_w(Buffer) );
3593  0,
3594  REG_SZ,
3595  (LPBYTE)Buffer,
3596  RequiredSize * sizeof(WCHAR)))
3597  {
3600  FullBuffer);
3601  return INVALID_HANDLE_VALUE;
3602  }
3603 
3604  return hClassKey;
3605 }
3606 
3607 /***********************************************************************
3608  * SetupDiInstallClassW (SETUPAPI.@)
3609  */
3611  HWND hwndParent,
3612  PCWSTR InfFileName,
3613  DWORD Flags,
3614  HSPFILEQ FileQueue)
3615 {
3616  return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3617 }
3618 
3619 
3620 /***********************************************************************
3621  * SetupDiOpenClassRegKey (SETUPAPI.@)
3622  */
3624  const GUID* ClassGuid,
3625  REGSAM samDesired)
3626 {
3627  return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3629 }
3630 
3631 
3632 /***********************************************************************
3633  * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3634  */
3636  const GUID* ClassGuid,
3637  REGSAM samDesired,
3638  DWORD Flags,
3640  PVOID Reserved)
3641 {
3642  PWSTR MachineNameW = NULL;
3643  HKEY hKey;
3644 
3645  TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3647 
3648  if (MachineName)
3649  {
3650  MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
3651  if (MachineNameW == NULL)
3652  return INVALID_HANDLE_VALUE;
3653  }
3654 
3655  hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3656  Flags, MachineNameW, Reserved);
3657 
3658  MyFree(MachineNameW);
3659 
3660  return hKey;
3661 }
3662 
3663 
3664 /***********************************************************************
3665  * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3666  */
3668  const GUID* ClassGuid,
3669  REGSAM samDesired,
3670  DWORD Flags,
3672  PVOID Reserved)
3673 {
3674  HKEY HKLM;
3675  HKEY hClassesKey;
3676  HKEY key;
3677  LPCWSTR lpKeyName;
3678  LONG l;
3679 
3680  TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3682 
3683  if (MachineName != NULL)
3684  {
3686  if (l != ERROR_SUCCESS)
3687  {
3688  SetLastError(l);
3689  return INVALID_HANDLE_VALUE;
3690  }
3691  }
3692  else
3694 
3695  if (Flags == DIOCR_INSTALLER)
3696  {
3697  lpKeyName = REGSTR_PATH_CLASS_NT;
3698  }
3699  else if (Flags == DIOCR_INTERFACE)
3700  {
3701  lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
3702  }
3703  else
3704  {
3705  ERR("Invalid Flags parameter!\n");
3707  if (MachineName != NULL) RegCloseKey(HKLM);
3708  return INVALID_HANDLE_VALUE;
3709  }
3710 
3711  if (!ClassGuid)
3712  {
3713  if ((l = RegOpenKeyExW(HKLM,
3714  lpKeyName,
3715  0,
3716  samDesired,
3717  &hClassesKey)))
3718  {
3720  hClassesKey = INVALID_HANDLE_VALUE;
3721  }
3722  if (MachineName != NULL)
3723  RegCloseKey(HKLM);
3724  key = hClassesKey;
3725  }
3726  else
3727  {
3728  WCHAR bracedGuidString[39];
3729 
3730  SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3731 
3732  if (!(l = RegOpenKeyExW(HKLM,
3733  lpKeyName,
3734  0,
3735  samDesired,
3736  &hClassesKey)))
3737  {
3738  if (MachineName != NULL)
3739  RegCloseKey(HKLM);
3740 
3741  if ((l = RegOpenKeyExW(hClassesKey,
3742  bracedGuidString,
3743  0,
3744  samDesired,
3745  &key)))
3746  {
3747  SetLastError(l);
3749  }
3750  RegCloseKey(hClassesKey);
3751  }
3752  else
3753  {
3754  if (MachineName != NULL) RegCloseKey(HKLM);
3755  SetLastError(l);
3757  }
3758  }
3759 
3760  return key;
3761 }
3762 
3763 /***********************************************************************
3764  * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3765  */
3768  PCWSTR DevicePath,
3769  DWORD OpenFlags,
3770  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3771 {
3772  struct DeviceInfoSet * list;
3773  PCWSTR pEnd;
3774  DWORD dwLength, dwError, dwIndex, dwKeyName, dwSubIndex;
3775  CLSID ClassId;
3776  WCHAR Buffer[MAX_PATH + 1];
3777  WCHAR SymBuffer[MAX_PATH + 1];
3778  WCHAR InstancePath[MAX_PATH + 1];
3779  HKEY hKey, hDevKey, hSymKey;
3780  struct DeviceInfo * deviceInfo;
3781  struct DeviceInterface *deviceInterface;
3782  BOOL Ret;
3783  PLIST_ENTRY ItemList;
3784  PLIST_ENTRY InterfaceListEntry;
3785 
3786  TRACE("%p %s %08x %p\n",
3787  DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3788 
3789 
3790  if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
3791  {
3793  return FALSE;
3794  }
3795 
3797  {
3799  return FALSE;
3800  }
3801 
3802  list = (struct DeviceInfoSet * )DeviceInfoSet;
3803 
3804  dwLength = wcslen(DevicePath);
3805  if (dwLength < 39)
3806  {
3807  /* path must be at least a guid length + L'\0' */
3809  return FALSE;
3810  }
3811 
3812  if (DevicePath[0] != L'\\' ||
3813  DevicePath[1] != L'\\' ||
3814  (DevicePath[2] != L'?' && DevicePath[2] != L'.') ||
3815  DevicePath[3] != L'\\')
3816  {
3817  /* invalid formatted path */
3819  return FALSE;
3820  }
3821 
3822  /* check for reference strings */
3823  pEnd = wcschr(&DevicePath[4], L'\\');
3824  if (!pEnd)
3825  {
3826  /* no reference string */
3827  pEnd = DevicePath + dwLength;
3828  }
3829 
3830  /* copy guid */
3831  wcscpy(Buffer, pEnd - 37);
3832  Buffer[36] = L'\0';
3833 
3834  dwError = UuidFromStringW(Buffer, &ClassId);
3835  if (dwError != NOERROR)
3836  {
3837  /* invalid formatted path */
3839  return FALSE;
3840  }
3841 
3842  hKey = SetupDiOpenClassRegKeyExW(&ClassId, KEY_READ, DIOCR_INTERFACE, list->MachineName, NULL);
3843 
3844  if (hKey == INVALID_HANDLE_VALUE)
3845  {
3846  /* invalid device class */
3847  return FALSE;
3848  }
3849 
3850  ItemList = list->ListHead.Flink;
3851  while (ItemList != &list->ListHead)
3852  {
3853  deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
3854  InterfaceListEntry = deviceInfo->InterfaceListHead.Flink;
3855  while (InterfaceListEntry != &deviceInfo->InterfaceListHead)
3856  {
3857  deviceInterface = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
3858  if (!IsEqualIID(&deviceInterface->InterfaceClassGuid, &ClassId))
3859  {
3860  InterfaceListEntry = InterfaceListEntry->Flink;
3861  continue;
3862  }
3863 
3864  if (!wcsicmp(deviceInterface->SymbolicLink, DevicePath))
3865  {
3866  if (DeviceInterfaceData)
3867  {
3868  DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
3869  DeviceInterfaceData->Flags = deviceInterface->Flags;
3870  CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
3871  }
3872 
3873  return TRUE;
3874  }
3875 
3876  }
3877  }
3878 
3879 
3880  dwIndex = 0;
3881  do
3882  {
3883  Buffer[0] = 0;
3884  dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
3885  dwError = RegEnumKeyExW(hKey, dwIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
3886 
3887  if (dwError != ERROR_SUCCESS)
3888  break;
3889 
3890  if (RegOpenKeyExW(hKey, Buffer, 0, KEY_READ, &hDevKey) != ERROR_SUCCESS)
3891  break;
3892 
3893  dwSubIndex = 0;
3894  InstancePath[0] = 0;
3895  dwKeyName = sizeof(InstancePath);
3896 
3897  dwError = RegQueryValueExW(hDevKey, L"DeviceInstance", NULL, NULL, (LPBYTE)InstancePath, &dwKeyName);
3898 
3899  while(TRUE)
3900  {
3901  Buffer[0] = 0;
3902  dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
3903  dwError = RegEnumKeyExW(hDevKey, dwSubIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
3904 
3905  if (dwError != ERROR_SUCCESS)
3906  break;
3907 
3908  dwError = RegOpenKeyExW(hDevKey, Buffer, 0, KEY_READ, &hSymKey);
3909  if (dwError != ERROR_SUCCESS)
3910  break;
3911 
3912  /* query for symbolic link */
3913  dwKeyName = sizeof(SymBuffer);
3914  SymBuffer[0] = L'\0';
3915  dwError = RegQueryValueExW(hSymKey, L"SymbolicLink", NULL, NULL, (LPBYTE)SymBuffer, &dwKeyName);
3916 
3917  if (dwError != ERROR_SUCCESS)
3918  {
3919  RegCloseKey(hSymKey);
3920  break;
3921  }
3922 
3923  if (!wcsicmp(SymBuffer, DevicePath))
3924  {
3925  Ret = CreateDeviceInfo(list, InstancePath, &ClassId, &deviceInfo);
3926  RegCloseKey(hSymKey);
3927  RegCloseKey(hDevKey);
3928  RegCloseKey(hKey);
3929 
3930  if (Ret)
3931  {
3932  deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymBuffer) + 1) * sizeof(WCHAR));
3933  if (deviceInterface)
3934  {
3935 
3936  CopyMemory(&deviceInterface->InterfaceClassGuid, &ClassId, sizeof(GUID));
3937  deviceInterface->DeviceInfo = deviceInfo;
3938  deviceInterface->Flags = SPINT_ACTIVE; //FIXME
3939 
3940  wcscpy(deviceInterface->SymbolicLink, SymBuffer);
3941 
3942  InsertTailList(&deviceInfo->InterfaceListHead, &deviceInterface->ListEntry);
3943  InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
3944 
3945 
3946  if (DeviceInterfaceData)
3947  {
3948  DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
3949  DeviceInterfaceData->Flags = deviceInterface->Flags;
3950  CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
3951  }
3952  else
3953  {
3954  Ret = FALSE;
3956  }
3957  }
3958  }
3959  else
3960  {
3961  HeapFree(GetProcessHeap(), 0, deviceInfo);
3962  Ret = FALSE;
3963  }
3964  return Ret;
3965  }
3966  RegCloseKey(hSymKey);
3967  dwSubIndex++;
3968  }
3969 
3970  RegCloseKey(hDevKey);
3971  dwIndex++;
3972  } while(TRUE);
3973 
3974  RegCloseKey(hKey);
3975  return FALSE;
3976 }
3977 
3978 /***********************************************************************
3979  * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3980  */
3983  PCSTR DevicePath,
3984  DWORD OpenFlags,
3985  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3986 {
3987  LPWSTR DevicePathW = NULL;
3988  BOOL bResult;
3989 
3990  TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3991 
3992  DevicePathW = pSetupMultiByteToUnicode(DevicePath, CP_ACP);
3993  if (DevicePathW == NULL)
3994  return FALSE;
3995 
3997  DevicePathW, OpenFlags, DeviceInterfaceData);
3998 
3999  MyFree(DevicePathW);
4000 
4001  return bResult;
4002 }
4003 
4004 /***********************************************************************
4005  * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4006  */
4012 {
4013  FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
4014  ClassInstallParams->InstallFunction, ClassInstallParamsSize);
4015  return FALSE;
4016 }
4017 
4018 static BOOL WINAPI
4022 {
4024 }
4025 
4026 /***********************************************************************
4027  * SetupDiCallClassInstaller (SETUPAPI.@)
4028  */
4030  DI_FUNCTION InstallFunction,
4033 {
4034  BOOL ret = FALSE;
4035 
4036  TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
4037 
4038  if (!DeviceInfoSet)
4044  else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
4046  else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4048  else
4049  {
4051 #define CLASS_COINSTALLER 0x1
4052 #define DEVICE_COINSTALLER 0x2
4053 #define CLASS_INSTALLER 0x4
4054  UCHAR CanHandle = 0;
4056 
4057  switch (InstallFunction)
4058  {
4061  break;
4064  break;
4065  case DIF_ALLOW_INSTALL:
4066  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4067  break;
4068  case DIF_DETECT:
4069  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4070  break;
4072  CanHandle = CLASS_INSTALLER;
4073  break;
4074  case DIF_INSTALLDEVICE:
4077  break;
4079  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4081  break;
4082  case DIF_INSTALLINTERFACES:
4085  break;
4088  break;
4090  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4091  break;
4093  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4094  break;
4096  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4097  break;
4099  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4100  break;
4101  case DIF_POWERMESSAGEWAKE:
4103  break;
4104  case DIF_PROPERTYCHANGE:
4107  break;
4109  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4111  break;
4112  case DIF_REGISTERDEVICE:
4113  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4115  break;
4116  case DIF_REMOVE:
4119  break;
4121  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4123  break;
4124  case DIF_SELECTDEVICE:
4125  CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4127  break;
4128  case DIF_TROUBLESHOOTER:
4130  break;
4131  case DIF_UNREMOVE:
4134  break;
4135  default:
4136  ERR("Install function %u not supported\n", InstallFunction);
4138  }
4139 
4142  /* Don't process this call, as a parameter is invalid */
4143  CanHandle = 0;
4144 
4145  if (CanHandle != 0)
4146  {
4147  LIST_ENTRY ClassCoInstallersListHead;
4148  LIST_ENTRY DeviceCoInstallersListHead;
4149  HMODULE ClassInstallerLibrary = NULL;
4150  CLASS_INSTALL_PROC ClassInstaller = NULL;
4152  PLIST_ENTRY ListEntry;
4153  HKEY hKey;
4154  DWORD dwRegType, dwLength;
4155  DWORD rc = NO_ERROR;
4156 
4157  InitializeListHead(&ClassCoInstallersListHead);
4158  InitializeListHead(&DeviceCoInstallersListHead);
4159 
4160  if (CanHandle & DEVICE_COINSTALLER)
4161  {
4163  if (hKey != INVALID_HANDLE_VALUE)
4164  {
4165  rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
4166  if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4167  {
4168  LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4169  if (KeyBuffer != NULL)
4170  {
4172  if (rc == ERROR_SUCCESS)
4173  {
4174  LPWSTR ptr;
4175  for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4176  {
4177  /* Add coinstaller to DeviceCoInstallersListHead list */
4178  struct CoInstallerElement *coinstaller;
4179  TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
4180  coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4181  if (!coinstaller)
4182  continue;
4183  ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4184  if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4185  InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
4186  else
4187  HeapFree(GetProcessHeap(), 0, coinstaller);
4188  }
4189  }
4190  HeapFree(GetProcessHeap(), 0, KeyBuffer);
4191  }
4192  }
4193  RegCloseKey(hKey);
4194  }
4195  }
4196  if (CanHandle & CLASS_COINSTALLER)
4197  {
4198  rc = RegOpenKeyExW(
4201  0, /* Options */
4203  &hKey);
4204  if (rc == ERROR_SUCCESS)
4205  {
4206  WCHAR szGuidString[40];
4207  if (pSetupStringFromGuid(&DeviceInfoData->ClassGuid, szGuidString, ARRAYSIZE(szGuidString)) == ERROR_SUCCESS)
4208  {
4209  rc = RegQueryValueExW(hKey, szGuidString, NULL, &dwRegType, NULL, &dwLength);
4210  if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4211  {
4212  LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4213  if (KeyBuffer != NULL)
4214  {
4215  rc = RegQueryValueExW(hKey, szGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4216  if (rc == ERROR_SUCCESS)
4217  {
4218  LPWSTR ptr;
4219  for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4220  {
4221  /* Add coinstaller to ClassCoInstallersListHead list */
4222  struct CoInstallerElement *coinstaller;
4223  TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
4224  coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4225  if (!coinstaller)
4226  continue;
4227  ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4228  if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4229  InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
4230  else
4231  HeapFree(GetProcessHeap(), 0, coinstaller);
4232  }
4233  }
4234  HeapFree(GetProcessHeap(), 0, KeyBuffer);
4235  }
4236  }
4237  }
4238  RegCloseKey(hKey);
4239  }
4240  }
4241  if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
4242  {
4244  if (hKey != INVALID_HANDLE_VALUE)
4245  {
4246  rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
4247  if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
4248  {
4249  LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4250  if (KeyBuffer != NULL)
4251  {
4252  rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4253  if (rc == ERROR_SUCCESS)
4254  {
4255  /* Get ClassInstaller function pointer */
4256  TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
4257  if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
4258  {
4259  InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
4261  }
4262  }
4263  HeapFree(GetProcessHeap(), 0, KeyBuffer);
4264  }
4265  }
4266  RegCloseKey(hKey);
4267  }
4268  }
4269 
4270  /* Call Class co-installers */
4271  Context.PostProcessing = FALSE;
4272  rc = NO_ERROR;
4273  ListEntry = ClassCoInstallersListHead.Flink;
4274  while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
4275  {
4276  struct CoInstallerElement *coinstaller;
4277  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4278  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4279  coinstaller->PrivateData = Context.PrivateData;
4281  {
4282  coinstaller->DoPostProcessing = TRUE;
4283  rc = NO_ERROR;
4284  }
4286  }
4287 
4288  /* Call Device co-installers */
4289  ListEntry = DeviceCoInstallersListHead.Flink;
4290  while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
4291  {
4292  struct CoInstallerElement *coinstaller;
4293  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4294  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4295  coinstaller->PrivateData = Context.PrivateData;
4297  {
4298  coinstaller->DoPostProcessing = TRUE;
4299  rc = NO_ERROR;
4300  }
4302  }
4303 
4304  /* Call Class installer */
4305  if (ClassInstaller)
4306  {
4307  rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
4308  FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
4309  }
4310  else
4311  rc = ERROR_DI_DO_DEFAULT;
4312 
4313  /* Call default handler */
4314  if (rc == ERROR_DI_DO_DEFAULT)
4315  {
4316  if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
4317  {
4319  rc = NO_ERROR;
4320  else
4321  rc = GetLastError();
4322  }
4323  else
4324  rc = NO_ERROR;
4325  }
4326 
4327  /* Call Class co-installers that required postprocessing */
4328  Context.PostProcessing = TRUE;
4329  ListEntry = ClassCoInstallersListHead.Flink;
4330  while (ListEntry != &ClassCoInstallersListHead)
4331  {
4332  struct CoInstallerElement *coinstaller;
4333  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4334  if (coinstaller->DoPostProcessing)
4335  {
4336  Context.InstallResult = rc;
4337  Context.PrivateData = coinstaller->PrivateData;
4338  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4339  }
4340  FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4342  }
4343 
4344  /* Call Device co-installers that required postprocessing */
4345  ListEntry = DeviceCoInstallersListHead.Flink;
4346  while (ListEntry != &DeviceCoInstallersListHead)
4347  {
4348  struct CoInstallerElement *coinstaller;
4349  coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4350  if (coinstaller->DoPostProcessing)
4351  {
4352  Context.InstallResult = rc;
4353  Context.PrivateData = coinstaller->PrivateData;
4354  rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4355  }
4356  FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4358  }
4359 
4360  /* Free allocated memory */
4361  while (!IsListEmpty(&ClassCoInstallersListHead))
4362  {
4363  ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
4365  }
4366  while (!IsListEmpty(&DeviceCoInstallersListHead))
4367  {
4368  ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
4370  }
4371 
4372  ret = (rc == NO_ERROR);
4373  }
4374  }
4375 
4376  TRACE("Returning %d\n", ret);
4377  return ret;
4378 }
4379 
4380 /***********************************************************************
4381  * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4382  */
4387 {
4388  SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4389  BOOL ret = FALSE;
4390 
4392 
4393  if (DeviceInstallParams == NULL)
4395  else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
4397  else
4398  {
4399  deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4401 
4402  if (ret)
4403  {
4404  /* Do W->A conversion */
4405  memcpy(
4407  &deviceInstallParamsW,
4408  FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
4409  if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
4410  DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
4411  {
4412  DeviceInstallParams->DriverPath[0] = '\0';
4413  ret = FALSE;
4414  }
4415  }
4416  }
4417 
4418  TRACE("Returning %d\n", ret);
4419  return ret;
4420 }
4421 
4422 /***********************************************************************
4423  * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4424  */
4425 BOOL WINAPI
4428  OUT LPGUID ClassGuid)
4429 {
4430  struct DeviceInfoSet *list;
4431  BOOL ret = FALSE;
4432 
4433  TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
4434 
4435  if (!DeviceInfoSet)
4439  else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
4441  else
4442  {
4443  memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
4444 
4445  ret = TRUE;
4446  }
4447 
4448  TRACE("Returning %d\n", ret);
4449  return ret;
4450 }
4451 
4452 /***********************************************************************
4453  * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4454  */
4455 BOOL WINAPI
4460 {
4461  struct DeviceInfoSet *list;
4462  BOOL ret = FALSE;
4463 
4465 
4466  if (!DeviceInfoSet)
4470  else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4472  else if (!DeviceInstallParams)
4474  else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4476  else
4477  {
4479 
4480  if (DeviceInfoData)
4481  Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
4482  else
4483  Source = &list->InstallParams;
4484 
4485  ret = TRUE;
4486 
4487  _SEH2_TRY
4488  {