ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

newdev.c
Go to the documentation of this file.
00001 /*
00002  * New device installer (newdev.dll)
00003  *
00004  * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
00005  *           2005 Christoph von Wittich (Christoph@ActiveVB.de)
00006  *           2009 Colin Finck (colin@reactos.org)
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  */
00022 
00023 #include "newdev_private.h"
00024 
00025 WINE_DEFAULT_DEBUG_CHANNEL(newdev);
00026 
00027 /* Global variables */
00028 HINSTANCE hDllInstance;
00029 
00030 static BOOL
00031 SearchDriver(
00032     IN PDEVINSTDATA DevInstData,
00033     IN LPCWSTR Directory OPTIONAL,
00034     IN LPCWSTR InfFile OPTIONAL);
00035 
00036 /*
00037 * @implemented
00038 */
00039 BOOL WINAPI
00040 UpdateDriverForPlugAndPlayDevicesW(
00041     IN HWND hwndParent,
00042     IN LPCWSTR HardwareId,
00043     IN LPCWSTR FullInfPath,
00044     IN DWORD InstallFlags,
00045     OUT PBOOL bRebootRequired OPTIONAL)
00046 {
00047     DEVINSTDATA DevInstData;
00048     DWORD i;
00049     LPWSTR Buffer = NULL;
00050     DWORD BufferSize;
00051     LPCWSTR CurrentHardwareId; /* Pointer into Buffer */
00052     BOOL FoundHardwareId, FoundAtLeastOneDevice = FALSE;
00053     BOOL ret = FALSE;
00054 
00055     DevInstData.hDevInfo = INVALID_HANDLE_VALUE;
00056 
00057     TRACE("UpdateDriverForPlugAndPlayDevicesW(%p %s %s 0x%x %p)\n",
00058         hwndParent, debugstr_w(HardwareId), debugstr_w(FullInfPath), InstallFlags, bRebootRequired);
00059 
00060     /* FIXME: InstallFlags bRebootRequired ignored! */
00061 
00062     /* Check flags */
00063     if (InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE))
00064     {
00065         TRACE("Unknown flags: 0x%08lx\n", InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE));
00066         SetLastError(ERROR_INVALID_FLAGS);
00067         goto cleanup;
00068     }
00069 
00070     /* Enumerate all devices of the system */
00071     DevInstData.hDevInfo = SetupDiGetClassDevsW(NULL, NULL, hwndParent, DIGCF_ALLCLASSES | DIGCF_PRESENT);
00072     if (DevInstData.hDevInfo == INVALID_HANDLE_VALUE)
00073         goto cleanup;
00074     DevInstData.devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
00075     for (i = 0; ; i++)
00076     {
00077         if (!SetupDiEnumDeviceInfo(DevInstData.hDevInfo, i, &DevInstData.devInfoData))
00078         {
00079             if (GetLastError() != ERROR_NO_MORE_ITEMS)
00080             {
00081                 TRACE("SetupDiEnumDeviceInfo() failed with error 0x%x\n", GetLastError());
00082                 goto cleanup;
00083             }
00084             /* This error was expected */
00085             break;
00086         }
00087 
00088         /* Get Hardware ID */
00089         HeapFree(GetProcessHeap(), 0, Buffer);
00090         Buffer = NULL;
00091         BufferSize = 0;
00092         while (!SetupDiGetDeviceRegistryPropertyW(
00093             DevInstData.hDevInfo,
00094             &DevInstData.devInfoData,
00095             SPDRP_HARDWAREID,
00096             NULL,
00097             (PBYTE)Buffer,
00098             BufferSize,
00099             &BufferSize))
00100         {
00101             if (GetLastError() == ERROR_FILE_NOT_FOUND)
00102             {
00103                 Buffer = NULL;
00104                 break;
00105             }
00106             else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
00107             {
00108                 TRACE("SetupDiGetDeviceRegistryPropertyW() failed with error 0x%x\n", GetLastError());
00109                 goto cleanup;
00110             }
00111             /* This error was expected */
00112             HeapFree(GetProcessHeap(), 0, Buffer);
00113             Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize);
00114             if (!Buffer)
00115             {
00116                 TRACE("HeapAlloc() failed\n", GetLastError());
00117                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00118                 goto cleanup;
00119             }
00120         }
00121         if (Buffer == NULL)
00122             continue;
00123 
00124         /* Check if we match the given hardware ID */
00125         FoundHardwareId = FALSE;
00126         for (CurrentHardwareId = Buffer; *CurrentHardwareId != UNICODE_NULL; CurrentHardwareId += wcslen(CurrentHardwareId) + 1)
00127         {
00128             if (wcscmp(CurrentHardwareId, HardwareId) == 0)
00129             {
00130                 FoundHardwareId = TRUE;
00131                 break;
00132             }
00133         }
00134         if (!FoundHardwareId)
00135             continue;
00136 
00137         /* We need to try to update the driver of this device */
00138 
00139         /* Get Instance ID */
00140         HeapFree(GetProcessHeap(), 0, Buffer);
00141         Buffer = NULL;
00142         if (SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, NULL, 0, &BufferSize))
00143         {
00144             /* Error, as the output buffer should be too small */
00145             SetLastError(ERROR_GEN_FAILURE);
00146             goto cleanup;
00147         }
00148         else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
00149         {
00150             TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError());
00151             goto cleanup;
00152         }
00153         else if ((Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize * sizeof(WCHAR))) == NULL)
00154         {
00155             TRACE("HeapAlloc() failed\n", GetLastError());
00156             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00157             goto cleanup;
00158         }
00159         else if (!SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, Buffer, BufferSize, NULL))
00160         {
00161             TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError());
00162             goto cleanup;
00163         }
00164         TRACE("Trying to update the driver of %s\n", debugstr_w(Buffer));
00165 
00166         /* Search driver in the specified .inf file */
00167         if (!SearchDriver(&DevInstData, NULL, FullInfPath))
00168         {
00169             TRACE("SearchDriver() failed with error 0x%x\n", GetLastError());
00170             continue;
00171         }
00172 
00173         /* FIXME: HACK! We shouldn't check of ERROR_PRIVILEGE_NOT_HELD */
00174         //if (!InstallCurrentDriver(&DevInstData))
00175         if (!InstallCurrentDriver(&DevInstData) && GetLastError() != ERROR_PRIVILEGE_NOT_HELD)
00176         {
00177             TRACE("InstallCurrentDriver() failed with error 0x%x\n", GetLastError());
00178             continue;
00179         }
00180 
00181         FoundAtLeastOneDevice = TRUE;
00182     }
00183 
00184     if (FoundAtLeastOneDevice)
00185     {
00186         SetLastError(NO_ERROR);
00187         ret = TRUE;
00188     }
00189     else
00190     {
00191         TRACE("No device found with HardwareID %s\n", debugstr_w(HardwareId));
00192         SetLastError(ERROR_NO_SUCH_DEVINST);
00193     }
00194 
00195 cleanup:
00196     if (DevInstData.hDevInfo != INVALID_HANDLE_VALUE)
00197         SetupDiDestroyDeviceInfoList(DevInstData.hDevInfo);
00198     HeapFree(GetProcessHeap(), 0, Buffer);
00199     return ret;
00200 }
00201 
00202 /*
00203 * @implemented
00204 */
00205 BOOL WINAPI
00206 UpdateDriverForPlugAndPlayDevicesA(
00207     IN HWND hwndParent,
00208     IN LPCSTR HardwareId,
00209     IN LPCSTR FullInfPath,
00210     IN DWORD InstallFlags,
00211     OUT PBOOL bRebootRequired OPTIONAL)
00212 {
00213     BOOL Result;
00214     LPWSTR HardwareIdW = NULL;
00215     LPWSTR FullInfPathW = NULL;
00216 
00217     int len = MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, NULL, 0);
00218     HardwareIdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00219     if (!HardwareIdW)
00220     {
00221         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00222         return FALSE;
00223     }
00224     MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, HardwareIdW, len);
00225 
00226     len = MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, NULL, 0);
00227     FullInfPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00228     if (!FullInfPathW)
00229     {
00230         HeapFree(GetProcessHeap(), 0, HardwareIdW);
00231         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00232         return FALSE;
00233     }
00234     MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, FullInfPathW, len);
00235 
00236     Result = UpdateDriverForPlugAndPlayDevicesW(
00237         hwndParent,
00238         HardwareIdW,
00239         FullInfPathW,
00240         InstallFlags,
00241         bRebootRequired);
00242 
00243     HeapFree(GetProcessHeap(), 0, HardwareIdW);
00244     HeapFree(GetProcessHeap(), 0, FullInfPathW);
00245 
00246     return Result;
00247 }
00248 
00249 /* Directory and InfFile MUST NOT be specified simultaneously */
00250 static BOOL
00251 SearchDriver(
00252     IN PDEVINSTDATA DevInstData,
00253     IN LPCWSTR Directory OPTIONAL,
00254     IN LPCWSTR InfFile OPTIONAL)
00255 {
00256     SP_DEVINSTALL_PARAMS_W DevInstallParams = {0,};
00257     BOOL ret;
00258 
00259     DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
00260     if (!SetupDiGetDeviceInstallParamsW(DevInstData->hDevInfo, &DevInstData->devInfoData, &DevInstallParams))
00261     {
00262         TRACE("SetupDiGetDeviceInstallParams() failed with error 0x%x\n", GetLastError());
00263         return FALSE;
00264     }
00265     DevInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
00266 
00267     if (InfFile)
00268     {
00269         DevInstallParams.Flags |= DI_ENUMSINGLEINF;
00270         wcsncpy(DevInstallParams.DriverPath, InfFile, MAX_PATH);
00271     }
00272     else if (Directory)
00273     {
00274         DevInstallParams.Flags &= ~DI_ENUMSINGLEINF;
00275         wcsncpy(DevInstallParams.DriverPath, Directory, MAX_PATH);
00276     }
00277     else
00278     {
00279         DevInstallParams.Flags &= ~DI_ENUMSINGLEINF;
00280         *DevInstallParams.DriverPath = '\0';
00281     }
00282 
00283     ret = SetupDiSetDeviceInstallParamsW(
00284         DevInstData->hDevInfo,
00285         &DevInstData->devInfoData,
00286         &DevInstallParams);
00287     if (!ret)
00288     {
00289         TRACE("SetupDiSetDeviceInstallParams() failed with error 0x%x\n", GetLastError());
00290         return FALSE;
00291     }
00292 
00293     ret = SetupDiBuildDriverInfoList(
00294         DevInstData->hDevInfo,
00295         &DevInstData->devInfoData,
00296         SPDIT_COMPATDRIVER);
00297     if (!ret)
00298     {
00299         TRACE("SetupDiBuildDriverInfoList() failed with error 0x%x\n", GetLastError());
00300         return FALSE;
00301     }
00302 
00303     DevInstData->drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
00304     ret = SetupDiEnumDriverInfoW(
00305         DevInstData->hDevInfo,
00306         &DevInstData->devInfoData,
00307         SPDIT_COMPATDRIVER,
00308         0,
00309         &DevInstData->drvInfoData);
00310     if (!ret)
00311     {
00312         if (GetLastError() == ERROR_NO_MORE_ITEMS)
00313             return FALSE;
00314         TRACE("SetupDiEnumDriverInfo() failed with error 0x%x\n", GetLastError());
00315         return FALSE;
00316     }
00317 
00318     return TRUE;
00319 }
00320 
00321 static BOOL
00322 IsDots(IN LPCWSTR str)
00323 {
00324     if(wcscmp(str, L".") && wcscmp(str, L"..")) return FALSE;
00325     return TRUE;
00326 }
00327 
00328 static LPCWSTR
00329 GetFileExt(IN LPWSTR FileName)
00330 {
00331     LPCWSTR Dot;
00332 
00333     Dot = wcsrchr(FileName, '.');
00334     if (!Dot)
00335         return L"";
00336 
00337     return Dot;
00338 }
00339 
00340 static BOOL
00341 SearchDriverRecursive(
00342     IN PDEVINSTDATA DevInstData,
00343     IN LPCWSTR Path)
00344 {
00345     WIN32_FIND_DATAW wfd;
00346     WCHAR DirPath[MAX_PATH];
00347     WCHAR FileName[MAX_PATH];
00348     WCHAR FullPath[MAX_PATH];
00349     WCHAR LastDirPath[MAX_PATH] = L"";
00350     WCHAR PathWithPattern[MAX_PATH];
00351     BOOL ok = TRUE;
00352     BOOL retval = FALSE;
00353     HANDLE hFindFile = INVALID_HANDLE_VALUE;
00354 
00355     wcscpy(DirPath, Path);
00356 
00357     if (DirPath[wcslen(DirPath) - 1] != '\\')
00358         wcscat(DirPath, L"\\");
00359 
00360     wcscpy(PathWithPattern, DirPath);
00361     wcscat(PathWithPattern, L"\\*");
00362 
00363     for (hFindFile = FindFirstFileW(PathWithPattern, &wfd);
00364         ok && hFindFile != INVALID_HANDLE_VALUE;
00365         ok = FindNextFileW(hFindFile, &wfd))
00366     {
00367 
00368         wcscpy(FileName, wfd.cFileName);
00369         if (IsDots(FileName))
00370             continue;
00371 
00372         if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00373         {
00374             /* Recursive search */
00375             wcscpy(FullPath, DirPath);
00376             wcscat(FullPath, FileName);
00377             if (SearchDriverRecursive(DevInstData, FullPath))
00378             {
00379                 retval = TRUE;
00380                 /* We continue the search for a better driver */
00381             }
00382         }
00383         else
00384         {
00385             LPCWSTR pszExtension = GetFileExt(FileName);
00386 
00387             if ((_wcsicmp(pszExtension, L".inf") == 0) && (wcscmp(LastDirPath, DirPath) != 0))
00388             {
00389                 wcscpy(LastDirPath, DirPath);
00390 
00391                 if (wcslen(DirPath) > MAX_PATH)
00392                     /* Path is too long to be searched */
00393                     continue;
00394 
00395                 if (SearchDriver(DevInstData, DirPath, NULL))
00396                 {
00397                     retval = TRUE;
00398                     /* We continue the search for a better driver */
00399                 }
00400 
00401             }
00402         }
00403     }
00404 
00405     if (hFindFile != INVALID_HANDLE_VALUE)
00406         FindClose(hFindFile);
00407     return retval;
00408 }
00409 
00410 BOOL
00411 ScanFoldersForDriver(
00412     IN PDEVINSTDATA DevInstData)
00413 {
00414     BOOL result;
00415 
00416     /* Search in default location */
00417     result = SearchDriver(DevInstData, NULL, NULL);
00418 
00419     if (DevInstData->CustomSearchPath)
00420     {
00421         /* Search only in specified paths */
00422         /* We need to check all specified directories to be
00423          * sure to find the best driver for the device.
00424          */
00425         LPCWSTR Path;
00426         for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += wcslen(Path) + 1)
00427         {
00428             TRACE("Search driver in %s\n", debugstr_w(Path));
00429             if (wcslen(Path) == 2 && Path[1] == ':')
00430             {
00431                 if (SearchDriverRecursive(DevInstData, Path))
00432                     result = TRUE;
00433             }
00434             else
00435             {
00436                 if (SearchDriver(DevInstData, Path, NULL))
00437                     result = TRUE;
00438             }
00439         }
00440     }
00441 
00442     return result;
00443 }
00444 
00445 BOOL
00446 PrepareFoldersToScan(
00447     IN PDEVINSTDATA DevInstData,
00448     IN BOOL IncludeRemovableDevices,
00449     IN BOOL IncludeCustomPath,
00450     IN HWND hwndCombo OPTIONAL)
00451 {
00452     WCHAR drive[] = {'?',':',0};
00453     DWORD dwDrives = 0;
00454     DWORD i;
00455     UINT nType;
00456     DWORD CustomTextLength = 0;
00457     DWORD LengthNeeded = 0;
00458     LPWSTR Buffer;
00459 
00460     /* Calculate length needed to store the search paths */
00461     if (IncludeRemovableDevices)
00462     {
00463         dwDrives = GetLogicalDrives();
00464         for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1)
00465         {
00466             if (dwDrives & i)
00467             {
00468                 nType = GetDriveTypeW(drive);
00469                 if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM)
00470                 {
00471                     LengthNeeded += 3;
00472                 }
00473             }
00474         }
00475     }
00476     if (IncludeCustomPath)
00477     {
00478         CustomTextLength = 1 + ComboBox_GetTextLength(hwndCombo);
00479         LengthNeeded += CustomTextLength;
00480     }
00481 
00482     /* Allocate space for search paths */
00483     HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath);
00484     DevInstData->CustomSearchPath = Buffer = HeapAlloc(
00485         GetProcessHeap(),
00486         0,
00487         (LengthNeeded + 1) * sizeof(WCHAR));
00488     if (!Buffer)
00489     {
00490         TRACE("HeapAlloc() failed\n");
00491         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00492         return FALSE;
00493     }
00494 
00495     /* Fill search paths */
00496     if (IncludeRemovableDevices)
00497     {
00498         for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1)
00499         {
00500             if (dwDrives & i)
00501             {
00502                 nType = GetDriveTypeW(drive);
00503                 if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM)
00504                 {
00505                     Buffer += 1 + swprintf(Buffer, drive);
00506                 }
00507             }
00508         }
00509     }
00510     if (IncludeCustomPath)
00511     {
00512         Buffer += 1 + GetWindowTextW(hwndCombo, Buffer, CustomTextLength);
00513     }
00514     *Buffer = '\0';
00515 
00516     return TRUE;
00517 }
00518 
00519 BOOL
00520 InstallCurrentDriver(
00521     IN PDEVINSTDATA DevInstData)
00522 {
00523     BOOL ret;
00524 
00525     TRACE("Installing driver %s: %s\n",
00526         debugstr_w(DevInstData->drvInfoData.MfgName),
00527         debugstr_w(DevInstData->drvInfoData.Description));
00528 
00529     ret = SetupDiCallClassInstaller(
00530         DIF_SELECTBESTCOMPATDRV,
00531         DevInstData->hDevInfo,
00532         &DevInstData->devInfoData);
00533     if (!ret)
00534     {
00535         TRACE("SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV) failed with error 0x%x\n", GetLastError());
00536         return FALSE;
00537     }
00538 
00539     ret = SetupDiCallClassInstaller(
00540         DIF_ALLOW_INSTALL,
00541         DevInstData->hDevInfo,
00542         &DevInstData->devInfoData);
00543     if (!ret)
00544     {
00545         TRACE("SetupDiCallClassInstaller(DIF_ALLOW_INSTALL) failed with error 0x%x\n", GetLastError());
00546         return FALSE;
00547     }
00548 
00549     ret = SetupDiCallClassInstaller(
00550         DIF_NEWDEVICEWIZARD_PREANALYZE,
00551         DevInstData->hDevInfo,
00552         &DevInstData->devInfoData);
00553     if (!ret)
00554     {
00555         TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_PREANALYZE) failed with error 0x%x\n", GetLastError());
00556         return FALSE;
00557     }
00558 
00559     ret = SetupDiCallClassInstaller(
00560         DIF_NEWDEVICEWIZARD_POSTANALYZE,
00561         DevInstData->hDevInfo,
00562         &DevInstData->devInfoData);
00563     if (!ret)
00564     {
00565         TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_POSTANALYZE) failed with error 0x%x\n", GetLastError());
00566         return FALSE;
00567     }
00568 
00569     ret = SetupDiCallClassInstaller(
00570         DIF_INSTALLDEVICEFILES,
00571         DevInstData->hDevInfo,
00572         &DevInstData->devInfoData);
00573     if (!ret)
00574     {
00575         TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES) failed with error 0x%x\n", GetLastError());
00576         return FALSE;
00577     }
00578 
00579     ret = SetupDiCallClassInstaller(
00580         DIF_REGISTER_COINSTALLERS,
00581         DevInstData->hDevInfo,
00582         &DevInstData->devInfoData);
00583     if (!ret)
00584     {
00585         TRACE("SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed with error 0x%x\n", GetLastError());
00586         return FALSE;
00587     }
00588 
00589     ret = SetupDiCallClassInstaller(
00590         DIF_INSTALLINTERFACES,
00591         DevInstData->hDevInfo,
00592         &DevInstData->devInfoData);
00593     if (!ret)
00594     {
00595         TRACE("SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed with error 0x%x\n", GetLastError());
00596         return FALSE;
00597     }
00598 
00599     ret = SetupDiCallClassInstaller(
00600         DIF_INSTALLDEVICE,
00601         DevInstData->hDevInfo,
00602         &DevInstData->devInfoData);
00603     if (!ret)
00604     {
00605         TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed with error 0x%x\n", GetLastError());
00606         return FALSE;
00607     }
00608 
00609     ret = SetupDiCallClassInstaller(
00610         DIF_NEWDEVICEWIZARD_FINISHINSTALL,
00611         DevInstData->hDevInfo,
00612         &DevInstData->devInfoData);
00613     if (!ret)
00614     {
00615         TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL) failed with error 0x%x\n", GetLastError());
00616         return FALSE;
00617     }
00618 
00619     ret = SetupDiCallClassInstaller(
00620         DIF_DESTROYPRIVATEDATA,
00621         DevInstData->hDevInfo,
00622         &DevInstData->devInfoData);
00623     if (!ret)
00624     {
00625         TRACE("SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA) failed with error 0x%x\n", GetLastError());
00626         return FALSE;
00627     }
00628 
00629     return TRUE;
00630 }
00631 
00632 /*
00633 * @implemented
00634 */
00635 BOOL WINAPI
00636 DevInstallW(
00637     IN HWND hWndParent,
00638     IN HINSTANCE hInstance,
00639     IN LPCWSTR InstanceId,
00640     IN INT Show)
00641 {
00642     PDEVINSTDATA DevInstData = NULL;
00643     BOOL ret;
00644     DWORD config_flags;
00645     BOOL retval = FALSE;
00646 
00647     TRACE("(%p, %p, %s, %d)\n", hWndParent, hInstance, debugstr_w(InstanceId), Show);
00648 
00649     if (!IsUserAdmin())
00650     {
00651         /* XP kills the process... */
00652         ExitProcess(ERROR_ACCESS_DENIED);
00653     }
00654 
00655     DevInstData = HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA));
00656     if (!DevInstData)
00657     {
00658         TRACE("HeapAlloc() failed\n");
00659         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00660         goto cleanup;
00661     }
00662 
00663     /* Clear devinst data */
00664     ZeroMemory(DevInstData, sizeof(DEVINSTDATA));
00665     DevInstData->devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */
00666 
00667     /* Fill devinst data */
00668     DevInstData->hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
00669     if (DevInstData->hDevInfo == INVALID_HANDLE_VALUE)
00670     {
00671         TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError());
00672         goto cleanup;
00673     }
00674 
00675     DevInstData->devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
00676     ret = SetupDiOpenDeviceInfoW(
00677         DevInstData->hDevInfo,
00678         InstanceId,
00679         NULL,
00680         0, /* Open flags */
00681         &DevInstData->devInfoData);
00682     if (!ret)
00683     {
00684         TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n",
00685             GetLastError(), debugstr_w(InstanceId));
00686         DevInstData->devInfoData.cbSize = 0;
00687         goto cleanup;
00688     }
00689 
00690     SetLastError(ERROR_GEN_FAILURE);
00691     ret = SetupDiGetDeviceRegistryProperty(
00692         DevInstData->hDevInfo,
00693         &DevInstData->devInfoData,
00694         SPDRP_DEVICEDESC,
00695         &DevInstData->regDataType,
00696         NULL, 0,
00697         &DevInstData->requiredSize);
00698 
00699     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && DevInstData->regDataType == REG_SZ)
00700     {
00701         DevInstData->buffer = HeapAlloc(GetProcessHeap(), 0, DevInstData->requiredSize);
00702         if (!DevInstData->buffer)
00703         {
00704             TRACE("HeapAlloc() failed\n");
00705             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00706         }
00707         else
00708         {
00709             ret = SetupDiGetDeviceRegistryPropertyW(
00710                 DevInstData->hDevInfo,
00711                 &DevInstData->devInfoData,
00712                 SPDRP_DEVICEDESC,
00713                 &DevInstData->regDataType,
00714                 DevInstData->buffer, DevInstData->requiredSize,
00715                 &DevInstData->requiredSize);
00716         }
00717     }
00718     if (!ret)
00719     {
00720         TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n",
00721             GetLastError(), debugstr_w(InstanceId));
00722         goto cleanup;
00723     }
00724 
00725     if (SetupDiGetDeviceRegistryPropertyW(
00726         DevInstData->hDevInfo,
00727         &DevInstData->devInfoData,
00728         SPDRP_CONFIGFLAGS,
00729         NULL,
00730         (BYTE *)&config_flags,
00731         sizeof(config_flags),
00732         NULL))
00733     {
00734         if (config_flags & CONFIGFLAG_FAILEDINSTALL)
00735         {
00736             /* The device is disabled */
00737             TRACE("Device is disabled\n");
00738             retval = TRUE;
00739             goto cleanup;
00740         }
00741     }
00742 
00743     TRACE("Installing %s (%s)\n", debugstr_w((PCWSTR)DevInstData->buffer), debugstr_w(InstanceId));
00744 
00745     /* Search driver in default location and removable devices */
00746     if (!PrepareFoldersToScan(DevInstData, FALSE, FALSE, NULL))
00747     {
00748         TRACE("PrepareFoldersToScan() failed with error 0x%lx\n", GetLastError());
00749         goto cleanup;
00750     }
00751     if (ScanFoldersForDriver(DevInstData))
00752     {
00753         /* Driver found ; install it */
00754         retval = InstallCurrentDriver(DevInstData);
00755         TRACE("InstallCurrentDriver() returned %d\n", retval);
00756         if (retval && Show != SW_HIDE)
00757         {
00758             /* Should we display the 'Need to reboot' page? */
00759             SP_DEVINSTALL_PARAMS installParams;
00760             installParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
00761             if (SetupDiGetDeviceInstallParams(
00762                 DevInstData->hDevInfo,
00763                 &DevInstData->devInfoData,
00764                 &installParams))
00765             {
00766                 if (installParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))
00767                 {
00768                     TRACE("Displaying 'Reboot' wizard page\n");
00769                     retval = DisplayWizard(DevInstData, hWndParent, IDD_NEEDREBOOT);
00770                 }
00771             }
00772         }
00773         goto cleanup;
00774     }
00775     else if (Show == SW_HIDE)
00776     {
00777         /* We can't show the wizard. Fail the install */
00778         TRACE("No wizard\n");
00779         goto cleanup;
00780     }
00781 
00782     /* Prepare the wizard, and display it */
00783     TRACE("Need to show install wizard\n");
00784     retval = DisplayWizard(DevInstData, hWndParent, IDD_WELCOMEPAGE);
00785 
00786 cleanup:
00787     if (DevInstData)
00788     {
00789         if (DevInstData->devInfoData.cbSize != 0)
00790         {
00791             if (!SetupDiDestroyDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER))
00792                 TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError());
00793         }
00794         if (DevInstData->hDevInfo != INVALID_HANDLE_VALUE)
00795         {
00796             if (!SetupDiDestroyDeviceInfoList(DevInstData->hDevInfo))
00797                 TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError());
00798         }
00799         HeapFree(GetProcessHeap(), 0, DevInstData->buffer);
00800         HeapFree(GetProcessHeap(), 0, DevInstData);
00801     }
00802 
00803     return retval;
00804 }
00805 
00806 /*
00807 * @implemented
00808 */
00809 BOOL WINAPI
00810 ClientSideInstallW(
00811     IN HWND hWndOwner,
00812     IN DWORD dwUnknownFlags,
00813     IN LPWSTR lpNamedPipeName)
00814 {
00815     BOOL ReturnValue = FALSE;
00816     BOOL ShowWizard;
00817     DWORD BytesRead;
00818     DWORD Value;
00819     HANDLE hPipe = INVALID_HANDLE_VALUE;
00820     PWSTR DeviceInstance = NULL;
00821     PWSTR InstallEventName = NULL;
00822 
00823     /* Open the pipe */
00824     hPipe = CreateFileW(lpNamedPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00825 
00826     if(hPipe == INVALID_HANDLE_VALUE)
00827     {
00828         ERR("CreateFileW failed with error %u\n", GetLastError());
00829         goto cleanup;
00830     }
00831 
00832     /* Read the data. Some is just included for compatibility with Windows right now and not yet used by ReactOS.
00833        See umpnpmgr for more details. */
00834     if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL))
00835     {
00836         ERR("ReadFile failed with error %u\n", GetLastError());
00837         goto cleanup;
00838     }
00839 
00840     InstallEventName = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value);
00841 
00842     if(!ReadFile(hPipe, InstallEventName, Value, &BytesRead, NULL))
00843     {
00844         ERR("ReadFile failed with error %u\n", GetLastError());
00845         goto cleanup;
00846     }
00847 
00848     /* I couldn't figure out what the following value means under Windows XP.
00849        Therefore I used it in umpnpmgr to pass the ShowWizard variable. */
00850     if(!ReadFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesRead, NULL))
00851     {
00852         ERR("ReadFile failed with error %u\n", GetLastError());
00853         goto cleanup;
00854     }
00855 
00856     /* Next one is again size in bytes of the following string */
00857     if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL))
00858     {
00859         ERR("ReadFile failed with error %u\n", GetLastError());
00860         goto cleanup;
00861     }
00862 
00863     DeviceInstance = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value);
00864 
00865     if(!ReadFile(hPipe, DeviceInstance, Value, &BytesRead, NULL))
00866     {
00867         ERR("ReadFile failed with error %u\n", GetLastError());
00868         goto cleanup;
00869     }
00870 
00871     ReturnValue = DevInstallW(NULL, NULL, DeviceInstance, ShowWizard ? SW_SHOWNOACTIVATE : SW_HIDE);
00872 
00873 cleanup:
00874     if(hPipe != INVALID_HANDLE_VALUE)
00875         CloseHandle(hPipe);
00876 
00877     if(InstallEventName)
00878         HeapFree(GetProcessHeap(), 0, InstallEventName);
00879 
00880     if(DeviceInstance)
00881         HeapFree(GetProcessHeap(), 0, DeviceInstance);
00882 
00883     return ReturnValue;
00884 }
00885 
00886 BOOL WINAPI
00887 DllMain(
00888     IN HINSTANCE hInstance,
00889     IN DWORD dwReason,
00890     IN LPVOID lpReserved)
00891 {
00892     if (dwReason == DLL_PROCESS_ATTACH)
00893     {
00894         INITCOMMONCONTROLSEX InitControls;
00895 
00896         DisableThreadLibraryCalls(hInstance);
00897 
00898         InitControls.dwSize = sizeof(INITCOMMONCONTROLSEX);
00899         InitControls.dwICC = ICC_PROGRESS_CLASS;
00900         InitCommonControlsEx(&InitControls);
00901         hDllInstance = hInstance;
00902     }
00903 
00904     return TRUE;
00905 }

Generated on Fri May 25 2012 04:23:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.