1 /*
2 * SetupAPI interface-related functions
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 AddInterface[] = {'A','d','d','I','n','t','e','r','f','a','c','e',0};
26 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
27 static const WCHAR Control[] = {'C','o','n','t','r','o','l',0};
28 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
29 static const WCHAR DotInterfaces[] = {'.','I','n','t','e','r','f','a','c','e','s',0};
30 static const WCHAR Linked[] = {'L','i','n','k','e','d',0};
31 static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
32
33 static BOOL
CreateDeviceInterface(IN struct DeviceInfo * deviceInfo,IN LPCWSTR SymbolicLink,IN LPCGUID pInterfaceGuid,OUT struct DeviceInterface ** pDeviceInterface)34 CreateDeviceInterface(
35 IN struct DeviceInfo* deviceInfo,
36 IN LPCWSTR SymbolicLink,
37 IN LPCGUID pInterfaceGuid,
38 OUT struct DeviceInterface **pDeviceInterface)
39 {
40 struct DeviceInterface *deviceInterface;
41
42 *pDeviceInterface = NULL;
43
44 deviceInterface = HeapAlloc(GetProcessHeap(), 0,
45 FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (strlenW(SymbolicLink) + 1) * sizeof(WCHAR));
46 if (!deviceInterface)
47 {
48 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
49 return FALSE;
50 }
51 deviceInterface->DeviceInfo = deviceInfo;
52 strcpyW(deviceInterface->SymbolicLink, SymbolicLink);
53 deviceInterface->Flags = 0; /* Flags will be updated later */
54 memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
55
56 *pDeviceInterface = deviceInterface;
57 return TRUE;
58 }
59
60 BOOL
DestroyDeviceInterface(struct DeviceInterface * deviceInterface)61 DestroyDeviceInterface(
62 struct DeviceInterface* deviceInterface)
63 {
64 return HeapFree(GetProcessHeap(), 0, deviceInterface);
65 }
66
67 LONG
SETUP_CreateInterfaceList(struct DeviceInfoSet * list,PCWSTR MachineName,CONST GUID * InterfaceGuid,PCWSTR DeviceInstanceW,BOOL OnlyPresentInterfaces)68 SETUP_CreateInterfaceList(
69 struct DeviceInfoSet *list,
70 PCWSTR MachineName,
71 CONST GUID *InterfaceGuid,
72 PCWSTR DeviceInstanceW /* OPTIONAL */,
73 BOOL OnlyPresentInterfaces)
74 {
75 HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
76 HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
77 HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
78 HKEY hControlKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
79 HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */
80 HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
81 LONG rc;
82 WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1];
83 PWSTR pSymbolicLink = NULL;
84 PWSTR InstancePath = NULL;
85 DWORD i, j;
86 DWORD dwLength, dwInstancePathLength;
87 DWORD dwRegType;
88 DWORD LinkedValue;
89 GUID ClassGuid;
90 struct DeviceInfo *deviceInfo;
91
92 hInterfaceKey = INVALID_HANDLE_VALUE;
93 hDeviceInstanceKey = NULL;
94 hReferenceKey = NULL;
95
96 /* Open registry key related to this interface */
97 hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL);
98 if (hInterfaceKey == INVALID_HANDLE_VALUE)
99 {
100 /* Key doesn't exist. Let's keep it empty */
101 rc = ERROR_SUCCESS;
102 goto cleanup;
103 }
104
105 /* Enumerate sub keys of hInterfaceKey */
106 i = 0;
107 while (TRUE)
108 {
109 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
110 rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
111 if (rc == ERROR_NO_MORE_ITEMS)
112 break;
113 if (rc != ERROR_SUCCESS)
114 goto cleanup;
115 i++;
116
117 /* Open sub key */
118 if (hDeviceInstanceKey != NULL)
119 RegCloseKey(hDeviceInstanceKey);
120 rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey);
121 if (rc != ERROR_SUCCESS)
122 goto cleanup;
123
124 /* Read DeviceInstance */
125 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength);
126 if (rc != ERROR_SUCCESS)
127 goto cleanup;
128 if (dwRegType != REG_SZ)
129 {
130 rc = ERROR_GEN_FAILURE;
131 goto cleanup;
132 }
133 HeapFree(GetProcessHeap(), 0, InstancePath);
134 InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR));
135 if (!InstancePath)
136 {
137 rc = ERROR_NOT_ENOUGH_MEMORY;
138 goto cleanup;
139 }
140 rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength);
141 if (rc != ERROR_SUCCESS)
142 goto cleanup;
143 InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0';
144 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
145
146 if (DeviceInstanceW)
147 {
148 /* Check if device enumerator is not the right one */
149 if (strcmpW(DeviceInstanceW, InstancePath) != 0)
150 continue;
151 }
152
153 /* Find class GUID associated to the device instance */
154 rc = RegOpenKeyExW(
155 list->HKLM,
156 REGSTR_PATH_SYSTEMENUM,
157 0, /* Options */
158 READ_CONTROL,
159 &hEnumKey);
160 if (rc != ERROR_SUCCESS)
161 goto cleanup;
162 rc = RegOpenKeyExW(
163 hEnumKey,
164 InstancePath,
165 0, /* Options */
166 KEY_QUERY_VALUE,
167 &hKey);
168 RegCloseKey(hEnumKey);
169 if (rc != ERROR_SUCCESS)
170 goto cleanup;
171 dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
172 rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
173 RegCloseKey(hKey);
174 if (rc != ERROR_SUCCESS)
175 goto cleanup;
176 KeyBuffer[dwLength / sizeof(WCHAR)] = '\0';
177 KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
178 if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK)
179 {
180 rc = ERROR_GEN_FAILURE;
181 goto cleanup;
182 }
183 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
184
185 /* If current device doesn't match the list GUID (if any), skip this entry */
186 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
187 continue;
188
189 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
190 j = 0;
191 while (TRUE)
192 {
193 struct DeviceInterface *interfaceInfo;
194
195 dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
196 rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
197 if (rc == ERROR_NO_MORE_ITEMS)
198 break;
199 if (rc != ERROR_SUCCESS)
200 goto cleanup;
201 j++;
202 if (KeyBuffer[0] != '#')
203 /* This entry doesn't represent an interesting entry */
204 continue;
205
206 /* Open sub key */
207 if (hReferenceKey != NULL)
208 RegCloseKey(hReferenceKey);
209 rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey);
210 if (rc != ERROR_SUCCESS)
211 goto cleanup;
212
213 /* Read SymbolicLink value */
214 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength);
215 if (rc != ERROR_SUCCESS )
216 goto cleanup;
217 if (dwRegType != REG_SZ)
218 {
219 rc = ERROR_GEN_FAILURE;
220 goto cleanup;
221 }
222
223 /* We have found a device */
224 /* Step 1. Create a device info element */
225 if (!CreateDeviceInfo(list, InstancePath, &ClassGuid, &deviceInfo))
226 {
227 rc = GetLastError();
228 goto cleanup;
229 }
230 TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
231 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
232
233 /* Step 2. Create an interface list for this element */
234 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
235 pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
236 if (!pSymbolicLink)
237 {
238 rc = ERROR_NOT_ENOUGH_MEMORY;
239 goto cleanup;
240 }
241 rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength);
242 pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0';
243 if (rc != ERROR_SUCCESS)
244 goto cleanup;
245 if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo))
246 {
247 rc = GetLastError();
248 goto cleanup;
249 }
250
251 /* Step 3. Update flags */
252 if (KeyBuffer[1] == '\0')
253 interfaceInfo->Flags |= SPINT_DEFAULT;
254 rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey);
255 if (rc != ERROR_SUCCESS)
256 {
257 #if 0
258 if (OnlyPresentInterfaces)
259 {
260 DestroyDeviceInterface(interfaceInfo);
261 continue;
262 }
263 else
264 interfaceInfo->Flags |= SPINT_REMOVED;
265 #endif
266 }
267 else
268 {
269 dwLength = sizeof(DWORD);
270 if (RegQueryValueExW(hControlKey, Linked, NULL, &dwRegType, (LPBYTE)&LinkedValue, &dwLength) == ERROR_SUCCESS
271 && dwRegType == REG_DWORD && LinkedValue)
272 interfaceInfo->Flags |= SPINT_ACTIVE;
273 RegCloseKey(hControlKey);
274 }
275
276 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink));
277 InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry);
278 }
279 }
280 rc = ERROR_SUCCESS;
281
282 cleanup:
283 if (hReferenceKey != NULL)
284 RegCloseKey(hReferenceKey);
285 if (hDeviceInstanceKey != NULL)
286 RegCloseKey(hDeviceInstanceKey);
287 if (hInterfaceKey != INVALID_HANDLE_VALUE)
288 RegCloseKey(hInterfaceKey);
289 HeapFree(GetProcessHeap(), 0, InstancePath);
290 HeapFree(GetProcessHeap(), 0, pSymbolicLink);
291 return rc;
292 }
293
294 static LPWSTR
CreateSymbolicLink(IN LPGUID InterfaceGuid,IN LPCWSTR ReferenceString,IN struct DeviceInfo * devInfo)295 CreateSymbolicLink(
296 IN LPGUID InterfaceGuid,
297 IN LPCWSTR ReferenceString,
298 IN struct DeviceInfo *devInfo)
299 {
300 DWORD Length, Index, Offset;
301 LPWSTR Key;
302
303 Length = wcslen(devInfo->instanceId) + 4 /* prepend ##?# */ + 41 /* #{GUID} + */ + 1 /* zero byte */;
304
305 Key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length * sizeof(WCHAR));
306 if (!Key)
307 return NULL;
308
309 wcscpy(Key, L"##?#");
310 wcscat(Key, devInfo->instanceId);
311
312 for(Index = 4; Index < Length; Index++)
313 {
314 if (Key[Index] == L'\\')
315 {
316 Key[Index] = L'#';
317 }
318 }
319
320 wcscat(Key, L"#");
321
322 Offset = wcslen(Key);
323 pSetupStringFromGuid(InterfaceGuid, Key + Offset, Length - Offset);
324
325 return Key;
326 }
327
328
329 static BOOL
InstallOneInterface(IN LPGUID InterfaceGuid,IN LPCWSTR ReferenceString,IN LPCWSTR InterfaceSection,IN UINT InterfaceFlags,IN HINF hInf,IN HDEVINFO DeviceInfoSet,IN struct DeviceInfo * devInfo)330 InstallOneInterface(
331 IN LPGUID InterfaceGuid,
332 IN LPCWSTR ReferenceString,
333 IN LPCWSTR InterfaceSection,
334 IN UINT InterfaceFlags,
335 IN HINF hInf,
336 IN HDEVINFO DeviceInfoSet,
337 IN struct DeviceInfo *devInfo)
338 {
339 HKEY hKey, hRefKey;
340 LPWSTR Path;
341 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
342 struct DeviceInterface *DevItf = NULL;
343
344 if (InterfaceFlags != 0)
345 {
346 SetLastError(ERROR_INVALID_PARAMETER);
347 return FALSE;
348 }
349
350 TRACE("Need to InstallOneInterface(%s %s %s %u) hInf %p DeviceInfoSet %p devInfo %p instanceId %s\n", debugstr_guid(InterfaceGuid),
351 debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags, hInf, DeviceInfoSet, devInfo, debugstr_w(devInfo->instanceId));
352
353
354 Path = CreateSymbolicLink(InterfaceGuid, ReferenceString, devInfo);
355 if (!Path)
356 return FALSE;
357
358 CreateDeviceInterface(devInfo, Path, InterfaceGuid, &DevItf);
359 HeapFree(GetProcessHeap(), 0, Path);
360 if (!DevItf)
361 {
362 return FALSE;
363 }
364
365 memcpy(&DeviceInterfaceData.InterfaceClassGuid, &DevItf->InterfaceClassGuid, sizeof(GUID));
366 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
367 DeviceInterfaceData.Flags = DevItf->Flags;
368 DeviceInterfaceData.Reserved = (ULONG_PTR)DevItf;
369
370 hKey = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, &DeviceInterfaceData, 0, KEY_ALL_ACCESS, NULL, 0);
371 HeapFree(GetProcessHeap(), 0, DevItf);
372 if (hKey == INVALID_HANDLE_VALUE)
373 {
374 return FALSE;
375 }
376
377 if (ReferenceString)
378 {
379 Path = HeapAlloc(GetProcessHeap(), 0, (wcslen(ReferenceString) + 2) * sizeof(WCHAR));
380 if (!Path)
381 {
382 RegCloseKey(hKey);
383 return FALSE;
384 }
385
386 wcscpy(Path, L"#");
387 wcscat(Path, ReferenceString);
388
389 if (RegCreateKeyExW(hKey, Path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hRefKey, NULL) != ERROR_SUCCESS)
390 {
391 ERR("failed to create key %s %lx\n", debugstr_w(Path), GetLastError());
392 HeapFree(GetProcessHeap(), 0, Path);
393 return FALSE;
394 }
395
396 RegCloseKey(hKey);
397 hKey = hRefKey;
398 HeapFree(GetProcessHeap(), 0, Path);
399 }
400
401 if (RegCreateKeyExW(hKey, L"Device Parameters", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hRefKey, NULL) != ERROR_SUCCESS)
402 {
403 RegCloseKey(hKey);
404 return FALSE;
405 }
406
407 return SetupInstallFromInfSectionW(NULL, /* FIXME */ hInf, InterfaceSection, SPINST_REGISTRY, hRefKey, NULL, 0, NULL, NULL, NULL, NULL);
408 }
409
410 /***********************************************************************
411 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
412 */
413 BOOL WINAPI
SetupDiInstallDeviceInterfaces(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData)414 SetupDiInstallDeviceInterfaces(
415 IN HDEVINFO DeviceInfoSet,
416 IN PSP_DEVINFO_DATA DeviceInfoData)
417 {
418 struct DeviceInfoSet *list = NULL;
419 BOOL ret = FALSE;
420
421 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
422
423 if (!DeviceInfoSet)
424 SetLastError(ERROR_INVALID_PARAMETER);
425 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
426 SetLastError(ERROR_INVALID_HANDLE);
427 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
428 SetLastError(ERROR_INVALID_HANDLE);
429 else if (!DeviceInfoData)
430 SetLastError(ERROR_INVALID_PARAMETER);
431 else if (DeviceInfoData && DeviceInfoData->Reserved == 0)
432 SetLastError(ERROR_INVALID_USER_BUFFER);
433 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
434 SetLastError(ERROR_INVALID_USER_BUFFER);
435 else
436 {
437 struct DeviceInfo *devInfo;
438 struct DriverInfoElement *SelectedDriver = NULL;
439 SP_DEVINSTALL_PARAMS_W InstallParams;
440 WCHAR SectionName[MAX_PATH];
441 DWORD SectionNameLength = 0;
442 INFCONTEXT ContextInterface;
443 LPWSTR InterfaceGuidString = NULL;
444 LPWSTR ReferenceString = NULL;
445 LPWSTR InterfaceSection = NULL;
446 INT InterfaceFlags;
447 GUID InterfaceGuid;
448 BOOL Result;
449
450 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
451
452 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
453 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
454 if (!Result)
455 goto cleanup;
456
457 SelectedDriver = (struct DriverInfoElement *)InstallParams.ClassInstallReserved;
458 if (SelectedDriver == NULL)
459 {
460 SetLastError(ERROR_NO_DRIVER_SELECTED);
461 ret = FALSE;
462 goto cleanup;
463 }
464
465 /* Get .Interfaces section name */
466 Result = SetupDiGetActualSectionToInstallW(
467 SelectedDriver->InfFileDetails->hInf,
468 SelectedDriver->Details.SectionName,
469 SectionName, MAX_PATH, &SectionNameLength, NULL);
470 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotInterfaces) - 1)
471 goto cleanup;
472 strcatW(SectionName, DotInterfaces);
473
474 ret = TRUE;
475 Result = SetupFindFirstLineW(
476 SelectedDriver->InfFileDetails->hInf,
477 SectionName,
478 AddInterface,
479 &ContextInterface);
480 while (ret && Result)
481 {
482 ret = GetStringField(&ContextInterface, 1, &InterfaceGuidString);
483 if (!ret)
484 goto cleanup;
485 else if (strlenW(InterfaceGuidString) != MAX_GUID_STRING_LEN - 1)
486 {
487 SetLastError(ERROR_INVALID_PARAMETER);
488 ret = FALSE;
489 goto cleanup;
490 }
491
492 InterfaceGuidString[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */
493 if (UuidFromStringW(&InterfaceGuidString[1], &InterfaceGuid) != RPC_S_OK)
494 {
495 /* Bad GUID, skip the entry */
496 SetLastError(ERROR_INVALID_PARAMETER);
497 ret = FALSE;
498 goto cleanup;
499 }
500
501 ret = GetStringField(&ContextInterface, 2, &ReferenceString);
502 if (!ret)
503 goto cleanup;
504
505 ret = GetStringField(&ContextInterface, 3, &InterfaceSection);
506 if (!ret)
507 {
508 /* ReferenceString is optional */
509 InterfaceSection = ReferenceString;
510 ReferenceString = NULL;
511 }
512
513 ret = SetupGetIntField(
514 &ContextInterface,
515 (ReferenceString ? 4 : 3), /* Field index */
516 &InterfaceFlags);
517 if (!ret)
518 {
519 if (GetLastError() == ERROR_INVALID_PARAMETER)
520 {
521 /* The field may be empty. Ignore the error */
522 InterfaceFlags = 0;
523 ret = TRUE;
524 }
525 else
526 goto cleanup;
527 }
528
529 /* Install Interface */
530 ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags, SelectedDriver->InfFileDetails->hInf, DeviceInfoSet, devInfo);
531
532 cleanup:
533 MyFree(InterfaceGuidString);
534 if (ReferenceString)
535 MyFree(ReferenceString);
536 MyFree(InterfaceSection);
537 InterfaceGuidString = ReferenceString = InterfaceSection = NULL;
538 Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface);
539 }
540 }
541
542 TRACE("Returning %d\n", ret);
543 return ret;
544 }
545
546 HKEY WINAPI
SetupDiOpenDeviceInterfaceRegKey(IN HDEVINFO DeviceInfoSet,IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,IN DWORD Reserved,IN REGSAM samDesired)547 SetupDiOpenDeviceInterfaceRegKey(
548 IN HDEVINFO DeviceInfoSet, IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IN DWORD Reserved, IN REGSAM samDesired)
549 {
550 HKEY hKey = INVALID_HANDLE_VALUE, hDevKey;
551 struct DeviceInfoSet * list;
552
553 TRACE("%p %p %p 0x%08x 0x%08x)\n", DeviceInfoSet, DeviceInterfaceData, Reserved, samDesired);
554
555 if (!DeviceInfoSet)
556 SetLastError(ERROR_INVALID_PARAMETER);
557 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
558 SetLastError(ERROR_INVALID_HANDLE);
559 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
560 SetLastError(ERROR_INVALID_HANDLE);
561 else if (!DeviceInterfaceData)
562 SetLastError(ERROR_INVALID_PARAMETER);
563 else if (DeviceInterfaceData && DeviceInterfaceData->Reserved == 0)
564 SetLastError(ERROR_INVALID_USER_BUFFER);
565 else if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
566 SetLastError(ERROR_INVALID_USER_BUFFER);
567 else
568 {
569 struct DeviceInterface *DevItf;
570 LPWSTR Path, Guid, Slash;
571 DWORD Length;
572 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
573
574 Length = wcslen(DevItf->SymbolicLink);
575
576 Path = HeapAlloc(GetProcessHeap(), 0, (Length+2) * sizeof(WCHAR));
577 if (!Path)
578 {
579 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
580 return INVALID_HANDLE_VALUE;
581 }
582
583 wcscpy(Path, DevItf->SymbolicLink);
584
585 Guid = wcsrchr(Path, '}');
586 Slash = wcsrchr(Path, '\\');
587 if (!Guid || !Slash)
588 {
589 HeapFree(GetProcessHeap(), 0, Path);
590 SetLastError(ERROR_INVALID_PARAMETER);
591 return INVALID_HANDLE_VALUE;
592 }
593
594 if ((ULONG_PTR)Slash > (ULONG_PTR)Guid)
595 {
596 /* Create an extra slash */
597 memmove(Slash+1, Slash, (wcslen(Slash) + 1) * sizeof(WCHAR));
598 Slash[1] = L'#';
599 }
600
601 Guid = Path;
602 while((ULONG_PTR)Guid < (ULONG_PTR)Slash)
603 {
604 if (*Guid == L'\\')
605 *Guid = L'#';
606
607 Guid++;
608 }
609
610 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL);
611 if (hKey != INVALID_HANDLE_VALUE)
612 {
613 if (RegOpenKeyExW(hKey, Path, 0, samDesired, &hDevKey) == ERROR_SUCCESS)
614 {
615 RegCloseKey(hKey);
616 hKey = hDevKey;
617 }
618 else
619 {
620 RegCloseKey(hKey);
621 hKey = INVALID_HANDLE_VALUE;
622 }
623 }
624
625 HeapFree(GetProcessHeap(), 0, Path);
626 }
627
628 return hKey;
629 }
630
631 /***********************************************************************
632 * SetupDiDeleteDeviceInterfaceData (SETUPAPI.@)
633 */
634 BOOL
635 WINAPI
SetupDiDeleteDeviceInterfaceData(HDEVINFO DeviceInfoSet,PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)636 SetupDiDeleteDeviceInterfaceData(
637 HDEVINFO DeviceInfoSet,
638 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
639 {
640 FIXME("SetupDiDeleteDeviceInterfaceData(%p %p) stub\n",
641 DeviceInfoSet, DeviceInterfaceData);
642 return TRUE;
643 }
644