install2.c
上传用户:xhy777
上传日期:2007-02-14
资源大小:24088k
文件大小:76k
源码类别:

系统编程

开发平台:

Visual C++

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include <tchar.h>
  4. #include <initguid.h>
  5. #include <devguid.h>
  6. // temporary extern defition from newdev.c
  7. typedef
  8. BOOL
  9. (*PINSTALLNEWDEVICE)(
  10.    HWND hwndParent,
  11.    LPGUID ClassGuid,
  12.    PDWORD Reboot
  13.    );
  14. ULONG PreConfigured;
  15. ULONG KeepEnabled;
  16. BOOL
  17. CALLBACK
  18. AddPropSheetPageProc(
  19.     IN HPROPSHEETPAGE hpage,
  20.     IN LPARAM lParam
  21.    )
  22. {
  23.     *((HPROPSHEETPAGE *)lParam) = hpage;
  24.     return TRUE;
  25. }
  26. #define LEGACY_DETECT 1
  27. #define REPORT_DEVICE 2
  28. /***************************************************************************/
  29. /***************************************************************************/
  30. /**                                                                       **/
  31. /**                      Service Controller stuff                         **/
  32. /**                                                                       **/
  33. /***************************************************************************/
  34. /***************************************************************************/
  35. VOID
  36. DeskSCSetServiceDemandStart(
  37.     LPTSTR ServiceName
  38.     )
  39. {
  40.     SC_HANDLE SCMHandle;
  41.     SC_HANDLE ServiceHandle;
  42.     ULONG     Attempts;
  43.     SC_LOCK   SCLock = NULL;
  44.     ULONG                  ServiceConfigSize = 0;
  45.     LPQUERY_SERVICE_CONFIG ServiceConfig;
  46.     TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart for service %ws calledn",
  47.              ServiceName);
  48.     //
  49.     // Pretty stright-forward :
  50.     //
  51.     // Open the service controller
  52.     // Open the service
  53.     // Change the service.
  54.     //
  55.     if (SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))
  56.     {
  57.         if (ServiceHandle = OpenService(SCMHandle, ServiceName, SERVICE_ALL_ACCESS))
  58.         {
  59.             TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart SC Managr handles opendedn");
  60.             QueryServiceConfig(ServiceHandle,
  61.                                NULL,
  62.                                0,
  63.                                &ServiceConfigSize);
  64.             ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
  65.             TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart buffer size = %dn", ServiceConfigSize);
  66.             if (ServiceConfig = (LPQUERY_SERVICE_CONFIG)
  67.                                  LocalAlloc(LPTR, ServiceConfigSize))
  68.             {
  69.                 if (QueryServiceConfig(ServiceHandle,
  70.                                        ServiceConfig,
  71.                                        ServiceConfigSize,
  72.                                        &ServiceConfigSize))
  73.                 {
  74.                     TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart Queried Config infon");
  75.                     //
  76.                     // The service exists.  Check that it's not disabled.
  77.                     //
  78.                     if (ServiceConfig->dwStartType == SERVICE_DISABLED) {
  79.                         ASSERT(FALSE);
  80.                     }
  81.                     //
  82.                     // Attempt to acquite the database lock.
  83.                     //
  84.                     for (Attempts = 20;
  85.                          ((SCLock = LockServiceDatabase(SCMHandle)) == NULL) &&
  86.                              Attempts;
  87.                          Attempts--)
  88.                     {
  89.                         TraceMsg(TF_GENERAL, "Install - Lock SC database lockedn");
  90.                         Sleep(500);
  91.                     }
  92.                     //
  93.                     // Change the service to demand start
  94.                     //
  95.                     if (ChangeServiceConfig(ServiceHandle,
  96.                                             SERVICE_NO_CHANGE,
  97.                                             SERVICE_DEMAND_START,
  98.                                             SERVICE_NO_CHANGE,
  99.                                             NULL,
  100.                                             NULL,
  101.                                             NULL,
  102.                                             NULL,
  103.                                             NULL,
  104.                                             NULL,
  105.                                             NULL))
  106.                     {
  107.                         TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart SC manager succeededn");
  108.                     }
  109.                     else
  110.                     {
  111.                         TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart SC manager failed : %dn",
  112.                                         GetLastError());
  113.                     }
  114.                     if (SCLock)
  115.                     {
  116.                         TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart Unlock databasen");
  117.                         UnlockServiceDatabase(SCLock);
  118.                     }
  119.                 }
  120.                 LocalFree(ServiceConfig);
  121.             }
  122.             CloseServiceHandle(ServiceHandle);
  123.         }
  124.         CloseServiceHandle(SCMHandle);
  125.     }
  126.     TraceMsg(TF_GENERAL, "DeskSCSetServiceDemandStart Leaven");
  127. }
  128. DWORD
  129. DeskSCStartService(
  130.     LPTSTR ServiceName
  131.     )
  132. {
  133.     SC_HANDLE SCMHandle;
  134.     SC_HANDLE ServiceHandle;
  135.     DWORD     dwRet = ERROR_SERVICE_NEVER_STARTED;
  136.     TraceMsg(TF_GENERAL, "DeskSCStartService for service %ws calledn",
  137.              ServiceName);
  138.     //
  139.     // Pretty stright-forward :
  140.     //
  141.     // Open the service controller
  142.     // Open the service
  143.     // Change the service.
  144.     //
  145.     if (SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))
  146.     {
  147.         if (ServiceHandle = OpenService(SCMHandle, ServiceName, SERVICE_ALL_ACCESS))
  148.         {
  149.             if (StartService(ServiceHandle, 0, NULL))
  150.             {
  151.                 dwRet = NO_ERROR;
  152.             }
  153.             else
  154.             {
  155.                 TraceMsg(TF_GENERAL, " StartService failed %dn", GetLastError());
  156.             }
  157.             CloseServiceHandle(ServiceHandle);
  158.         }
  159.         CloseServiceHandle(SCMHandle);
  160.     }
  161.     TraceMsg(TF_GENERAL, "DeskSCStartService Leave with status %wsn",
  162.              dwRet ? L"ERROR_SERVICE_NEVER_STARTED" : L"NO_ERROR");
  163.     return dwRet;
  164. }
  165. BOOL
  166. DeskSCStopService(
  167.     LPTSTR ServiceName
  168.     )
  169. {
  170.     SC_HANDLE      SCMHandle;
  171.     SC_HANDLE      ServiceHandle;
  172.     BOOL           bRet = FALSE;
  173.     SERVICE_STATUS ServiceStatus;
  174.     TraceMsg(TF_GENERAL, "DeskSCStopService for service %ws calledn",
  175.              ServiceName);
  176.     //
  177.     // Pretty stright-forward :
  178.     //
  179.     // Open the service controller
  180.     // Open the service
  181.     // Change the service.
  182.     //
  183.     if (SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))
  184.     {
  185.         if (ServiceHandle = OpenService(SCMHandle, ServiceName, SERVICE_ALL_ACCESS))
  186.         {
  187.             if (ControlService(ServiceHandle,
  188.                                SERVICE_CONTROL_STOP,
  189.                                &ServiceStatus))
  190.             {
  191.                 bRet= TRUE;
  192.             }
  193.             else
  194.             {
  195.                 TraceMsg(TF_GENERAL, " StopService failed %dn", GetLastError());
  196.             }
  197.             CloseServiceHandle(ServiceHandle);
  198.         }
  199.         CloseServiceHandle(SCMHandle);
  200.     }
  201.     TraceMsg(TF_GENERAL, "DeskSCStopService Leave with status %wsn",
  202.              bRet ? L"TRUE" : L"FALSE");
  203.     return bRet;
  204. }
  205. BOOL
  206. DeskSCDeleteService(
  207.     LPTSTR ServiceName
  208.     )
  209. {
  210.     SC_HANDLE      SCMHandle;
  211.     SC_HANDLE      ServiceHandle;
  212.     BOOL           bRet = FALSE;
  213.     TraceMsg(TF_GENERAL, "DeskSCDeleteService for service %ws calledn",
  214.              ServiceName);
  215.     //
  216.     // Pretty stright-forward :
  217.     //
  218.     // Open the service controller
  219.     // Open the service
  220.     // Change the service.
  221.     //
  222.     if (SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))
  223.     {
  224.         if (ServiceHandle = OpenService(SCMHandle, ServiceName, SERVICE_ALL_ACCESS))
  225.         {
  226.             if (DeleteService(ServiceHandle))
  227.             {
  228.                 bRet= TRUE;
  229.             }
  230.             else
  231.             {
  232.                 TraceMsg(TF_GENERAL, "DeleteService failed %dn", GetLastError());
  233.             }
  234.             CloseServiceHandle(ServiceHandle);
  235.         }
  236.         CloseServiceHandle(SCMHandle);
  237.     }
  238.     TraceMsg(TF_GENERAL, "DeskSCDeleteService Leave with status %wsn",
  239.              bRet ? L"TRUE" : L"FALSE");
  240.     return bRet;
  241. }
  242. /***************************************************************************/
  243. /***************************************************************************/
  244. /**                                                                       **/
  245. /**                      Service Installation                             **/
  246. /**                                                                       **/
  247. /***************************************************************************/
  248. /***************************************************************************/
  249. BOOL
  250. DeskIsPnPDriver(
  251.     IN HDEVINFO         hDevInfo,
  252.     IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL
  253.     )
  254. {
  255.     SP_DRVINFO_DATA        DriverInfoData;
  256.     SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  257.     DWORD                  cbOutputSize = 0;
  258.     HANDLE                 InfFileHandle;
  259.     DWORD                  PnPDriver = 0;
  260.     TCHAR                  szSoftwareSection[LINE_LEN];
  261.     INFCONTEXT             tmpContext;
  262.     TraceMsg(TF_GENERAL, "DeskIsPnPDrivern");
  263.     //
  264.     // Retrieve information about the driver node selected for this device.
  265.     //
  266.     DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  267.     if (!SetupDiGetSelectedDriver(hDevInfo,
  268.                                   pDeviceInfoData,
  269.                                   &DriverInfoData))
  270.     {
  271.         TraceMsg(TF_GENERAL, "SetupDiGetSelectedDriver Error %dn", GetLastError());
  272.         return GetLastError();
  273.     }
  274.     DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  275.     if (!(SetupDiGetDriverInfoDetail(hDevInfo,
  276.                                      pDeviceInfoData,
  277.                                      &DriverInfoData,
  278.                                      &DriverInfoDetailData,
  279.                                      DriverInfoDetailData.cbSize,
  280.                                      &cbOutputSize)) &&
  281.         (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  282.     {
  283.         TraceMsg(TF_GENERAL, "SetupDiGetDriverInfoDetail Error %dn", GetLastError());
  284.         return GetLastError();
  285.     }
  286.     //
  287.     // open the inf so we can run the sections in the inf, more or less
  288.     // manually.
  289.     //
  290.     InfFileHandle = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
  291.                                      NULL,
  292.                                      INF_STYLE_WIN4,
  293.                                      NULL);
  294.     if (InfFileHandle == INVALID_HANDLE_VALUE)
  295.     {
  296.         TraceMsg(TF_GENERAL, "SetupOpenInfFile Error %dn", INVALID_HANDLE_VALUE);
  297.         return ERROR_INVALID_PARAMETER;
  298.     }
  299.     //
  300.     // Get any interesting configuration data for the inf file.
  301.     //
  302.     wsprintf(szSoftwareSection,
  303.              TEXT("%ws.GeneralConfigData"),
  304.              DriverInfoDetailData.SectionName);
  305.     if (SetupFindFirstLine(InfFileHandle,
  306.                            szSoftwareSection,
  307.                            TEXT("PnPEnabled"),
  308.                            &tmpContext))
  309.     {
  310.         SetupGetIntField(&tmpContext,
  311.                          1,
  312.                          &PnPDriver);
  313.     }
  314.     TraceMsg(TF_GENERAL, "DeskIsPnPDriver returns %dn", (PnPDriver != 0));
  315.     return (PnPDriver != 0);
  316. }
  317. DWORD
  318. DeskInstallServiceExtensions(
  319.     IN HWND                    hwnd,
  320.     IN HDEVINFO                hDevInfo,
  321.     IN PSP_DEVINFO_DATA        pDeviceInfoData,
  322.     IN PSP_DRVINFO_DATA        DriverInfoData,
  323.     IN PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData,
  324.     IN LPTSTR                  pServiceName,
  325.     IN DWORD                   dwDetect
  326.     )
  327. {
  328.     DWORD retError = NO_ERROR;
  329.     HINF       InfFileHandle;
  330.     PVOID      Context;
  331.     INFCONTEXT tmpContext;
  332.     TCHAR szSoftwareSection[LINE_LEN];
  333.     ULONG maxmem;
  334.     ULONG numDev;
  335.     ULONG PnPDriver;
  336.     SP_DEVINSTALL_PARAMS   DeviceInstallParams;
  337.     TCHAR keyName[LINE_LEN];
  338.     DWORD disposition;
  339.     HKEY  hkey;
  340.     BOOL  bSetSoftwareKey;
  341.     TraceMsg(TF_GENERAL, "DeskInstallServiceExtensions calledn");
  342.     //
  343.     // open the inf so we can run the sections in the inf, more or less
  344.     // manually.
  345.     //
  346.     InfFileHandle = SetupOpenInfFile(DriverInfoDetailData->InfFileName,
  347.                                      NULL,
  348.                                      INF_STYLE_WIN4,
  349.                                      NULL);
  350.     if (InfFileHandle == INVALID_HANDLE_VALUE)
  351.     {
  352.         TraceMsg(TF_GENERAL, "SetupOpenInfFile Error %dn", INVALID_HANDLE_VALUE);
  353.         return ERROR_INVALID_PARAMETER;
  354.     }
  355.     //
  356.     // Get any interesting configuration data for the inf file.
  357.     //
  358.     maxmem = 8;
  359.     numDev = 1;
  360.     PreConfigured = 0;
  361.     KeepEnabled = 0;
  362.     PnPDriver = 0;
  363.     wsprintf(szSoftwareSection,
  364.              TEXT("%ws.GeneralConfigData"),
  365.              DriverInfoDetailData->SectionName);
  366.     if (SetupFindFirstLine(InfFileHandle,
  367.                            szSoftwareSection,
  368.                            TEXT("MaximumNumberOfDevices"),
  369.                            &tmpContext))
  370.     {
  371.         SetupGetIntField(&tmpContext,
  372.                          1,
  373.                          &numDev);
  374.     }
  375.     if (SetupFindFirstLine(InfFileHandle,
  376.                            szSoftwareSection,
  377.                            TEXT("MaximumDeviceMemoryConfiguration"),
  378.                            &tmpContext))
  379.     {
  380.         SetupGetIntField(&tmpContext,
  381.                          1,
  382.                          &maxmem);
  383.     }
  384.     if (SetupFindFirstLine(InfFileHandle,
  385.                            szSoftwareSection,
  386.                            TEXT("PreConfiguredSettings"),
  387.                            &tmpContext))
  388.     {
  389.         SetupGetIntField(&tmpContext,
  390.                          1,
  391.                          &PreConfigured);
  392.     }
  393.     if (SetupFindFirstLine(InfFileHandle,
  394.                            szSoftwareSection,
  395.                            TEXT("KeepExistingDriverEnabled"),
  396.                            &tmpContext))
  397.     {
  398.         SetupGetIntField(&tmpContext,
  399.                          1,
  400.                          &KeepEnabled);
  401.     }
  402.     if (SetupFindFirstLine(InfFileHandle,
  403.                            szSoftwareSection,
  404.                            TEXT("PnPEnabled"),
  405.                            &tmpContext))
  406.     {
  407.         SetupGetIntField(&tmpContext,
  408.                          1,
  409.                          &PnPDriver);
  410.     }
  411.     //
  412.     // Write the PnP and Detect configuration information to the registry.
  413.     //
  414.     wsprintf(keyName,
  415.              TEXT("System\CurrentControlSet\Services\%ws"),
  416.              pServiceName, numDev);
  417.     if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  418.                        keyName,
  419.                        0,
  420.                        NULL,
  421.                        REG_OPTION_NON_VOLATILE,
  422.                        KEY_READ | KEY_WRITE,
  423.                        NULL,
  424.                        &hkey,
  425.                        &disposition) == ERROR_SUCCESS)
  426.     {
  427.         ULONG Value = 1;
  428.         if (PnPDriver)
  429.         {
  430.             RegSetValueEx(hkey,
  431.                           TEXT("PnPEnabled"),
  432.                           0,
  433.                           REG_DWORD,
  434.                           (LPBYTE) (&Value),
  435.                           SIZEOF(ULONG) );
  436.         }
  437.         if (dwDetect == LEGACY_DETECT)
  438.         {
  439.             RegSetValueEx(hkey,
  440.                           TEXT("LegacyDetect"),
  441.                           0,
  442.                           REG_DWORD,
  443.                           (LPBYTE) (&Value),
  444.                           SIZEOF(ULONG) );
  445.         }
  446.         else if (dwDetect == REPORT_DEVICE)
  447.         {
  448.             RegSetValueEx(hkey,
  449.                           TEXT("ReportDevice"),
  450.                           0,
  451.                           REG_DWORD,
  452.                           (LPBYTE) (&Value),
  453.                           SIZEOF(ULONG) );
  454.         }
  455.         RegCloseKey(hkey);
  456.     }
  457.     //
  458.     // Increase the number of system PTEs if we have cards that will need
  459.     // more than 10 MEG of PTEs
  460.     //
  461.     if ((maxmem = maxmem * numDev) > 10)
  462.     {
  463.         //
  464.         // we need 1K PTEs to support 1 MEG
  465.         // Then add 50% for other devices this type of machine may have.
  466.         //
  467.         // NOTE - in the future, we may want to be smarter and try
  468.         // to merge with whatever someone else put in there.
  469.         //
  470.         maxmem *= 0x400 * 3/2;
  471.         if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  472.                            TEXT("System\CurrentControlSet\Control\Session Manager\Memory Management"),
  473.                            0,
  474.                            NULL,
  475.                            REG_OPTION_NON_VOLATILE,
  476.                            KEY_READ | KEY_WRITE,
  477.                            NULL,
  478.                            &hkey,
  479.                            &disposition) == ERROR_SUCCESS)
  480.         {
  481.             //
  482.             // Check if we walready set maxmem in the registry.
  483.             //
  484.             DWORD data;
  485.             DWORD cb = sizeof(data);
  486.             if ( (RegQueryValueEx(hkey,
  487.                                   TEXT("SystemPages"),
  488.                                   NULL,
  489.                                   NULL,
  490.                                   (LPBYTE)(&data),
  491.                                   &cb) != ERROR_SUCCESS) ||
  492.                  (data < maxmem) )
  493.             {
  494.                 //
  495.                 // Set the new value
  496.                 //
  497.                 RegSetValueEx(hkey,
  498.                               TEXT("SystemPages"),
  499.                               0,
  500.                               REG_DWORD,
  501.                               (LPBYTE) &maxmem,
  502.                               sizeof(DWORD));
  503.                 //
  504.                 // Tell the system we must reboot before running this driver.
  505.                 //
  506.                 ZeroMemory(&DeviceInstallParams, sizeof(DeviceInstallParams));
  507.                 DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  508.                 SetupDiGetDeviceInstallParams(hDevInfo,
  509.                                               pDeviceInfoData,
  510.                                               &DeviceInstallParams);
  511.                 DeviceInstallParams.Flags |= DI_NEEDREBOOT;
  512.                 SetupDiSetDeviceInstallParams(hDevInfo,
  513.                                               pDeviceInfoData,
  514.                                               &DeviceInstallParams);
  515.             }
  516.             RegCloseKey(hkey);
  517.         }
  518.     }
  519.     //
  520.     // We may have to do this for multiple adapters at this point.
  521.     // So loop throught the number of devices, which has 1 as the default
  522.     // value
  523.     //
  524.     //
  525.     // Initialize the default callback so that the MsgHandler works
  526.     // properly
  527.     //
  528.     Context = SetupInitDefaultQueueCallback(hwnd);
  529.     bSetSoftwareKey = TRUE;
  530.     do {
  531.         if (PnPDriver && bSetSoftwareKey)
  532.         {
  533.             HKEY hkeyTmp;
  534.             hkey = INVALID_HANDLE_VALUE;
  535.             //
  536.             // For PnP, install the display driver under the software key
  537.             //
  538.             hkeyTmp = SetupDiOpenDevRegKey(hDevInfo,
  539.                                            pDeviceInfoData,
  540.                                            DICS_FLAG_GLOBAL,
  541.                                            0,
  542.                                            DIREG_DRV,
  543.                                            KEY_READ | KEY_WRITE);
  544.             if (hkeyTmp != INVALID_HANDLE_VALUE)
  545.             {
  546.                 RegCreateKeyEx(hkeyTmp,
  547.                                TEXT("Settings"),
  548.                                0,
  549.                                NULL,
  550.                                REG_OPTION_NON_VOLATILE,
  551.                                KEY_READ | KEY_WRITE,
  552.                                NULL,
  553.                                &hkey,
  554.                                &disposition);
  555.                 RegCloseKey(hkeyTmp);
  556.             }
  557.         }
  558.         else
  559.         {
  560.             numDev -= 1;
  561.             //
  562.             // For all drivers, install the information under DeviceX
  563.             // We do this for legacy purposes since many drivers rely on
  564.             // information written to this key.
  565.             //
  566.             wsprintf(keyName,
  567.                      TEXT("System\CurrentControlSet\Services\%ws\Device%d"),
  568.                      pServiceName, numDev);
  569.             RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  570.                            keyName,
  571.                            0,
  572.                            NULL,
  573.                            REG_OPTION_NON_VOLATILE,
  574.                            KEY_READ | KEY_WRITE,
  575.                            NULL,
  576.                            &hkey,
  577.                            &disposition);
  578.         }
  579.         if (hkey != INVALID_HANDLE_VALUE)
  580.         {
  581.             wsprintf(szSoftwareSection,
  582.                      TEXT("%ws.SoftwareSettings"),
  583.                      DriverInfoDetailData->SectionName);
  584.             if (!SetupInstallFromInfSection(hwnd,
  585.                                             InfFileHandle,
  586.                                             szSoftwareSection,
  587.                                             SPINST_REGISTRY,
  588.                                             hkey,
  589.                                             NULL,
  590.                                             0,
  591.                                             &SetupDefaultQueueCallback,
  592.                                             Context,
  593.                                             NULL,
  594.                                             NULL))
  595.             {
  596.                 TraceMsg(TF_GENERAL, "SetupInstallFromInfSection Error %dn", INVALID_HANDLE_VALUE);
  597.                 return ERROR_INVALID_PARAMETER;
  598.             }
  599.             //
  600.             // Write the description of the device if we are not detecting
  601.             //
  602.             // Only do this for legacy installation at this point.
  603.             //
  604.             if ((PnPDriver && bSetSoftwareKey) == FALSE)
  605.             {
  606.                 RegSetValueEx(hkey,
  607.                               TEXT("Device Description"),
  608.                               0,
  609.                               REG_SZ,
  610.                               (LPBYTE) DriverInfoDetailData->DrvDescription,
  611.                               (lstrlen(DriverInfoDetailData->DrvDescription) + 1) *
  612.                                    sizeof(TCHAR) );
  613.             }
  614. #if 0
  615.             //
  616.             // Invoke the resource picker for adapters that need it.
  617.             //
  618.             {
  619.                 LOG_CONF LogConfig;
  620.                 RES_DES ResDes;
  621.                 HMODULE hModule;
  622.                 FARPROC PropSheetExtProc;
  623.                 if (CM_Get_First_Log_Conf(&LogConfig,
  624.                                           pDeviceInfoData->DevInst,
  625.                                           BASIC_LOG_CONF) == CR_SUCCESS)
  626.                 {
  627.                     //
  628.                     // This device instance has a basic log config, so we want to
  629.                     // give the user a resource selection dialog.
  630.                     // (before we do that, go ahead and free the log config
  631.                     // handle--we don't need it.)
  632.                     //
  633.                     CM_Free_Log_Conf_Handle(LogConfig);
  634.                     if ((hModule = GetModuleHandle(TEXT("setupapi.dll"))) &&
  635.                         (PropSheetExtProc = GetProcAddress(hModule,
  636.                                                            "ExtensionPropSheetPageProc")))
  637.                     {
  638.                         SP_PROPSHEETPAGE_REQUEST PropSheetRequest;
  639.                         HPROPSHEETPAGE    hPage = {0};
  640.                         PROPSHEETPAGE     PropPage;
  641.                         PROPSHEETHEADER   PropHeader;
  642.                         PropSheetRequest.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
  643.                         PropSheetRequest.PageRequested = SPPSR_SELECT_DEVICE_RESOURCES;
  644.                         PropSheetRequest.DeviceInfoSet = hDevInfo;
  645.                         PropSheetRequest.pDeviceInfoData = pDeviceInfoData;
  646.                         //
  647.                         // Try to get the property sheet extension from setupapi.
  648.                         //
  649.                         if (PropSheetExtProc(&PropSheetRequest,
  650.                                              AddPropSheetPageProc,
  651.                                              &hPage))
  652.                         {
  653.                             PropHeader.dwSize      = sizeof(PROPSHEETHEADER);
  654.                             PropHeader.dwFlags     = PSH_NOAPPLYNOW;
  655.                             PropHeader.hwndParent  = hwnd;
  656.                             PropHeader.hInstance   = ghmod;
  657.                             PropHeader.pszIcon     = NULL;
  658.                             PropHeader.pszCaption  = TEXT(" ");
  659.                             PropHeader.nPages      = 1;
  660.                             PropHeader.phpage      = &hPage;
  661.                             PropHeader.nStartPage  = 0;
  662.                             PropHeader.pfnCallback = NULL;
  663.                             if (PropertySheet(&PropHeader) == -1)
  664.                             {
  665.                                 if(hPage)
  666.                                 {
  667.                                     DestroyPropertySheetPage(hPage);
  668.                                 }
  669.                             }
  670.                             else
  671.                             {
  672.                                 //
  673.                                 // BUGBUG can this return zero ?
  674.                                 //
  675.                                 //
  676.                                 // If we were successful, then we want to retrieve the user's selection.
  677.                                 //
  678.                                 CM_Get_First_Log_Conf(&LogConfig,
  679.                                                       pDeviceInfoData->DevInst,
  680.                                                       FORCED_LOG_CONF);
  681.                                 ResDes = LogConfig;
  682.                                 // while(
  683.                                 if (CM_Get_Next_Res_Des(&ResDes,
  684.                                                         ResDes,
  685.                                                         ResType_Mem,
  686.                                                         NULL,
  687.                                                         0) == CR_SUCCESS)
  688.                                 {
  689.                                     MEM_RESOURCE memRes;
  690.                                     if (CM_Get_Res_Des_Data(ResDes,
  691.                                                             &memRes,
  692.                                                             sizeof(memRes),
  693.                                                             0) == CR_SUCCESS)
  694.                                     {
  695.                                         RegSetValueEx(hkey,
  696.                                                       TEXT("MemBase"),
  697.                                                       0,
  698.                                                       REG_DWORD,
  699.                                                       (LPBYTE) &(memRes.MEM_Header.MD_Alloc_Base),
  700.                                                       sizeof(DWORD));
  701.                                     }
  702.                                     CM_Free_Res_Des_Handle(ResDes); // resdesnext
  703.                                 }
  704.                             }
  705.                         }
  706.                     }
  707.                 }
  708.             }
  709. #endif
  710.             RegCloseKey(hkey);
  711.         }
  712.         bSetSoftwareKey = FALSE;
  713.     } while (numDev != 0);
  714.     //
  715.     // optinally run the OpenGl section in the inf.
  716.     // Ignore any errors at this point since this is an optional
  717.     // entry.
  718.     //
  719.     if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  720.                        TEXT("SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers"),
  721.                        0,
  722.                        NULL,
  723.                        REG_OPTION_NON_VOLATILE,
  724.                        KEY_READ | KEY_WRITE,
  725.                        NULL,
  726.                        &hkey,
  727.                        &disposition) == ERROR_SUCCESS)
  728.     {
  729.         wsprintf(szSoftwareSection,
  730.                  TEXT("%ws.OpenGLSoftwareSettings"),
  731.                  DriverInfoDetailData->SectionName);
  732.         SetupInstallFromInfSection(hwnd,
  733.                                    InfFileHandle,
  734.                                    szSoftwareSection,
  735.                                    SPINST_REGISTRY,
  736.                                    hkey,
  737.                                    NULL,
  738.                                    0,
  739.                                    &SetupDefaultQueueCallback,
  740.                                    Context,
  741.                                    NULL,
  742.                                    NULL);
  743.         RegCloseKey(hkey);
  744.     }
  745.     //
  746.     // Get the next line for detection if we are detecting.
  747.     //
  748.     SetupCloseInfFile(InfFileHandle);
  749.     TraceMsg(TF_GENERAL, "DeskInstallServiceExtensions return %dn", retError);
  750.     return retError;
  751. }
  752. DWORD
  753. DeskInstallService(
  754.     IN HDEVINFO         hDevInfo,
  755.     IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL,
  756.     IN LPTSTR           pServiceName,
  757.     IN DWORD            dwDetect
  758.     )
  759. {
  760.     SP_DEVINSTALL_PARAMS   DeviceInstallParams;
  761.     SP_DRVINFO_DATA        DriverInfoData;
  762.     SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  763.     DWORD                  cbOutputSize;
  764.     HINF                   hInf;
  765.     TCHAR                  ActualInfSection[LINE_LEN];
  766.     INFCONTEXT             infContext;
  767.     DWORD                  status = NO_ERROR;
  768.     TraceMsg(TF_GENERAL, "DeskInstallService calledn");
  769.     //
  770.     // Get the params so we can get the window handle.
  771.     //
  772.     DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  773.     SetupDiGetDeviceInstallParams(hDevInfo,
  774.                                   pDeviceInfoData,
  775.                                   &DeviceInstallParams);
  776.     //
  777.     // Retrieve information about the driver node selected for this device.
  778.     //
  779.     DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  780.     if (!SetupDiGetSelectedDriver(hDevInfo,
  781.                                   pDeviceInfoData,
  782.                                   &DriverInfoData))
  783.     {
  784.         TraceMsg(TF_GENERAL, "SetupDiGetSelectedDriver Error %dn", GetLastError());
  785.         return GetLastError();
  786.     }
  787.     DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  788.     if (!(SetupDiGetDriverInfoDetail(hDevInfo,
  789.                                      pDeviceInfoData,
  790.                                      &DriverInfoData,
  791.                                      &DriverInfoDetailData,
  792.                                      DriverInfoDetailData.cbSize,
  793.                                      &cbOutputSize)) &&
  794.         (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  795.     {
  796.         TraceMsg(TF_GENERAL, "SetupDiGetDriverInfoDetail Error %dn", GetLastError());
  797.         return GetLastError();
  798.     }
  799.     //
  800.     // Open the INF that installs this driver node, so we can 'pre-run' the
  801.     // AddService/DelService entries in its install service install section.
  802.     //
  803.     hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
  804.                             NULL,
  805.                             INF_STYLE_WIN4,
  806.                             NULL);
  807.     if(hInf == INVALID_HANDLE_VALUE)
  808.     {
  809.         //
  810.         // For some reason we couldn't open the INF--this should never happen.
  811.         //
  812.         TraceMsg(TF_GENERAL, "SetupOpenInfFile Errorn");
  813.         return ERROR_INVALID_HANDLE;
  814.     }
  815.     //
  816.     // Now find the actual (potentially OS/platform-specific) install section name.
  817.     //
  818.     if (!SetupDiGetActualSectionToInstall(hInf,
  819.                                           DriverInfoDetailData.SectionName,
  820.                                           ActualInfSection,
  821.                                           sizeof(ActualInfSection) / sizeof(TCHAR),
  822.                                           NULL,
  823.                                           NULL))
  824.     {
  825.         status = GetLastError();
  826.         TraceMsg(TF_GENERAL, "SetupDiGetActualSectionToInstall Error %dn", status);
  827.     }
  828.     else
  829.     {
  830.         //
  831.         // Append a ".Services" to get the service install section name.
  832.         //
  833.         lstrcat(ActualInfSection, TEXT(".Services"));
  834.         //
  835.         // Now run the service modification entries in this section...
  836.         //
  837.         if (!SetupInstallServicesFromInfSection(hInf,
  838.                                                 ActualInfSection,
  839.                                                 0))
  840.         {
  841.             status = GetLastError();
  842.             TraceMsg(TF_GENERAL, "SetupInstallServicesFromInfSection Error %dn", status);
  843.         }
  844.     }
  845.     //
  846.     // Get the service Name if needed (detection)
  847.     //
  848.     if (SetupFindFirstLine(hInf,
  849.                            ActualInfSection,
  850.                            TEXT("AddService"),
  851.                            &infContext))
  852.     {
  853.         SetupGetStringField(&infContext,
  854.                             1,
  855.                             pServiceName,
  856.                             LINE_LEN,
  857.                             NULL);
  858.     }
  859.     SetupCloseInfFile(hInf);
  860.     if (status != NO_ERROR)
  861.     {
  862.         return status;
  863.     }
  864.     //
  865.     // Now that the basic install has been performed (wihtout starting the
  866.     // device), write the extra data to the registry.
  867.     //
  868.     status = DeskInstallServiceExtensions(DeviceInstallParams.hwndParent,
  869.                                           hDevInfo,
  870.                                           pDeviceInfoData,
  871.                                           &DriverInfoData,
  872.                                           &DriverInfoDetailData,
  873.                                           pServiceName,
  874.                                           dwDetect);
  875.     if (status != NO_ERROR)
  876.     {
  877.         TraceMsg(TF_GENERAL, "DeskInstallServiceExtensions Error %dn", status);
  878.         return status;
  879.     }
  880.     if (dwDetect == 0)
  881.     {
  882.         //
  883.         // We have a DEVNODE and therefore a pDeviceInfoData.
  884.         // Do the full device install, which will also start the device
  885.         // dynamically.
  886.         //
  887.         if (!SetupDiInstallDevice(hDevInfo, pDeviceInfoData))
  888.         {
  889.             TraceMsg(TF_GENERAL, "SetupDiInstallDevice Error %dn", GetLastError());
  890.             //
  891.             // Remove the device !??
  892.             //
  893.             return GetLastError();
  894.         }
  895.         else
  896.         {
  897.             //
  898.             // For a PnP Device which will never do detection, we want to mark
  899.             // the device as DemandStart.
  900.             //
  901.             DeskSCSetServiceDemandStart(pServiceName);
  902.         }
  903.     }
  904.     //
  905.     // If some of the flags (like paged pool) needed to be changed,
  906.     // let's ask for a reboot right now.
  907.     //
  908.     // Otherwise, we can actually try to start the device at this point.
  909.     //
  910.     TraceMsg(TF_GENERAL, "DeskInstallService return 0n");
  911.     return NO_ERROR;
  912. }
  913. DWORD
  914. DeskRemoveService(
  915.     IN HDEVINFO         hDevInfo,
  916.     IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL,
  917.     IN LPTSTR           pServiceName
  918.     )
  919. {
  920.     CONFIGRET  crStatus = CR_FAILURE;
  921.     ULONG      DevIdBufferLen;
  922.     LPTSTR     DevIdBuffer;
  923.     LPTSTR     pTmp;
  924.     TraceMsg(TF_GENERAL, "DeskRemoveService calledn");
  925.     //
  926.     // Remove the service
  927.     //
  928.     //
  929.     // Check if any devices are controlled by this service.
  930.     //
  931.     CM_Get_Device_ID_List_Size(&DevIdBufferLen,
  932.                                pServiceName,
  933.                                CM_GETIDLIST_FILTER_SERVICE);
  934.     if ( (DevIdBufferLen) &&
  935.          (DevIdBuffer = LocalAlloc(LPTR, DevIdBufferLen * sizeof(TCHAR))))
  936.     {
  937.         crStatus = CM_Get_Device_ID_List(pServiceName,
  938.                                          DevIdBuffer,
  939.                                          DevIdBufferLen,
  940.                                          CM_GETIDLIST_FILTER_SERVICE);
  941.     }
  942.     if (crStatus == CR_SUCCESS)
  943.     {
  944.         pTmp = DevIdBuffer;
  945.         //
  946.         // Walk the MULTI_SZ with the devices in it.
  947.         //
  948.         while (*pTmp)
  949.         {
  950.             DEVINST DevInst;
  951.             // ASSERT(wcsstr(TEXT("_DETECT"), pTmp));
  952.             crStatus =
  953.                 CM_Locate_DevNode(&DevInst,
  954.                                   pTmp,
  955.                                   CM_LOCATE_DEVNODE_NORMAL | CM_LOCATE_DEVNODE_PHANTOM);
  956.             if (crStatus != CR_SUCCESS)
  957.             {
  958.                 TraceMsg(TF_GENERAL, " CM_Locate_DevNode %ws failed %dn",
  959.                          pTmp, crStatus);
  960.                 continue;
  961.             }
  962.             //
  963.             // LATER : Make sure we only delete legacy devnodes.
  964.             //
  965.             crStatus = CM_Uninstall_DevNode(DevInst, 0);
  966.             if (crStatus != CR_SUCCESS)
  967.             {
  968.                 TraceMsg(TF_GENERAL, " CM_Locate_DevNode %ws failed %dn",
  969.                          pTmp, crStatus);
  970.                 continue;
  971.             }
  972.             TraceMsg(TF_GENERAL, "Deleted device %wsn", pTmp);
  973.             //
  974.             // Next string in the MULTI_SZ
  975.             //
  976.             while (*pTmp++);
  977.         }
  978.         DeskSCDeleteService(pServiceName);
  979.     }
  980.     TraceMsg(TF_GENERAL, "DeskRemoveService return 0n");
  981.     return NO_ERROR;
  982. }
  983. /***************************************************************************/
  984. /***************************************************************************/
  985. /**                                                                       **/
  986. /**                              Detection                                **/
  987. /**                                                                       **/
  988. /***************************************************************************/
  989. /***************************************************************************/
  990. DWORD
  991. DeskDetectDevice(
  992.     IN  HDEVINFO                hDevInfo,
  993.     IN  PDETECT_PROGRESS_NOTIFY ProgressFunction,
  994.     IN  PVOID                   ProgressFunctionParam,
  995.     OUT PSP_DRVINFO_DATA        pDrvInfoData
  996.     )
  997. {
  998.     SP_DEVINSTALL_PARAMS DeviceInstallParams;
  999.     HINF                 InfFileHandle;
  1000.     PVOID                Context;
  1001.     INFCONTEXT           infoContext;
  1002.     ULONG                LineCount = 0;
  1003.     ULONG                LoopCount = 0;
  1004.     TCHAR                Provider[LINE_LEN];
  1005.     UCHAR                Buffer[1024];
  1006.     DWORD                detectionStatus = ERROR_DEV_NOT_EXIST;
  1007.     TraceMsg(TF_GENERAL, "DeskDetectDevice calledn");
  1008.     //
  1009.     // Set the parameters for the device installation to only use dispdet.inf
  1010.     // Also use this to get the hwnd.
  1011.     //
  1012.     ZeroMemory(&DeviceInstallParams, sizeof(DeviceInstallParams));
  1013.     DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  1014.     SetupDiGetDeviceInstallParams(hDevInfo,
  1015.                                   NULL,
  1016.                                   &DeviceInstallParams);
  1017.     DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
  1018.     lstrcpy(DeviceInstallParams.DriverPath, TEXT("dispdet.inf"));
  1019.     SetupDiSetDeviceInstallParams(hDevInfo,
  1020.                                   NULL,
  1021.                                   &DeviceInstallParams);
  1022.     if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
  1023.     {
  1024.         return ERROR_INVALID_PARAMETER;
  1025.     }
  1026.     TraceMsg(TF_GENERAL, "DetectDriverList DriverInfoList createdn");
  1027.     //
  1028.     // Open the main inf for us to do detection.
  1029.     // Detection is only done on legacy drivers that we provide
  1030.     //
  1031.     InfFileHandle = SetupOpenInfFile(TEXT("dispdet.inf"),
  1032.                                      NULL,
  1033.                                      INF_STYLE_WIN4,
  1034.                                      NULL);
  1035.     if (InfFileHandle == INVALID_HANDLE_VALUE)
  1036.     {
  1037.         return ERROR_INVALID_PARAMETER;
  1038.     }
  1039.     //
  1040.     // Append layout.inx so we can do file copy.
  1041.     //
  1042.     SetupOpenAppendInfFile(NULL,
  1043.                            InfFileHandle,
  1044.                            NULL);
  1045.     Context = SetupInitDefaultQueueCallback(DeviceInstallParams.hwndParent);
  1046.     if (!SetupInstallFromInfSection(DeviceInstallParams.hwndParent,
  1047.                                     InfFileHandle,
  1048.                                     TEXT("detect.install.drivers"),
  1049.                                     SPINST_FILES,
  1050.                                     NULL,
  1051.                                     NULL,
  1052.                                     0,
  1053.                                     &SetupDefaultQueueCallback,
  1054.                                     Context,
  1055.                                     NULL,
  1056.                                     NULL))
  1057.     {
  1058.         TraceMsg(TF_GENERAL, " Install detect files failed %dn", GetLastError());
  1059.         return GetLastError();
  1060.     }
  1061.     //
  1062.     // Get the provider name
  1063.     //
  1064.     if (SetupGetInfInformation(InfFileHandle,
  1065.                                INFINFO_INF_SPEC_IS_HINF,
  1066.                                (PSP_INF_INFORMATION) Buffer,
  1067.                                sizeof(Buffer),
  1068.                                NULL))
  1069.     {
  1070.         TraceMsg(TF_GENERAL, " Getting Provider Namen");
  1071.         SetupQueryInfVersionInformation((PSP_INF_INFORMATION) Buffer,
  1072.                                         0,
  1073.                                         TEXT("Provider"),
  1074.                                         Provider,
  1075.                                         LINE_LEN,
  1076.                                         NULL);
  1077.     }
  1078.     //
  1079.     // Get the list of drivers we want to try to detect.
  1080.     //
  1081.     LineCount = SetupGetLineCount(InfFileHandle,
  1082.                                   TEXT("DetectDriverList"));
  1083.     TraceMsg(TF_GENERAL, "DetectDriverList size = %dn", LineCount);
  1084.     //
  1085.     // Get the list of drivers we want to try to detect.
  1086.     //
  1087.     if (!SetupFindFirstLine(InfFileHandle,
  1088.                             TEXT("DetectDriverList"),
  1089.                             NULL,
  1090.                             &infoContext))
  1091.     {
  1092.         return ERROR_INVALID_PARAMETER;
  1093.     }
  1094.     do
  1095.     {
  1096.         TCHAR DeviceDescription[LINE_LEN];
  1097.         ULONG DeviceDescriptionSize;
  1098.         TCHAR Manufacturer[LINE_LEN];
  1099.         ULONG ManufacturerSize;
  1100.         TCHAR ServiceName[LINE_LEN];
  1101.         TCHAR DetectBroken[LINE_LEN];
  1102.         ULONG DetectBrokenSize;
  1103.         ASSERT(LoopCount < LineCount);
  1104.         //
  1105.         // For each driver in the list, install it and see if it loads
  1106.         //
  1107.         if ( (!SetupGetStringField(&infoContext,
  1108.                                    0,
  1109.                                    Manufacturer,
  1110.                                    LINE_LEN,
  1111.                                    &ManufacturerSize))
  1112.            ||
  1113.              (!SetupGetStringField(&infoContext,
  1114.                                    1,
  1115.                                    DeviceDescription,
  1116.                                    LINE_LEN,
  1117.                                    &DeviceDescriptionSize))
  1118.            )
  1119.         {
  1120.             TraceMsg(TF_GENERAL, " Get Item failed on line %d, error %dn",
  1121.                      LineCount, GetLastError());
  1122.         }
  1123.         else
  1124.         {
  1125.             //
  1126.             // Find the appropriate entry in the list of devices.
  1127.             //
  1128.             TraceMsg(TF_GENERAL, "DeskDetectDevice on device %ws, %wsn",
  1129.                      Manufacturer, DeviceDescription);
  1130.             ZeroMemory(pDrvInfoData, sizeof(SP_DRVINFO_DATA));
  1131.             pDrvInfoData->cbSize     = sizeof(SP_DRVINFO_DATA);
  1132.             pDrvInfoData->DriverType = SPDIT_CLASSDRIVER;
  1133.             pDrvInfoData->Reserved   = 0; // Means search the list for this driver
  1134.             _tcscpy(pDrvInfoData->Description,  DeviceDescription);
  1135.             _tcscpy(pDrvInfoData->MfgName,      Manufacturer);
  1136.             _tcscpy(pDrvInfoData->ProviderName, Provider);
  1137.             if (!SetupDiSetSelectedDriver(hDevInfo,
  1138.                                           NULL,
  1139.                                           pDrvInfoData))
  1140.             {
  1141.                 TraceMsg(TF_GENERAL, "DeskDetectDevice Select device failed on %ws, error %dn",
  1142.                          DeviceDescription, GetLastError());
  1143.             }
  1144.             else
  1145.             {
  1146.                 TraceMsg(TF_GENERAL, "DeskDetectDevice Match on device %wsn", DeviceDescription);
  1147.                 //
  1148.                 // Install the service in the registry.
  1149.                 //
  1150.                 if (DeskInstallService(hDevInfo,
  1151.                                        NULL,
  1152.                                        ServiceName,
  1153.                                        LEGACY_DETECT) == NO_ERROR)
  1154.                 {
  1155.                     TraceMsg(TF_GENERAL, "DeskDetectDevice Service %ws installedn",
  1156.                              ServiceName);
  1157.                     //
  1158.                     //  We have no DEVNODE.  Start the driver by hand.
  1159.                     //
  1160.                     if (DeskSCStartService(ServiceName) == NO_ERROR)
  1161.                     {
  1162.                         TraceMsg(TF_GENERAL, "DeskDetectDevice Service startedn");
  1163.                         //
  1164.                         // We detected a device !!!
  1165.                         //
  1166.                         detectionStatus = NO_ERROR;
  1167.                         //
  1168.                         // Stop the service
  1169.                         // BUGBUG Don't care if it stops or not for now.
  1170.                         //
  1171.                         DeskSCStopService(ServiceName);
  1172.                     }
  1173.                     TraceMsg(TF_GENERAL, "DeskDetectDevice remove Servicen");
  1174.                     DeskRemoveService(hDevInfo,
  1175.                                       NULL,
  1176.                                       ServiceName);
  1177.                     //
  1178.                     // For broken drivers that trash the screen during
  1179.                     // detection, reset the device to the default state.
  1180.                     //
  1181.                     if (SetupGetStringField(&infoContext,
  1182.                                             2,
  1183.                                             DetectBroken,
  1184.                                             LINE_LEN,
  1185.                                             &DetectBrokenSize))
  1186.                     {
  1187.                         TraceMsg(TF_GENERAL, " detect : %wsn", DetectBroken);
  1188.                         if (_tcscmp(DetectBroken, TEXT("detect_broken")) == 0)
  1189.                         {
  1190.                             TraceMsg(TF_GENERAL, "DeskDetectDevice detect_broken - RESET_SCREENn");
  1191.                             ChangeDisplaySettings(NULL, CDS_RESET);
  1192.                         }
  1193.                     }
  1194.                 }
  1195.             }
  1196.             //
  1197.             // If we found a device, then stop detection.
  1198.             //
  1199.             // NOTE - machines with more than 1 video card should have PnP
  1200.             // drivers for those !
  1201.             //
  1202.             if (detectionStatus == NO_ERROR)
  1203.             {
  1204.                 TraceMsg(TF_GENERAL, "DeskDetectDevice found device - stop detectionn");
  1205.                 break;
  1206.             }
  1207.         }
  1208.         //
  1209.         // Track how far along we are in detection
  1210.         //
  1211.         TraceMsg(TF_GENERAL, "DeskDetectDevice Display LoopCountn");
  1212.         LoopCount++;
  1213.         if (ProgressFunction)
  1214.         {
  1215.             if (ProgressFunction(ProgressFunctionParam,
  1216.                                  LoopCount * 100 / LineCount))
  1217.             {
  1218.                 //
  1219.                 // User cancelled - leave now.
  1220.                 //
  1221.                 break;
  1222.             }
  1223.         }
  1224.     } while (SetupFindNextLine(&infoContext, &infoContext));
  1225.     TraceMsg(TF_GENERAL, "DeskDetectDevice Completen");
  1226.     //
  1227.     // Clean out all of the extra files we copied
  1228.     //
  1229.     if (!SetupInstallFromInfSection(DeviceInstallParams.hwndParent,
  1230.                                     InfFileHandle,
  1231.                                     TEXT("detect.remove.drivers"),
  1232.                                     SPINST_FILES,
  1233.                                     NULL,
  1234.                                     NULL,
  1235.                                     0,
  1236.                                     &SetupDefaultQueueCallback,
  1237.                                     Context,
  1238.                                     NULL,
  1239.                                     NULL))
  1240.     {
  1241.         TraceMsg(TF_GENERAL, " Remove detect files failed %dn", GetLastError());
  1242.     }
  1243.     return (detectionStatus);
  1244. }
  1245. /***************************************************************************/
  1246. /***************************************************************************/
  1247. /**                                                                       **/
  1248. /**                           Class Installers                            **/
  1249. /**                                                                       **/
  1250. /***************************************************************************/
  1251. /***************************************************************************/
  1252. LPTSTR UpdateDatabase[] = {
  1253.     TEXT("Root\LEGACY_UPGRADE_THIS_DRIVER\0000"),
  1254.     NULL,
  1255. };
  1256. BOOL
  1257. DeskCheckInstallDatabase(
  1258.     IN HDEVINFO         hDevInfo,
  1259.     IN PSP_DEVINFO_DATA pDeviceInfoData
  1260.     )
  1261. {
  1262.     BOOL            bRet = TRUE;
  1263.     HDEVINFO        HDevInfo;
  1264.     SP_DEVINFO_DATA DeviceInfoData;
  1265.     DWORD           index = 0;
  1266.     TCHAR           RegistryProperty[256];
  1267.     ULONG           BufferSize;
  1268. #if 0
  1269.     HKEY            hKey;
  1270.     //
  1271.     // BUGBUG this does not work.
  1272.     // It appears to always succeed
  1273.     //
  1274.     //
  1275.     // First. let's check if we have a driver key.
  1276.     // If we do, then we can control the upgrade easily.
  1277.     //
  1278.     hKey = SetupDiOpenDevRegKey(hDevInfo,
  1279.                                 pDeviceInfoData,
  1280.                                 DICS_FLAG_GLOBAL,
  1281.                                 0,
  1282.                                 DIREG_DRV,
  1283.                                 KEY_READ | KEY_WRITE);
  1284.     if (hKey != INVALID_HANDLE_VALUE)
  1285.     {
  1286.         //
  1287.         // If this succeeds, then we can safely upgrade the driver since
  1288.         // it is an existing, properly installed driver.
  1289.         //
  1290.         TraceMsg(TF_GENERAL, "Database - driver key existsn");
  1291.         RegCloseKey(hKey);
  1292.         return TRUE;
  1293.     }
  1294. #endif
  1295.     //
  1296.     // Let's find all the video drivers that are installed in the system
  1297.     //
  1298.     HDevInfo = SetupDiGetClassDevs((LPGUID) &GUID_DEVCLASS_DISPLAY,
  1299.                                    NULL,
  1300.                                    NULL,
  1301.                                    0);
  1302.     if (HDevInfo == INVALID_HANDLE_VALUE)
  1303.     {
  1304.         TraceMsg(TF_GENERAL, "Database - no existing drivern");
  1305.         return TRUE;
  1306.     }
  1307.     while (bRet)
  1308.     {
  1309.         ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
  1310.         DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  1311.         if (!SetupDiEnumDeviceInfo(HDevInfo,
  1312.                                    index++,
  1313.                                    &DeviceInfoData))
  1314.         {
  1315.             TraceMsg(TF_GENERAL, "Database retrieving device Error %dn", GetLastError());
  1316.             break;
  1317.         }
  1318.         //
  1319.         // For each driver we found, compare it to the driver we are being
  1320.         // asked to install.
  1321.         //
  1322.         //
  1323.         // If we have a root legacy device, then don't install any new
  1324.         // devnode (until we get better at this).
  1325.         //
  1326.         if (CR_SUCCESS == CM_Get_Device_ID(DeviceInfoData.DevInst,
  1327.                                            RegistryProperty,
  1328.                                            sizeof(RegistryProperty),
  1329.                                            0))
  1330.         {
  1331.             LPTSTR *pUpgrade = UpdateDatabase;
  1332.             TraceMsg(TF_GENERAL, "t CM_Get_Device_ID = %wsn", RegistryProperty);
  1333.             if (_tcsncicmp(TEXT("ROOT\LEGACY_"),
  1334.                            RegistryProperty,
  1335.                            sizeof(TEXT("ROOT\LEGACY_"))) == 0)
  1336.             {
  1337.                 TraceMsg(TF_GENERAL, "t Legacy DEVNODE = %wsn", RegistryProperty);
  1338.                 //
  1339.                 // We have a legacy DEVNODE.
  1340.                 // By default, we don't want to upgrade any of these devices.
  1341.                 //
  1342.                 // Check if it's part of our database that we should upgrade.
  1343.                 //
  1344.                 bRet = FALSE;
  1345.                 while (*pUpgrade)
  1346.                 {
  1347.                     if (_tcsicmp(*pUpgrade, RegistryProperty) == 0)
  1348.                     {
  1349.                         TraceMsg(TF_GENERAL, "t Upgrade DEVNODE = %wsn", RegistryProperty);
  1350.                         bRet = TRUE;
  1351.                         break;
  1352.                     }
  1353.                     pUpgrade++;
  1354.                 }
  1355.             }
  1356.         }
  1357.         //
  1358.         // Print out other data for informational purposes.
  1359.         //
  1360.         BufferSize = sizeof(RegistryProperty);
  1361.         if (CR_SUCCESS ==
  1362.                 CM_Get_DevNode_Registry_Property(DeviceInfoData.DevInst,
  1363.                                                  CM_DRP_DEVICEDESC,
  1364.                                                  NULL,
  1365.                                                  RegistryProperty,
  1366.                                                  &BufferSize,
  1367.                                                  0))
  1368.         {
  1369.             TraceMsg(TF_GENERAL, "t CM_DRP_DEVICEDESC = %wsn", RegistryProperty);
  1370.         }
  1371.         BufferSize = sizeof(RegistryProperty);
  1372.         if (CR_SUCCESS ==
  1373.                 CM_Get_DevNode_Registry_Property(DeviceInfoData.DevInst,
  1374.                                                  CM_DRP_SERVICE,
  1375.                                                  NULL,
  1376.                                                  RegistryProperty,
  1377.                                                  &BufferSize,
  1378.                                                  0))
  1379.         {
  1380.             TraceMsg(TF_GENERAL, "t CM_DRP_SERVICE = %wsn", RegistryProperty);
  1381.         }
  1382.     }
  1383.     return bRet;
  1384. }
  1385. BOOL
  1386. bDoLegacyDetection(VOID)
  1387. {
  1388.     BOOL   bRet;
  1389.     HKEY   hkey;
  1390.     DWORD  bSetupInProgress = 0;
  1391.     DWORD  bUpgradeInProgress = 0;
  1392.     TCHAR  data[256];
  1393.     DWORD  cb;
  1394.     LPTSTR regstring;
  1395.     // ULONG  cCount;
  1396.     // cCount = GetPrivateProfileString(TEXT("data"),
  1397.     //                                  TEXT("winntupgrade"),
  1398.     //                                  TEXT("missing"),
  1399.     //                                  data,
  1400.     //                                  256,
  1401.     //                                  TEXT(".\$winnt$.inf"));
  1402.     hkey = NULL;
  1403.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1404.                      TEXT("System\Setup"),
  1405.                      0,
  1406.                      KEY_READ | KEY_WRITE,
  1407.                      &hkey) == ERROR_SUCCESS)
  1408.     {
  1409.         cb = 256;
  1410.         if (RegQueryValueEx(hkey,
  1411.                             TEXT("SystemSetupInProgress"),
  1412.                             NULL,
  1413.                             NULL,
  1414.                             (LPBYTE)(data),
  1415.                             &cb) == ERROR_SUCCESS)
  1416.         {
  1417.             bSetupInProgress = * ((LPDWORD)(data));
  1418.         }
  1419.         cb = 256;
  1420.         if (RegQueryValueEx(hkey,
  1421.                             TEXT("UpgradeInProgress"),
  1422.                             NULL,
  1423.                             NULL,
  1424.                             (LPBYTE)(data),
  1425.                             &cb) == ERROR_SUCCESS)
  1426.         {
  1427.             bUpgradeInProgress = * ((LPDWORD)(data));
  1428.         }
  1429.         if (hkey) {
  1430.             RegCloseKey(hkey);
  1431.         }
  1432.     }
  1433.     if (bSetupInProgress)
  1434.     {
  1435.         if (bUpgradeInProgress)
  1436.         {
  1437.             regstring = TEXT("System\Video_Upgrade");
  1438.             TraceMsg(TF_GENERAL, "/t/tUpgraden");
  1439.             bRet = FALSE;
  1440.         }
  1441.         else
  1442.         {
  1443.             //
  1444.             // We only do installation or detection if not BASEVIDEO
  1445.             //
  1446.             cb = 256;
  1447.             hkey = NULL;
  1448.             if ( (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1449.                                TEXT("System\CurrentControlSet\Control\Setup"),
  1450.                                0,
  1451.                                KEY_READ | KEY_WRITE,
  1452.                                &hkey) == ERROR_SUCCESS)     &&
  1453.                  (RegQueryValueEx(hkey,
  1454.                                   TEXT("video"),
  1455.                                   NULL,
  1456.                                   NULL,
  1457.                                   (LPBYTE)(data),
  1458.                                   &cb) == ERROR_SUCCESS)    &&
  1459.                  (_tcscmp(data, TEXT("forcevga")) == 0)
  1460.                )
  1461.             {
  1462.                 regstring = TEXT("System\Basevideo_Winnt");
  1463.                 TraceMsg(TF_GENERAL, "/t/tbasevideo installn");
  1464.                 bRet = FALSE;
  1465.             }
  1466.             else
  1467.             {
  1468.                 regstring = TEXT("System\Video_Clean");
  1469.                 TraceMsg(TF_GENERAL, "/t/tCleanInstalln");
  1470.                 bRet = TRUE;
  1471.             }
  1472.             if (hkey) {
  1473.                 RegCloseKey(hkey);
  1474.             }
  1475.         }
  1476.     }
  1477.     else
  1478.     {
  1479.         regstring = TEXT("System\Video_Missing_Winnt");
  1480.         TraceMsg(TF_GENERAL, "/t/tMissing $Winnt$.inf filen");
  1481.         bRet = TRUE;
  1482.     }
  1483. #if ANDREVA_DBG
  1484.     {
  1485.         DWORD  disposition;
  1486.         hkey = NULL;
  1487.         RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1488.                        regstring,
  1489.                        0,
  1490.                        NULL,
  1491.                        REG_OPTION_NON_VOLATILE,
  1492.                        KEY_READ | KEY_WRITE,
  1493.                        NULL,
  1494.                        &hkey,
  1495.                        &disposition);
  1496.         if (hkey) {
  1497.             RegCloseKey(hkey);
  1498.         }
  1499.     }
  1500. #endif
  1501.     return bRet;
  1502. }
  1503. DWORD
  1504. DisplayClassInstaller(
  1505.     IN DI_FUNCTION      InstallFunction,
  1506.     IN HDEVINFO         hDevInfo,
  1507.     IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL
  1508.     )
  1509. /*++
  1510. Routine Description:
  1511.   This routine acts as the class installer for Display devices.
  1512. Arguments:
  1513.     InstallFunction - Specifies the device installer function code indicating
  1514.         the action being performed.
  1515.     DeviceInfoSet - Supplies a handle to the device information set being
  1516.         acted upon by this install action.
  1517.     pDeviceInfoData - Optionally, supplies the address of a device information
  1518.         element being acted upon by this install action.
  1519. Return Value:
  1520.     If this function successfully completed the requested action, the return
  1521.         value is NO_ERROR.
  1522.     If the default behavior is to be performed for the requested action, the
  1523.         return value is ERROR_DI_DO_DEFAULT.
  1524.     If an error occurred while attempting to perform the requested action, a
  1525.         Win32 error code is returned.
  1526. --*/
  1527. {
  1528.     DWORD err;
  1529.     SP_DRVINFO_DATA DrvInfoData;
  1530.     // SP_SELECTDEVICE_PARAMS  SelectDevParams;
  1531.     // SP_DETECTDEVICE_PARAMS  DetectDevParams;
  1532.     TCHAR ServiceName[LINE_LEN];
  1533.     switch(InstallFunction) {
  1534.     case DIF_SELECTDEVICE :
  1535.         TraceMsg(TF_GENERAL, "DisplayClassInstaller DIF_SELECTDEVICE n");
  1536.         //
  1537.         // Check for old display driver infs that we no longer support.
  1538.         //
  1539.         if (SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
  1540.         {
  1541.             if (!SetupDiEnumDriverInfo(hDevInfo,
  1542.                                        NULL,
  1543.                                        SPDIT_CLASSDRIVER,
  1544.                                        0,
  1545.                                        &DrvInfoData))
  1546.             {
  1547.                 if (GetLastError() == ERROR_NO_MORE_ITEMS)
  1548.                 {
  1549.                     //
  1550.                     // This is what happens when an old inf is loaded.
  1551.                     // Tell the user it is an old inf.
  1552.                     //
  1553.                     FmtMessageBox(ghwndPropSheet,   // BUGBUG
  1554.                                   MB_ICONEXCLAMATION,
  1555.                                   FALSE,
  1556.                                   ID_DSP_TXT_INSTALL_DRIVER,
  1557.                                   ID_DSP_TXT_BAD_INF);
  1558.                     return ERROR_NO_MORE_ITEMS;
  1559.                 }
  1560.             }
  1561.         }
  1562.         break;
  1563. #if 0
  1564.         //
  1565.         // Set the test parameters for the display class installer.
  1566.         //
  1567.         ZeroMemory(&SelectDevParams, sizeof(SelectDevParams));
  1568.         SelectDevParams.ClassInstallHeader.cbSize
  1569.                                      = sizeof(SelectDevParams.ClassInstallHeader);
  1570.         SelectDevParams.ClassInstallHeader.InstallFunction
  1571.                                      = DIF_SELECTDEVICE;
  1572.         //
  1573.         // Get current SelectDevice parameters, and then set the fields
  1574.         // we want to be different from default
  1575.         //
  1576.         SetupDiGetClassInstallParams(hDevInfo,
  1577.                                      NULL,
  1578.                                      &SelectDevParams.ClassInstallHeader,
  1579.                                      sizeof(SelectDevParams),
  1580.                                      NULL);
  1581.         SelectDevParams.ClassInstallHeader.cbSize
  1582.                                  = sizeof(SelectDevParams.ClassInstallHeader);
  1583.         SelectDevParams.ClassInstallHeader.InstallFunction
  1584.                                  = DIF_SELECTDEVICE;
  1585.         //
  1586.         // Set the strings to use on the select driver page .
  1587.         //
  1588.         LoadString(ghmod,
  1589.                    IDS_DISPLAYINST,
  1590.                    SelectDevParams.Title,
  1591.                    sizeof(SelectDevParams.Title));
  1592.         LoadString(ghmod,
  1593.                    IDS_WINNTDEV_INSTRUCT,
  1594.                    SelectDevParams.Instructions,
  1595.                    sizeof(SelectDevParams.Instructions));
  1596.         LoadString(ghmod,
  1597.                    IDS_SELECTDEV_LABEL,
  1598.                    SelectDevParams.ListLabel,
  1599.                    sizeof(SelectDevParams.ListLabel));
  1600.         SetupDiSetClassInstallParams(hDevInfo,
  1601.                                      NULL,
  1602.                                      &SelectDevParams.ClassInstallHeader,
  1603.                                      sizeof(SelectDevParams));
  1604.         //
  1605.         // Let the wizard finish it's thing
  1606.         //
  1607.         break;
  1608. #endif
  1609.     case DIF_FIRSTTIMESETUP :
  1610.         TraceMsg(TF_GENERAL, "DisplayClassInstaller DIF_FIRSTTIMESETUP n");
  1611.         ASSERT(pDeviceInfoData == NULL);
  1612.         //
  1613.         // Don't do video driver detection during upgrade.
  1614.         //
  1615.         if (bDoLegacyDetection() == FALSE)
  1616.         {
  1617.             return NO_ERROR;
  1618.         }
  1619.         err = DeskDetectDevice(hDevInfo,
  1620.                                NULL,
  1621.                                NULL,
  1622.                                &DrvInfoData);
  1623.         if (err == NO_ERROR)
  1624.         {
  1625.             SP_DEVINFO_DATA      DeviceInfoData;
  1626.             SP_DEVINSTALL_PARAMS DeviceInstallParams;
  1627.             SP_DRVINFO_DATA      NewDrvInfoData = DrvInfoData;
  1628.             //
  1629.             // Create the DeviceInfoData for this new device.
  1630.             //
  1631.             TraceMsg(TF_GENERAL, " FIRSTTIME Creating DeviceInfon");
  1632.             ZeroMemory(&DeviceInfoData, sizeof(DeviceInfoData));
  1633.             DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  1634.             if (!SetupDiCreateDeviceInfo(hDevInfo,
  1635.                                          TEXT("Display"),
  1636.                                          (LPGUID) &GUID_DEVCLASS_DISPLAY,
  1637.                                          NULL,
  1638.                                          NULL,
  1639.                                          DICD_GENERATE_ID,
  1640.                                          &DeviceInfoData))
  1641.             {
  1642.                 err = GetLastError();
  1643.                 TraceMsg(TF_GENERAL, " FIRSTTIME CreateDeviceInfo failed : error = %dn",err);
  1644.                 return err;
  1645.             }
  1646.             //
  1647.             // Set the inf name to display.inf
  1648.             //
  1649.             // Also copy the files silently since we are in setup.
  1650.             //
  1651.             ZeroMemory(&DeviceInstallParams, sizeof(DeviceInstallParams));
  1652.             DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  1653.             if (!SetupDiGetDeviceInstallParams(hDevInfo,
  1654.                                                &DeviceInfoData,
  1655.                                                &DeviceInstallParams))
  1656.             {
  1657.                 err = GetLastError();
  1658.                 TraceMsg(TF_GENERAL, " FIRSTTIME GetDeviceInstall : error = %dn",err);
  1659.                 return err;
  1660.             }
  1661.             DeviceInstallParams.Flags |= DI_ENUMSINGLEINF | DI_QUIETINSTALL;
  1662.             lstrcpy(DeviceInstallParams.DriverPath, TEXT("display.inf"));
  1663.             if (!SetupDiSetDeviceInstallParams(hDevInfo,
  1664.                                                &DeviceInfoData,
  1665.                                                &DeviceInstallParams))
  1666.             {
  1667.                 err = GetLastError();
  1668.                 TraceMsg(TF_GENERAL, " FIRSTTIME SetDeviceInstall : error = %dn",err);
  1669.                 return err;
  1670.             }
  1671.             //
  1672.             // Build the driver list
  1673.             //
  1674.             if (!SetupDiBuildDriverInfoList(hDevInfo,
  1675.                                             &DeviceInfoData,
  1676.                                             SPDIT_CLASSDRIVER))
  1677.             {
  1678.                 err = GetLastError();
  1679.                 DbgPrint("Desk.cpl: FIRSTTIME SetupDiBuildDriverInfoList Error %dn", err);
  1680.                 return err;
  1681.             }
  1682.             //
  1683.             // Find the same driver in display.inf
  1684.             //
  1685.             NewDrvInfoData.Reserved = 0;
  1686.             if (!SetupDiSetSelectedDriver(hDevInfo,
  1687.                                           &DeviceInfoData,
  1688.                                           &NewDrvInfoData))
  1689.             {
  1690.                 err = GetLastError();
  1691.                 TraceMsg(TF_GENERAL, " FIRSTTIME display.inf dispdet.inf inconsistent = %dn", err);
  1692.                 ASSERT(FALSE);
  1693.                 return err;
  1694.             }
  1695.             //
  1696.             // How do we finish the install ... ?
  1697.             //
  1698.             // If this is a PnP device, just install the service and
  1699.             // run it.  The video port will call IoReportDetectedDevice
  1700.             // which will later complete the installation of the deivce
  1701.             //
  1702.             // For non-PnP drivers, we can do nothing at this point, and a
  1703.             // DEVNODE will be created.
  1704.             //
  1705.             if (DeskIsPnPDriver(hDevInfo, NULL))
  1706.             {
  1707.                 if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
  1708.                                                hDevInfo,
  1709.                                                &DeviceInfoData))
  1710.                 {
  1711.                     err = GetLastError();
  1712.                     TraceMsg(TF_GENERAL, " FIRSTTIME install of driver files failed = %dn", err);
  1713.                 }
  1714.                 else
  1715.                 {
  1716.                     err = DeskInstallService(hDevInfo,
  1717.                                              &DeviceInfoData,
  1718.                                              ServiceName,
  1719.                                              REPORT_DEVICE);
  1720.                     if (err == NO_ERROR)
  1721.                     {
  1722.                         err = DeskSCStartService(ServiceName);
  1723.                     }
  1724.                 }
  1725.                 //
  1726.                 // Remove the device info since we don't want to install
  1727.                 // it later on.
  1728.                 //
  1729.                 SetupDiDeleteDeviceInfo(hDevInfo,
  1730.                                         &DeviceInfoData);
  1731.             }
  1732.             else
  1733.             {
  1734.                 //
  1735.                 // We will get called later to register and install this
  1736.                 // device if it is a TRUE legacy DEVNODE...
  1737.                 //
  1738.             }
  1739.         }
  1740.         return err;
  1741. #if LATER
  1742.     case DIF_DETECT :
  1743.         TraceMsg(TF_GENERAL, "DisplayClassInstaller DIF_DETECT n");
  1744.         ASSERT(pDeviceInfoData == NULL);
  1745.         //
  1746.         // Get the progress bar parameter for detection
  1747.         //
  1748.         ZeroMemory(&DetectDevParams, sizeof(DetectDevParams));
  1749.         DetectDevParams.ClassInstallHeader.cbSize
  1750.                                      = sizeof(DetectDevParams.ClassInstallHeader);
  1751.         DetectDevParams.ClassInstallHeader.InstallFunction
  1752.                                      = DIF_DETECT;
  1753.         SetupDiGetClassInstallParams(hDevInfo,
  1754.                                      NULL,
  1755.                                      &DetectDevParams.ClassInstallHeader,
  1756.                                      sizeof(DetectDevParams),
  1757.                                      NULL);
  1758.         err = DeskDetectDevice(hDevInfo,
  1759.                                DetectDevParams.DetectProgressNotify,
  1760.                                DetectDevParams.ProgressNotifyParam,
  1761.                                &DrvInfoData);
  1762.         return err;
  1763. #endif
  1764.     case DIF_REGISTERDEVICE :
  1765.         TraceMsg(TF_GENERAL, "DisplayClassInstaller DIF_REGISTERDEVICE n");
  1766.         if (!SetupDiRegisterDeviceInfo(hDevInfo,
  1767.                                        pDeviceInfoData,
  1768.                                        0,
  1769.                                        NULL,
  1770.                                        NULL,
  1771.                                        NULL))
  1772.         {
  1773.             err = GetLastError();
  1774.             TraceMsg(TF_GENERAL, "DIF_REGISTERDEVICE failed : error = %dn",err);
  1775.             return err;
  1776.         }
  1777.         return NO_ERROR;
  1778.     case DIF_ALLOW_INSTALL :
  1779.         TraceMsg(TF_GENERAL, "DisplayClassInstaller DIF_ALLOW_INSTALL n");
  1780.         //
  1781.         // Only allow installation if this is a DEVNODE we don't have a legacy
  1782.         // driver for already.
  1783.         //
  1784.         if (DeskCheckInstallDatabase(hDevInfo,
  1785.                                      pDeviceInfoData) == FALSE)
  1786.         {
  1787.             return ERROR_DI_DONT_INSTALL;
  1788.         }
  1789.         return ERROR_DI_DO_DEFAULT;
  1790.     case DIF_INSTALLDEVICE :
  1791.         TraceMsg(TF_GENERAL, "DisplayClassInstaller DIF_INSTALLDEVICE n");
  1792.         {
  1793.             DISPLAY_DEVICE displayDevice;
  1794.             displayDevice.cb = sizeof(DISPLAY_DEVICE);
  1795.             err = DeskInstallService(hDevInfo,
  1796.                                      pDeviceInfoData,
  1797.                                      ServiceName,
  1798.                                      0);  // not a detect install
  1799.             //
  1800.             // Calling EnumDisplayDevices will rescan the devices, and if a
  1801.             // new device is detected, we will disable and reenable the main
  1802.             // device.
  1803.             // This reset of the display device will clear up any mess caused
  1804.             // by installing a new driver
  1805.             //
  1806.             EnumDisplayDevices(NULL, 0, &displayDevice, 0);
  1807.         }
  1808.         return err;
  1809.     case DIF_REMOVE :
  1810.     default :
  1811.         TraceMsg(TF_GENERAL, "DisplayClassInstaller default function = %dn", (DWORD) InstallFunction);
  1812.         break;
  1813.     }
  1814.     //
  1815.     // If we did not exit from the routine by handling the call, tell the
  1816.     // setup code to handle everything the default way.
  1817.     //
  1818.     return ERROR_DI_DO_DEFAULT;
  1819. }
  1820. DWORD
  1821. MonitorClassInstaller(
  1822.     IN DI_FUNCTION      InstallFunction,
  1823.     IN HDEVINFO         hDevInfo,
  1824.     IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL
  1825.     )
  1826. /*++
  1827. Routine Description:
  1828.   This routine acts as the class installer for Display devices.
  1829. Arguments:
  1830.     InstallFunction - Specifies the device installer function code indicating
  1831.         the action being performed.
  1832.     DeviceInfoSet - Supplies a handle to the device information set being
  1833.         acted upon by this install action.
  1834.     pDeviceInfoData - Optionally, supplies the address of a device information
  1835.         element being acted upon by this install action.
  1836. Return Value:
  1837.     If this function successfully completed the requested action, the return
  1838.         value is NO_ERROR.
  1839.     If the default behavior is to be performed for the requested action, the
  1840.         return value is ERROR_DI_DO_DEFAULT.
  1841.     If an error occurred while attempting to perform the requested action, a
  1842.         Win32 error code is returned.
  1843. --*/
  1844. {
  1845.     TraceMsg(TF_GENERAL, " MonitorClassInstaller function = %dn", (DWORD) InstallFunction);
  1846.     //
  1847.     // If we did not exit from the routine by handling the call, tell the
  1848.     // setup code to handle everything the default way.
  1849.     //
  1850.     return ERROR_DI_DO_DEFAULT;
  1851. }
  1852. /***************************************************************************/
  1853. /***************************************************************************/
  1854. /**                                                                       **/
  1855. /**                           Internal setup call                         **/
  1856. /**                                                                       **/
  1857. /***************************************************************************/
  1858. /***************************************************************************/
  1859. DWORD
  1860. InstallNewDriver(
  1861.     HWND    hwnd,
  1862.     LPCTSTR pszModel,
  1863.     PBOOL   pbKeepEnabled
  1864.     )
  1865. {
  1866.     DWORD err;
  1867.     BOOL bStatus;
  1868.     LPTSTR keyName;
  1869.     DWORD reboot;
  1870.     HMODULE hModule;
  1871.     PINSTALLNEWDEVICE InstallNewDevice;
  1872.     hModule = LoadLibrary(TEXT("newdev.dll"));
  1873.     if (hModule)
  1874.     {
  1875.         InstallNewDevice = (PINSTALLNEWDEVICE)GetProcAddress(hModule, "InstallNewDevice");
  1876.         if (InstallNewDevice)
  1877.         {
  1878.             bStatus = (*InstallNewDevice)(hwnd, (LPGUID) &GUID_DEVCLASS_DISPLAY, &reboot);
  1879.         }
  1880.     }
  1881.     if (bStatus)
  1882.     {
  1883.         DWORD disposition;
  1884.         HKEY hkey;
  1885.         *pbKeepEnabled = KeepEnabled;
  1886.         //
  1887.         // Tell the user the driver was installed.
  1888.         //
  1889.         FmtMessageBox(hwnd,
  1890.                       MB_ICONINFORMATION | MB_OK,
  1891.                       FALSE,
  1892.                       ID_DSP_TXT_INSTALL_DRIVER,
  1893.                       ID_DSP_TXT_DRIVER_INSTALLED);
  1894.         if (PreConfigured == 0)
  1895.         {
  1896.             //
  1897.             // Create a registry key that indicates a new display was
  1898.             // installed.
  1899.             //
  1900.             keyName = SZ_NEW_DISPLAY;
  1901.             if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1902.                                keyName,
  1903.                                0,
  1904.                                NULL,
  1905.                                REG_OPTION_NON_VOLATILE,
  1906.                                KEY_READ | KEY_WRITE,
  1907.                                NULL,
  1908.                                &hkey,
  1909.                                &disposition) == ERROR_SUCCESS)
  1910.             {
  1911.                 RegCloseKey(hkey);
  1912.             }
  1913.         }
  1914.         //
  1915.         // Save into the registry the fact that it will take a reboot
  1916.         // for these changes to take effect
  1917.         //
  1918.         if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1919.                            SZ_REBOOT_NECESSARY,
  1920.                            0,
  1921.                            NULL,
  1922.                            REG_OPTION_VOLATILE,
  1923.                            KEY_READ | KEY_WRITE,
  1924.                            NULL,
  1925.                            &hkey,
  1926.                            &disposition) == ERROR_SUCCESS)
  1927.         {
  1928.             RegCloseKey(hkey);
  1929.         }
  1930.         //
  1931.         // If everything succeeded properly, then we need to reboot the
  1932.         // machine
  1933.         //
  1934.         // Ask the user to reboot the machine.
  1935.         //
  1936.         PropSheet_RestartWindows(ghwndPropSheet);
  1937.         PropSheet_CancelToClose(ghwndPropSheet);
  1938.     }
  1939.     else
  1940.     {
  1941.         err = GetLastError();
  1942.         if (err != ERROR_CANCELLED)
  1943.         {
  1944.             //
  1945.             // Tell the user the driver was not installed properly.
  1946.             //
  1947.             FmtMessageBox(hwnd,
  1948.                           MB_ICONSTOP | MB_OK,
  1949.                           FALSE,
  1950.                           ID_DSP_TXT_INSTALL_DRIVER,
  1951.                           ID_DSP_TXT_DRIVER_INSTALLED_FAILED);
  1952.         }
  1953.     }
  1954.     return err;
  1955. }