Implement parts of SetupDiInstallDevice
Modified: trunk/reactos/lib/setupapi/devinst.c

Modified: trunk/reactos/lib/setupapi/devinst.c
--- trunk/reactos/lib/setupapi/devinst.c	2005-09-26 11:37:32 UTC (rev 18088)
+++ trunk/reactos/lib/setupapi/devinst.c	2005-09-26 11:39:24 UTC (rev 18089)
@@ -4377,22 +4377,227 @@
     IN HDEVINFO DeviceInfoSet,
     IN PSP_DEVINFO_DATA DeviceInfoData)
 {
+    struct DriverInfoElement *DriverInfo;
+    struct DeviceInfoSet *DevInfoSet = (struct DeviceInfoSet *)DeviceInfoSet;
+    struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+    SYSTEMTIME DriverDate;
+    WCHAR SectionName[MAX_PATH];
+    DWORD SectionNameLength = 0;
+    BOOL Result = FALSE;
+    INFCONTEXT ContextService;
+    UINT Flags;
+    DWORD RequiredSize;
+    HINF hInf = NULL;
+    LPCWSTR AssociatedService = NULL;
+    BOOL RebootRequired = FALSE;
+    HKEY hEnumKey, hKey;
+    LONG rc;
+
     TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
 
-    /* Steps to follow:
-     * 0. If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit
-     * 1. Create driver key and write InfPath and ProviderName
-     * 2a Process inf sections: {DDInstall}, {DDInstall}.HW [SetupDiOpenDevRegKey]
-     *  b Process {DDInstall}.LogConfigOverride if present [SetupDiOpenDevRegKey]
-     *  c Process {DDInstall}.Services [SetupDiOpenDevRegKey]
-     * 3. Copy inf file to Inf\ directory [SetupCopyOEMInf]
-     * 4. Install other waiting files
-     * 5. Load the driver/Call AddDevice
-     * 6. Send IRP_MN_START_DEVICE if DI_NEEDRESTART, DI_NEEDREBOOT and DI_DONOTCALLCONFIGMG are not set
-     */
+    if (!DeviceInfoSet)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+        SetLastError(ERROR_INVALID_HANDLE);
+    else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+        SetLastError(ERROR_INVALID_HANDLE);
+    else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+    else if (DeviceInfoData && ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver == NULL)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver == NULL)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else
+        Result = TRUE;
 
