diff --git a/reactos/dll/win32/setupapi/devinst.c b/reactos/dll/win32/setupapi/devinst.c index cb12d766ad5..e589016e903 100644 --- a/reactos/dll/win32/setupapi/devinst.c +++ b/reactos/dll/win32/setupapi/devinst.c @@ -2628,7 +2628,14 @@ HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW( HINF InfHandle, PCWSTR InfSectionName) { + HKEY hKey, hDevKey; + LPWSTR SymbolicLink; + DWORD Length, Index; + LONG rc; + WCHAR bracedGuidString[39]; + struct DeviceInterface *DevItf; struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, samDesired, InfHandle, InfSectionName); @@ -2650,11 +2657,79 @@ HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW( SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } - - FIXME("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, - samDesired, InfHandle, InfSectionName); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return INVALID_HANDLE_VALUE; + + hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL); + if (hKey == INVALID_HANDLE_VALUE) + { + hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL); + if (hKey == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString); + + if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + RegCloseKey(hKey); + hKey = hDevKey; + } + + DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved; + + Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR); + SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length); + if (!SymbolicLink) + { + RegCloseKey(hKey); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return INVALID_HANDLE_VALUE; + } + + wcscpy(SymbolicLink, DevItf->SymbolicLink); + + Index = 0; + while(SymbolicLink[Index]) + { + if (SymbolicLink[Index] == L'\\') + { + SymbolicLink[Index] = L'#'; + } + Index++; + } + + rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL); + + RegCloseKey(hKey); + HeapFree(GetProcessHeap(), 0, SymbolicLink); + + if (rc == ERROR_SUCCESS) + { + if (InfHandle && InfSectionName) + { + if (!SetupInstallFromInfSection(NULL /*FIXME */, + InfHandle, + InfSectionName, + SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF, + hDevKey, + NULL, + 0, + set->SelectedDevice->InstallParams.InstallMsgHandler, + set->SelectedDevice->InstallParams.InstallMsgHandlerContext, + INVALID_HANDLE_VALUE, + NULL)) + { + RegCloseKey(hDevKey); + return INVALID_HANDLE_VALUE; + } + } + } + + SetLastError(rc); + return hDevKey; } /*********************************************************************** @@ -3611,6 +3686,7 @@ HKEY WINAPI SetupDiOpenClassRegKeyExW( key = INVALID_HANDLE_VALUE; } } + return key; } diff --git a/reactos/dll/win32/setupapi/interface.c b/reactos/dll/win32/setupapi/interface.c index 172917b1c06..fc9f89076b7 100644 --- a/reactos/dll/win32/setupapi/interface.c +++ b/reactos/dll/win32/setupapi/interface.c @@ -292,22 +292,118 @@ cleanup: return rc; } +static LPWSTR +CreateSymbolicLink( + IN LPGUID InterfaceGuid, + IN LPCWSTR ReferenceString, + IN struct DeviceInfo *devInfo) +{ + DWORD Length, Index, Offset; + LPWSTR Key; + + Length = wcslen(devInfo->instanceId) + 4 /* prepend ##?# */ + 41 /* #{GUID} + */ + 1 /* zero byte */; + + Key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length * sizeof(WCHAR)); + if (!Key) + return NULL; + + wcscpy(Key, L"##?#"); + wcscat(Key, devInfo->instanceId); + + for(Index = 4; Index < Length; Index++) + { + if (Key[Index] == L'\\') + { + Key[Index] = L'#'; + } + } + + wcscat(Key, L"#"); + + Offset = wcslen(Key); + pSetupStringFromGuid(InterfaceGuid, Key + Offset, Length - Offset); + + return Key; +} + + static BOOL InstallOneInterface( IN LPGUID InterfaceGuid, IN LPCWSTR ReferenceString, IN LPCWSTR InterfaceSection, - IN UINT InterfaceFlags) + IN UINT InterfaceFlags, + IN HINF hInf, + IN HDEVINFO DeviceInfoSet, + IN struct DeviceInfo *devInfo) { + BOOL ret; + HKEY hKey, hRefKey; + LPWSTR Path; + SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; + PLIST_ENTRY InterfaceListEntry; + struct DeviceInterface *DevItf = NULL; + if (InterfaceFlags != 0) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid), - debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags); - return TRUE; + TRACE("Need to InstallOneInterface(%s %s %s %u) hInf %p DeviceInfoSet %p devInfo %p instanceId %s\n", debugstr_guid(InterfaceGuid), + debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags, hInf, DeviceInfoSet, devInfo, debugstr_w(devInfo->instanceId)); + + + Path = CreateSymbolicLink(InterfaceGuid, ReferenceString, devInfo); + if (!Path) + return FALSE; + + CreateDeviceInterface(devInfo, Path, InterfaceGuid, &DevItf); + HeapFree(GetProcessHeap(), 0, Path); + if (!DevItf) + { + return FALSE; + } + + InsertTailList(&devInfo->InterfaceListHead, &DevItf->ListEntry); + + memcpy(&DeviceInterfaceData.InterfaceClassGuid, &DevItf->InterfaceClassGuid, sizeof(GUID)); + DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + DeviceInterfaceData.Flags = DevItf->Flags; + DeviceInterfaceData.Reserved = (ULONG_PTR)DevItf; + + hKey = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, &DeviceInterfaceData, 0, KEY_ALL_ACCESS, NULL, 0); + HeapFree(GetProcessHeap(), 0, DevItf); + if (hKey == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + if (ReferenceString) + { + Path = HeapAlloc(GetProcessHeap(), 0, (wcslen(ReferenceString) + 2) * sizeof(WCHAR)); + if (!Path) + { + RegCloseKey(hKey); + return FALSE; + } + + wcscpy(Path, L"#"); + wcscat(Path, ReferenceString); + + if (RegCreateKeyExW(hKey, Path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hRefKey, NULL) != ERROR_SUCCESS) + { + ERR("failed to create key %s %lx\n", debugstr_w(Path), GetLastError()); + HeapFree(GetProcessHeap(), 0, Path); + return FALSE; + } + + RegCloseKey(hKey); + hKey = hRefKey; + HeapFree(GetProcessHeap(), 0, Path); + } + + return SetupInstallFromInfSectionW(NULL, /* FIXME */ hInf, InterfaceSection, SPINST_REGISTRY, hKey, NULL, 0, NULL, NULL, NULL, NULL); } /*********************************************************************** @@ -335,7 +431,8 @@ SetupDiInstallDeviceInterfaces( SetLastError(ERROR_INVALID_USER_BUFFER); else { - struct DriverInfoElement *SelectedDriver; + struct DeviceInfo *devInfo; + struct DriverInfoElement *SelectedDriver = NULL; SP_DEVINSTALL_PARAMS_W InstallParams; WCHAR SectionName[MAX_PATH]; DWORD SectionNameLength = 0; @@ -347,6 +444,8 @@ SetupDiInstallDeviceInterfaces( GUID InterfaceGuid; BOOL Result; + devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; + InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); if (!Result) @@ -402,11 +501,15 @@ SetupDiInstallDeviceInterfaces( ret = GetStringField(&ContextInterface, 3, &InterfaceSection); if (!ret) - goto cleanup; + { + /* ReferenceString is optional */ + InterfaceSection = ReferenceString; + ReferenceString = NULL; + } ret = SetupGetIntField( &ContextInterface, - 4, /* Field index */ + (ReferenceString ? 4 : 3), /* Field index */ &InterfaceFlags); if (!ret) { @@ -421,11 +524,12 @@ SetupDiInstallDeviceInterfaces( } /* Install Interface */ - ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags); + ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags, SelectedDriver->InfFileDetails->hInf, DeviceInfoSet, devInfo); cleanup: MyFree(InterfaceGuidString); - MyFree(ReferenceString); + if (ReferenceString) + MyFree(ReferenceString); MyFree(InterfaceSection); InterfaceGuidString = ReferenceString = InterfaceSection = NULL; Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface); diff --git a/reactos/dll/win32/setupapi/setupapi_private.h b/reactos/dll/win32/setupapi/setupapi_private.h index f527d7aa15a..09630a6e3f5 100644 --- a/reactos/dll/win32/setupapi/setupapi_private.h +++ b/reactos/dll/win32/setupapi/setupapi_private.h @@ -334,6 +334,10 @@ FreeFunctionPointer( IN HMODULE ModulePointer, IN PVOID FunctionPointer); +DWORD +WINAPI +pSetupStringFromGuid(LPGUID lpGUID, PWSTR pString, DWORD dwStringLen); + DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst); VOID WINAPI MyFree(LPVOID lpMem);