-    FIXME("SetupDiInstallDevice not implemented. Doing nothing\n");
-    //SetLastError(ERROR_GEN_FAILURE);
-    //return FALSE;
+    if (!Result)
+    {
+        /* One parameter is bad */
+        return FALSE;
+    }
+
+    /* FIXME: If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit */
+
+    if (DeviceInfoData)
+        DriverInfo = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->SelectedDriver;
+    else
+        DriverInfo = ((struct DeviceInfoSet *)DeviceInfoSet)->SelectedDriver;
+    FileTimeToSystemTime(&DriverInfo->Info.DriverDate, &DriverDate);
+
+    hInf = SetupOpenInfFileW(DriverInfo->InfPath, NULL, INF_STYLE_WIN4, NULL);
+    if (hInf == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    Result = SetupDiGetActualSectionToInstallW(hInf, DriverInfo->InfSection,
+        SectionName, MAX_PATH, &SectionNameLength, NULL);
+    if (!Result || SectionNameLength > MAX_PATH - 9)
+    {
+        SetupCloseInfFile(hInf);
+        return FALSE;
+    }
+
+    /* Create driver key information */
+    FIXME("FIXME: Create driver key information\n");
+    
+    /* Write information to driver key */
+    FIXME("FIXME: Write information to driver key\n");
+    FIXME("DriverDate      : '%u-%u-%u'\n", 0, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
+    FIXME("DriverDateData  :"); { ULONG i; for (i = 0; i < sizeof(DriverInfo->Info.DriverDate); i++) DbgPrint(" %02x", ((PCHAR)&DriverInfo->Info.DriverDate)[i] & 0xff); } DbgPrint("\n");
+    FIXME("DriverDesc      : '%S'\n", DriverInfo->Info.Description);
+    FIXME("DriverVersion   : '%u.%u.%u.%u'\n", DriverInfo->Info.DriverVersion & 0xff, (DriverInfo->Info.DriverVersion >> 8) & 0xff, (DriverInfo->Info.DriverVersion >> 16) & 0xff, (DriverInfo->Info.DriverVersion >> 24) & 0xff);
+    FIXME("InfPath         : '%S'\n", DriverInfo->InfPath);
+    FIXME("InfSection      : '%S'\n", DriverInfo->InfSection); /* FIXME: remove extension */
+    FIXME("InfSectionExt   : '%S'\n", L"???"); /* FIXME */
+    FIXME("MatchingDeviceId: '%S'\n", L"???"); /* FIXME */
+    FIXME("ProviderName    : '%S'\n", DriverInfo->Info.ProviderName);
+
+    /* Install services */
+    wcscat(SectionName, L".Services");
+    Result = SetupFindFirstLineW(hInf, SectionName, NULL, &ContextService);
+    while (Result)
+    {
+        LPWSTR ServiceName = NULL;
+        LPWSTR ServiceSection = NULL;
+
+        Result = SetupGetStringFieldW(
+            &ContextService,
+            1, /* Field index */
+            NULL, 0,
+            &RequiredSize);
+        if (!Result)
+            goto cleanup;
+        if (RequiredSize > 0)
+        {
+            /* We got the needed size for the buffer */
+            ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+            if (!ServiceName)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                goto cleanup;
+            }
+            Result = SetupGetStringFieldW(
+                &ContextService,
+                1, /* Field index */
+                ServiceName, RequiredSize,
+                &RequiredSize);
+            if (!Result)
+                goto cleanup;
+        }
+        Result = SetupGetIntField(
+            &ContextService,
+            2, /* Field index */
+            &Flags);
+        if (!Result)
+        {
+            /* The field may be empty. Ignore the error */
+            Flags = 0;
+        }
+        Result = SetupGetStringFieldW(
+            &ContextService,
+            3, /* Field index */
+            NULL, 0,
+            &RequiredSize);
+        if (!Result)
+            goto cleanup;
+        if (RequiredSize > 0)
+        {
+            /* We got the needed size for the buffer */
+            ServiceSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
+            if (!ServiceSection)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+               goto cleanup;
+            }
+            Result = SetupGetStringFieldW(
+                &ContextService,
+                3, /* Field index */
+                ServiceSection, RequiredSize,
+               &RequiredSize);
+            if (!Result)
+               goto cleanup;
+        }
+        SetLastError(ERROR_SUCCESS);
+        Result = SetupInstallServicesFromInfSectionExW(hInf, ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, NULL, NULL);
+        if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
+        {
+            AssociatedService = ServiceName;
+            ServiceName = NULL;
+            if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
+                RebootRequired = TRUE;
+        }
+cleanup:
+        HeapFree(GetProcessHeap(), 0, ServiceName);
+        HeapFree(GetProcessHeap(), 0, ServiceSection);
+        if (!Result)
+        {
+            HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
+            SetupCloseInfFile(hInf);
+            return FALSE;
+        }
+        Result = SetupFindNextLine(&ContextService, &ContextService);
+    }
+
+    /* Copy .inf file to Inf\ directory */
+    FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /* SetupCopyOEMInf */
+
+    /* Write information to enum key */
+    rc = RegOpenKeyExW(DevInfoSet->HKLM,
+        EnumKeyName,
+        0,
+        KEY_ENUMERATE_SUB_KEYS,
+        &hEnumKey);
+    if (rc != ERROR_SUCCESS)
+    {
+       SetLastError(rc);
+       HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
+       SetupCloseInfFile(hInf);
+       return FALSE;
+    }
+    rc = RegOpenKeyExW(
+        hEnumKey,
+        DevInfo->DeviceName,
+        0, /* Options */
+        KEY_SET_VALUE,
+        &hKey);
+    RegCloseKey(hEnumKey);
+    if (rc != ERROR_SUCCESS)
+    {
+       SetLastError(rc);
+       HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
+       SetupCloseInfFile(hInf);
+       return FALSE;
+    }
+    FIXME("FIXME: Write information to enum key\n");
+    FIXME("ParentIdPrefix  : '%S'\n", L"0000"); /* FIXME */
+    //FIXME("Service         : '%S'\n", AssociatedService);
+    FIXME("Class           : '%S'\n", L"???"); /* FIXME: SetupDiGetINFClass */
+    FIXME("ClassGUID       : '%S'\n", L"???"); /* FIXME: SetupDiGetINFClass */
+    //FIXME("DeviceDesc      : '%S'\n", DriverInfo->Info.Description);
+    FIXME("Driver          : '%S'\n", L"???"); /* FIXME: autogenerated key */
+    //FIXME("Mfg             : '%S'\n", DriverInfo->Info.MfgName);
+    rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
+    if (rc == ERROR_SUCCESS)
+        rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)DriverInfo->Info.Description, (wcslen(DriverInfo->Info.Description) + 1) * sizeof(WCHAR));
+    if (rc == ERROR_SUCCESS)
+        rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)DriverInfo->Info.MfgName, (wcslen(DriverInfo->Info.MfgName) + 1) * sizeof(WCHAR));
+    RegCloseKey(hKey);
+    if (rc != ERROR_SUCCESS)
+    {
+       SetLastError(rc);
+       HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
+       SetupCloseInfFile(hInf);
+       return FALSE;
+    }
+
+    /* Load the driver/call AddDevice */
+    FIXME("FIXME: Load the driver/call AddDevice\n");
+
+    /* Send IRP_MN_START_DEVICE if needed */
+    //if (!RebootRequired && !(Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
+        FIXME("FIXME: Send IRP_MN_START_DEVICE\n");
+
+    /* End of installation */
+    HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
+    SetupCloseInfFile(hInf);
     return TRUE;
 }