Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1403 lines
42 KiB

  1. /* DRIVERS.C
  2. **
  3. ** Copyright (C) Microsoft, 1990, All Rights Reserved.
  4. **
  5. ** Multimedia Control Panel Applet for installing/configuring installable
  6. ** device drivers. See the ispec doc DRIVERS.DOC for more information.
  7. **
  8. ** History:
  9. **
  10. ** Tue Jul 31 1990 -by- MichaelE
  11. ** Created.
  12. **
  13. ** Thu Oct 25 1990 -by- MichaelE
  14. ** Added restart, horz. scroll, added SKIPDESC reading desc. strings.
  15. **
  16. ** Sat Oct 27 1990 -by- MichaelE
  17. ** Added FileCopy. Uses SULIB.LIB and LZCOPY.LIB. Finished stuff
  18. ** for case of installing a driver with more than one type.
  19. **
  20. ** May 1991 -by- JohnYG
  21. ** Added and replaced too many things to list. Better management
  22. ** of removed drivers, correct usage of DRV_INSTALL/DRV_REMOVE,
  23. ** installing VxD's, replaced "Unknown" dialog with an OEMSETUP.INF
  24. ** method, proper "Cancel" method, fixed many potential UAE's.
  25. */
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <ntseapi.h>
  30. #include <windows.h>
  31. #include <mmsystem.h>
  32. #include <memory.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <cpl.h>
  36. #include <cphelp.h>
  37. #include "drivers.h"
  38. #include "sulib.h"
  39. typedef struct
  40. {
  41. int idIcon;
  42. int idName;
  43. int idInfo;
  44. BOOL bEnabled;
  45. DWORD dwContext;
  46. PSTR pszHelp;
  47. } APPLET_INFO;
  48. #define NUM_APPLETS 1
  49. #define OBJECT_SIZE 1024
  50. APPLET_INFO near applets[NUM_APPLETS];
  51. BOOL bBadOemSetup;
  52. BOOL bRestart = FALSE;
  53. int iRestartMessage = 0;
  54. BOOL bInstallBootLine = FALSE;
  55. BOOL bCopyVxD;
  56. BOOL bFindOEM = FALSE;
  57. BOOL bRelated = FALSE;
  58. BOOL bDriversAppInUse;
  59. BOOL bCopyingRelated;
  60. BOOL bDescFileValid;
  61. HANDLE myInstance;
  62. HWND hlistbox;
  63. UINT wHelpMessage;
  64. DWORD dwContext;
  65. PINF pinfOldDefault;
  66. char szDriversHlp[24];
  67. char szLastQuery[20];
  68. char szSetupInf[18];
  69. char szKnown[250];
  70. char szRestartDrv[80];
  71. char szUnlisted[150];
  72. char szRelatedDesc[30];
  73. char szAppName[26];
  74. char szDrivers[12];
  75. char szRemove[12];
  76. char szControlIni[20];
  77. char szSysIni[20];
  78. char szMCI[6];
  79. char szOutOfRemoveSpace[54];
  80. char szDriversDesc[38];
  81. char szUserDrivers[38];
  82. // Where the source of files to copy is - user updates
  83. char szDirOfSrc[MAX_PATH];
  84. char szAddDriver[36];
  85. char szNoDesc[36];
  86. char szError[20];
  87. char szRemoveOrNot[250];
  88. char szRemoveOrNotStrict[250];
  89. char szStringBuf[128];
  90. char szMDrivers[38];
  91. char szMDrivers32[38];
  92. char szFullPath[MAXFILESPECLEN];
  93. char szSystem[MAX_PATH];
  94. char szOemInf[MAX_PATH];
  95. char aszClose[16];
  96. char szFileError[50];
  97. static HANDLE hIList;
  98. static HANDLE hWndMain;
  99. /*
  100. * Global flag telling us if we're allowed to write to ini files
  101. */
  102. BOOL IniFileWriteAllowed;
  103. DWORD GetFileDateTime (LPSTR);
  104. PSTR GetProfile (PSTR,PSTR, PSTR, PSTR, int);
  105. int AddIDriver (HWND, PIDRIVER);
  106. void AddIDrivers (HWND, PSTR, PSTR);
  107. BOOL InitInstalled (HWND, PSTR);
  108. BOOL InitAvailable (HWND, int);
  109. void CloseDrivers (HWND);
  110. void RemoveAvailable (HWND);
  111. BOOL UserInstalled (PSTR);
  112. BOOL RestartDlg (HWND, unsigned, UINT, LONG);
  113. BOOL AddUnlistedDlg (HWND, unsigned, UINT, LONG);
  114. int AvailableDriversDlg (HWND, unsigned, UINT, LONG);
  115. BOOL ListInstalledDlg (HWND, unsigned, UINT, LONG);
  116. LONG CPlApplet (HWND, unsigned, UINT, LONG);
  117. void ReBoot (HWND);
  118. /*
  119. * CheckSectionAccess()
  120. *
  121. * See if we can read/write to a given section
  122. */
  123. BOOL CheckSectionAccess(char *szIniFile, char *SectionName)
  124. {
  125. static char TestKey[] = "TestKey!!!";
  126. static char TestData[] = "TestData";
  127. static char ReturnData[50];
  128. /*
  129. * Check we can write, read back and delete our key
  130. */
  131. return WritePrivateProfileString(SectionName,
  132. TestKey,
  133. TestData,
  134. szIniFile) &&
  135. GetPrivateProfileString(SectionName,
  136. TestKey,
  137. "",
  138. ReturnData,
  139. sizeof(ReturnData),
  140. szIniFile) == (DWORD)strlen(TestData) &&
  141. WritePrivateProfileString(SectionName,
  142. TestKey,
  143. NULL,
  144. szIniFile);
  145. }
  146. /*
  147. * CheckIniAccess()
  148. *
  149. * Checks access to our 2 .ini file sections - DRIVERS_SECTION and
  150. * MCI_SECTION by just writing and reading some junk
  151. *
  152. * Basically if we don't have access to these sections we're not
  153. * going to allow Add and Remove. The individual MCI drivers must
  154. * take care not to put their data into non-writeable storage although
  155. * this completely messes up the default parameters thing so we're going
  156. * to put these into a well-known key in the win.ini file (ie per user).
  157. *
  158. */
  159. BOOL CheckIniAccess(void)
  160. {
  161. return CheckSectionAccess(szSysIni, szDrivers) &&
  162. CheckSectionAccess(szSysIni, szMCI) &&
  163. CheckSectionAccess(szControlIni, szUserDrivers) &&
  164. CheckSectionAccess(szControlIni, szDriversDesc) &&
  165. CheckSectionAccess(szControlIni, szRelatedDesc);
  166. }
  167. /*
  168. * QueryRemoveDrivers()
  169. *
  170. * Ask the user if they're sure. If the Driver is one required by the
  171. * system (ie not listed in [Userinstallable.drivers] in control.ini)
  172. * warn the user of that too.
  173. */
  174. BOOL NEAR PASCAL QueryRemoveDrivers(HWND hDlg, PSTR szKey, PSTR szDesc)
  175. {
  176. char bufout[MAXSTR];
  177. if (UserInstalled(szKey))
  178. wsprintf(bufout, szRemoveOrNot, (LPSTR)szDesc);
  179. else
  180. wsprintf(bufout, szRemoveOrNotStrict, (LPSTR)szDesc);
  181. return (MessageBox(hDlg, bufout, szRemove,
  182. MB_ICONEXCLAMATION | MB_TASKMODAL | MB_YESNO) == IDYES );
  183. }
  184. /*
  185. * GetProfile()
  186. *
  187. * Get private profile strings.
  188. */
  189. PSTR GetProfile(PSTR pstrAppName, PSTR pstrKeyName, PSTR pstrIniFile,
  190. PSTR pstrRet, int iSize)
  191. {
  192. char szNULL[2];
  193. szNULL[0] = '\0';
  194. GetPrivateProfileString(pstrAppName, (pstrKeyName==NULL) ? NULL :
  195. (LPSTR)pstrKeyName, szNULL, pstrRet, iSize, pstrIniFile);
  196. return(pstrRet);
  197. }
  198. /*********************************************************************
  199. *
  200. * AddIDriver()
  201. *
  202. * Add the passed driver to the Installed drivers list box, return
  203. * the list box index.
  204. *
  205. *********************************************************************/
  206. int AddIDriver(HWND hWnd, PIDRIVER pIDriver)
  207. {
  208. int iIndex;
  209. PIDRIVER pIDriverlocal;
  210. iIndex = (int)SendMessage(hWnd, LB_GETCOUNT, 0, 0L);
  211. while ( iIndex-- > 0)
  212. if ( (int)(pIDriverlocal = (PIDRIVER)SendMessage(hWnd, LB_GETITEMDATA, iIndex, 0L)) != LB_ERR)
  213. if (!FileNameCmp(pIDriverlocal->szFile, pIDriver->szFile))
  214. return(0);
  215. //
  216. // create the list box item
  217. //
  218. if ((iIndex = (int)SendMessage(hWnd, LB_ADDSTRING, 0,
  219. (LONG)(LPSTR)pIDriver->szDesc)) != LB_ERR)
  220. SendMessage(hWnd, LB_SETITEMDATA, iIndex, (LONG)pIDriver);
  221. return(iIndex);
  222. }
  223. /*********************************************************************
  224. *
  225. * AddIDrivers()
  226. *
  227. * Add drivers in the passed key strings list to the Installed Drivers box.
  228. *
  229. *********************************************************************/
  230. void AddIDrivers(HWND hWnd, PSTR pstrKeys, PSTR pstrSection)
  231. {
  232. PIDRIVER pIDriver;
  233. HWND hWndInstalled;
  234. PSTR pstrKey;
  235. PSTR pstrDesc;
  236. hWndInstalled = GetDlgItem(hWnd, LB_INSTALLED);
  237. pstrKey = pstrKeys;
  238. pstrDesc = (PSTR)LocalAlloc(LPTR, MAXSTR);
  239. /*
  240. * parse key strings for profile, and make IDRIVER structs
  241. */
  242. while ( *pstrKey )
  243. {
  244. pIDriver = (PIDRIVER)LocalAlloc(LPTR, sizeof(IDRIVER));
  245. if ( pIDriver )
  246. {
  247. PSTR pstr;
  248. if (*GetProfile(pstrSection, pstrKey, szSysIni, pIDriver->szFile,
  249. sizeof(pIDriver->szFile)) == '\0')
  250. {
  251. LocalFree((HANDLE)pIDriver);
  252. goto nextkey;
  253. }
  254. for ( pstr=pIDriver->szFile; *pstr && (*pstr!=COMMA) &&
  255. (*pstr!=SPACE); pstr++ )
  256. ;
  257. *pstr = '\0';
  258. #ifdef TRASHDRIVERDESC
  259. if (bDescFileValid)
  260. #endif
  261. /*
  262. * try to load the cached description
  263. */
  264. GetProfile(szDriversDesc,
  265. pIDriver->szFile,
  266. szControlIni,
  267. pIDriver->szDesc,
  268. sizeof(pIDriver->szDesc));
  269. /*
  270. * if we failed, then try to get the information from
  271. * mmdriver.inf or the exehdr
  272. */
  273. if (pIDriver->szDesc[0] == '\0')
  274. {
  275. if (LoadDesc(pIDriver, pstrKey, pstrDesc) != DESC_NOFILE)
  276. {
  277. if (!*pstrDesc)
  278. {
  279. /*
  280. * failed to load a description.
  281. * The file isn't in setup.inf
  282. * and doesn't have exehdr information
  283. */
  284. lstrcpy(pIDriver->szDesc, pIDriver->szFile);
  285. lstrcat(pIDriver->szDesc, szNoDesc);
  286. }
  287. else
  288. lstrcpy(pIDriver->szDesc, pstrDesc);
  289. WritePrivateProfileString(szDriversDesc, pIDriver->szFile,
  290. pIDriver->szDesc, szControlIni);
  291. } else {
  292. LocalFree((HANDLE)pIDriver);
  293. goto nextkey;
  294. }
  295. }
  296. strncpy(pIDriver->szAlias, pstrKey, sizeof(pIDriver->szAlias));
  297. pIDriver->szAlias[sizeof(pIDriver->szAlias) - 1] = 0;
  298. mbstowcs(pIDriver->wszAlias, pIDriver->szAlias, MAX_PATH);
  299. strncpy(pIDriver->szSection, pstrSection,sizeof(pIDriver->szSection));
  300. pIDriver->szSection[sizeof(pIDriver->szSection) - 1] = 0;
  301. mbstowcs(pIDriver->wszSection, pIDriver->szSection, MAX_PATH);
  302. pIDriver->KernelDriver = IsFileKernelDriver(pIDriver->szFile);
  303. pIDriver->fQueryable = pIDriver->KernelDriver ? 0 : -1;
  304. if (AddIDriver(hWndInstalled, pIDriver) < LB_OKAY)
  305. LocalFree((HANDLE)pIDriver);
  306. }
  307. else
  308. break; //ERROR Low Memory
  309. nextkey: while (*pstrKey++);
  310. }
  311. LocalFree((HANDLE)pstrDesc);
  312. }
  313. /*********************************************************************
  314. *
  315. * FindInstallableDriversSection()
  316. *
  317. *********************************************************************/
  318. PINF FindInstallableDriversSection(PINF pinf)
  319. {
  320. PINF pinfFound;
  321. pinfFound = infFindSection(pinf, szMDrivers32);
  322. if (pinfFound == NULL) {
  323. pinfFound = infFindSection(pinf, szMDrivers);
  324. }
  325. return pinfFound;
  326. }
  327. /*********************************************************************
  328. *
  329. * InitInstalled()
  330. *
  331. * Add the drivers installed in [DRIVERS] and [MCI] to the Installed
  332. * Drivers list box.
  333. *
  334. *********************************************************************/
  335. BOOL InitInstalled(HWND hWnd, PSTR pstrSection)
  336. {
  337. BOOL bSuccess=FALSE;
  338. PSTR pstr;
  339. #ifdef TRASHDRIVERDESC
  340. UINT wTime;
  341. BOOL fForce;
  342. char szOut[10];
  343. wTime = LOWORD(GetFileDateTime(szControlIni)) >> 1;
  344. if (fForce = (GetPrivateProfileInt((LPSTR)szUserDrivers,
  345. (LPSTR)szLastQuery, 0, (LPSTR)szControlIni) != wTime))
  346. {
  347. wsprintf(szOut, "%d", wTime);
  348. WritePrivateProfileString((LPSTR)szUserDrivers, (LPSTR)szLastQuery,
  349. szOut, (LPSTR)szControlIni);
  350. WritePrivateProfileString((LPSTR)szDriversDesc, NULL, NULL,
  351. (LPSTR)szControlIni);
  352. bDescFileValid = FALSE;
  353. }
  354. else
  355. bDescFileValid = TRUE;
  356. #endif
  357. pstr = (PSTR)LocalAlloc(LPTR, SECTION);
  358. if ( pstr )
  359. {
  360. if (*GetProfile(pstrSection, NULL, szSysIni, pstr, SECTION ))
  361. {
  362. AddIDrivers(hWnd,pstr,pstrSection);
  363. bSuccess = TRUE;
  364. }
  365. LocalFree((HANDLE)pstr);
  366. }
  367. return(bSuccess);
  368. }
  369. static VOID CancelToClose(HWND hwnd)
  370. {
  371. char aszText[sizeof(aszClose)];
  372. GetDlgItemText(hwnd, IDCANCEL, aszText, sizeof(aszText));
  373. if (lstrcmp(aszText, aszClose))
  374. SetDlgItemText(hwnd, IDCANCEL, aszClose);
  375. }
  376. static BOOL fRemove=FALSE;
  377. /********************************************************************
  378. *
  379. * ListInstalledDlg()
  380. *
  381. * Display list of installed installable drivers. Return TRUE/FALSE
  382. * indicating if should restart windows.
  383. *
  384. ********************************************************************/
  385. BOOL ListInstalledDlg(HWND hDlg, UINT uMsg, UINT wParam, LONG lParam)
  386. {
  387. DRVCONFIGINFO DrvConfigInfo;
  388. HANDLE hWndI, hWnd;
  389. PIDRIVER pIDriver;
  390. int iIndex;
  391. switch ( uMsg )
  392. {
  393. case WM_INITDIALOG:
  394. wsStartWait();
  395. // Window is redrawn twice at startup but showwindow does not fix it
  396. // ShowWindow(hDlg, TRUE);
  397. hWndI = GetDlgItem(hDlg, LB_INSTALLED);
  398. SendMessage(hWndI,WM_SETREDRAW, FALSE, 0L);
  399. /*
  400. * Handle the fact that we may not be able to update our .ini
  401. * sections
  402. *
  403. */
  404. IniFileWriteAllowed = CheckIniAccess();
  405. if (!IniFileWriteAllowed) {
  406. EnableWindow(GetDlgItem(hDlg, ID_ADD),FALSE);
  407. {
  408. char szCantAdd[120];
  409. LoadString(myInstance, IDS_CANTADD, szCantAdd,
  410. sizeof(szCantAdd));
  411. MessageBox(hDlg, szCantAdd, szError,
  412. MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  413. }
  414. }
  415. if (!(InitInstalled(hDlg, szDrivers) | InitInstalled(hDlg, szMCI)))
  416. {
  417. EnableWindow(GetDlgItem(hDlg, ID_CONFIGURE),FALSE);
  418. EnableWindow(GetDlgItem(hDlg, ID_REMOVE),FALSE);
  419. }
  420. SendMessage(hWndI, LB_SETCURSEL, 0, 0L );
  421. PostMessage(hDlg, WM_COMMAND, MAKELONG(LB_INSTALLED, LBN_SELCHANGE),
  422. (LONG)hWndI);
  423. SendMessage(hWndI,WM_SETREDRAW, TRUE, 0L);
  424. wsEndWait();
  425. break;
  426. case WM_COMMAND:
  427. hlistbox = hWndI = GetDlgItem(hDlg, LB_INSTALLED);
  428. hWndMain = hDlg;
  429. iIndex = (int)SendMessage(hWndI, LB_GETCURSEL, 0, 0L);
  430. pIDriver = (PIDRIVER)SendMessage(hWndI, LB_GETITEMDATA, iIndex, 0L);
  431. switch ( LOWORD(wParam ))
  432. {
  433. case IDH_CHILD_DRIVERS:
  434. goto DoHelp;
  435. case LB_INSTALLED:
  436. switch ( HIWORD(wParam) )
  437. {
  438. case LBN_SELCHANGE:
  439. case LBN_SETFOCUS:
  440. {
  441. BOOL fConfigurable;
  442. fConfigurable = ((iIndex >= LB_OKAY) && IsConfigurable(pIDriver, hDlg));
  443. EnableWindow(GetDlgItem(hDlg, ID_CONFIGURE),
  444. fConfigurable);
  445. // Only enable the button if we are not in the
  446. // process of removing a driver. Otherwise a
  447. // button click can get stacked up, the line
  448. // in the list box can get removed, perhaps as a
  449. // related driver, and bad things start to happen.
  450. EnableWindow(GetDlgItem(hDlg, ID_REMOVE),
  451. IniFileWriteAllowed && !fRemove &&
  452. iIndex != LB_ERR);
  453. break;
  454. }
  455. case LBN_DBLCLK:
  456. if ( IsWindowEnabled(hWnd = GetDlgItem(hDlg, ID_CONFIGURE)) )
  457. PostMessage(hDlg, WM_COMMAND, MAKELONG(ID_CONFIGURE, BN_CLICKED),(LONG)hWnd);
  458. break;
  459. }
  460. break;
  461. case ID_ADD:
  462. DialogBox(myInstance, MAKEINTRESOURCE(DLG_KNOWN), hDlg,
  463. AvailableDriversDlg);
  464. CancelToClose(hDlg);
  465. break;
  466. case ID_CONFIGURE:
  467. {
  468. HANDLE hDriver;
  469. hDriver = OpenDriver(pIDriver->wszAlias,
  470. pIDriver->wszSection,
  471. 0L);
  472. if (hDriver)
  473. {
  474. InitDrvConfigInfo(&DrvConfigInfo, pIDriver);
  475. if ((SendDriverMessage(
  476. hDriver,
  477. DRV_CONFIGURE,
  478. (LONG)hDlg,
  479. (LONG)(LPDRVCONFIGINFO)&DrvConfigInfo) ==
  480. DRVCNF_RESTART))
  481. {
  482. iRestartMessage= 0;
  483. DialogBox(myInstance,
  484. MAKEINTRESOURCE(DLG_RESTART), hDlg, RestartDlg);
  485. }
  486. CloseDriver(hDriver, 0L, 0L);
  487. CancelToClose(hDlg);
  488. }
  489. else
  490. OpenDriverError(hDlg, pIDriver->szDesc, pIDriver->szFile);
  491. }
  492. break;
  493. case ID_REMOVE:
  494. // Prevent any more REMOVE button presses
  495. // Otherwise one can get stacked up and cause trouble,
  496. // particularly if it is assocated with a driver that
  497. // is automatically removed. We have to use a static
  498. // as any focus changes cause the button to change state.
  499. fRemove = TRUE;
  500. EnableWindow(GetDlgItem(hDlg, ID_REMOVE),FALSE);
  501. if (QueryRemoveDrivers(hDlg, pIDriver->szAlias, pIDriver->szDesc))
  502. {
  503. LONG Status;
  504. Status = PostRemove(hWndI, pIDriver, TRUE, iIndex);
  505. if (Status != DRVCNF_CANCEL)
  506. {
  507. // As we have removed a driver we need to reset
  508. // the current selection
  509. PostMessage(hWndI, LB_SETCURSEL, 0, 0L );
  510. iRestartMessage= IDS_RESTART_REM;
  511. if (Status == DRVCNF_RESTART) {
  512. DialogBox(myInstance,
  513. MAKEINTRESOURCE(DLG_RESTART), hDlg, RestartDlg);
  514. }
  515. }
  516. }
  517. /* Reenable the Config/Remove buttons */
  518. fRemove = FALSE; // Remove can be activated again
  519. // Force the button state to be updated
  520. PostMessage(hWndMain, WM_COMMAND,
  521. MAKELONG(LB_INSTALLED, LBN_SELCHANGE),
  522. (LONG)hWndI);
  523. CancelToClose(hDlg);
  524. break;
  525. case IDCANCEL:
  526. wsStartWait();
  527. /*
  528. * free the driver structs added as DATAITEM
  529. */
  530. CloseDrivers(hWndI);
  531. wsEndWait();
  532. EndDialog(hDlg, FALSE);
  533. break;
  534. default:
  535. return(FALSE);
  536. }
  537. break;
  538. case WM_DESTROY:
  539. return(FALSE);
  540. default:
  541. if (uMsg == wHelpMessage)
  542. {
  543. DoHelp:
  544. WinHelp(hDlg, szDriversHlp, HELP_CONTEXT, IDH_CHILD_DRIVERS);
  545. return TRUE;
  546. }
  547. else
  548. return FALSE;
  549. break;
  550. }
  551. return(TRUE);
  552. }
  553. /*--------------------------------------------------------------------------*
  554. * *
  555. * *
  556. * LB_AVAILABLE Dialog Routines *
  557. * *
  558. * *
  559. *--------------------------------------------------------------------------*/
  560. /*
  561. * DLG: LB_AVAILABLE
  562. *
  563. * InitAvailable()
  564. *
  565. * Add the available drivers from mmdriver.inf to the passed list box.
  566. * The format of [Installable.drivers] in setup.inf is:
  567. * profile=disk#:driverfile,"type1,type2","Installable driver Description","vxd1.386,vxd2.386","opt1,2,3"
  568. *
  569. * for example:
  570. *
  571. * driver1=6:sndblst.drv,"midi,wave","SoundBlaster MIDI and Waveform drivers","vdmad.386,vadmad.386","3,260"
  572. */
  573. BOOL InitAvailable(HWND hWnd, int iLine)
  574. {
  575. PINF pinf;
  576. BOOL bInitd=FALSE;
  577. PSTR pstrKey;
  578. int iIndex;
  579. char szDesc[MAX_INF_LINE_LEN];
  580. SendMessage(hWnd,WM_SETREDRAW, FALSE, 0L);
  581. /*
  582. * Parse the list of keywords and load their strings
  583. */
  584. for (pinf = FindInstallableDriversSection(NULL); pinf; pinf = infNextLine(pinf))
  585. {
  586. //
  587. // found at least one keyname!
  588. //
  589. bInitd = TRUE;
  590. if ( (pstrKey = (PSTR)LocalAlloc(LPTR, MAX_SYS_INF_LEN)) != NULL )
  591. infParseField(pinf, 0, pstrKey);
  592. else
  593. break;
  594. /*
  595. * add the installable driver's description to listbox, and filename as data
  596. */
  597. infParseField(pinf, 3, szDesc);
  598. if ( (iIndex = (int)SendMessage(hWnd, LB_ADDSTRING, 0, (LONG)(LPSTR)szDesc)) != LB_ERR )
  599. SendMessage(hWnd, LB_SETITEMDATA, iIndex, (LONG)pstrKey);
  600. }
  601. if (iLine == UNLIST_LINE)
  602. {
  603. //
  604. // Add the "Install unlisted..." choice to the top of the list
  605. // box.
  606. LoadString(myInstance, IDS_UPDATED, szDesc, sizeof(szDesc));
  607. if ((iIndex = (int)(LONG)SendMessage(hWnd, LB_INSERTSTRING, 0, (LPARAM)(LPSTR)szDesc)) != LB_ERR)
  608. SendMessage(hWnd, LB_SETITEMDATA, (WPARAM)iIndex, (LPARAM)0);
  609. }
  610. if (bInitd)
  611. SendMessage(hWnd, LB_SETCURSEL, 0, 0L );
  612. SendMessage(hWnd,WM_SETREDRAW, TRUE, 0L);
  613. return(bInitd);
  614. }
  615. /*
  616. * DLG: LB_AVAILABLE
  617. *
  618. * RemoveAvailable()
  619. *
  620. * Remove all drivers from the listbox and free all storage associated with
  621. * the keyname
  622. */
  623. void RemoveAvailable(HWND hWnd)
  624. {
  625. int iIndex;
  626. HWND hWndA;
  627. PSTR pstrKey;
  628. hWndA = GetDlgItem(hWnd, LB_AVAILABLE);
  629. iIndex = (int)SendMessage(hWndA, LB_GETCOUNT, 0, 0L);
  630. while ( iIndex-- > 0)
  631. {
  632. if (( (int)(pstrKey = (PSTR)SendMessage(hWndA, LB_GETITEMDATA, iIndex,
  633. 0L)) != LB_ERR ) && pstrKey)
  634. LocalFree((HLOCAL)pstrKey);
  635. }
  636. }
  637. /*
  638. * DLG: LB_AVAILABLE
  639. *
  640. * AvailableDriversDlg()
  641. *
  642. * List the available installable drivers or return FALSE if there are none.
  643. */
  644. int AvailableDriversDlg(HWND hWnd, UINT uMsg, UINT wParam, LONG lParam)
  645. {
  646. PSTR pstrKey; //-jyg- added
  647. HWND hWndA, hWndI;
  648. int iIndex;
  649. switch ( uMsg )
  650. {
  651. case WM_INITDIALOG:
  652. ShowWindow(hWnd, TRUE);
  653. wsStartWait();
  654. if (pinfOldDefault)
  655. {
  656. infSetDefault(pinfOldDefault);
  657. pinfOldDefault = NULL;
  658. }
  659. if ( !InitAvailable(hWndA = GetDlgItem(hWnd, LB_AVAILABLE), UNLIST_LINE))
  660. {
  661. /*
  662. * We weren't able to find the [installable.drivers] section
  663. * of the
  664. * mmdriver.inf OR it was corrupt. Go ahead and query the
  665. * user to find an oemsetup.inf to make our default. This
  666. * is a bad state.
  667. */
  668. EndDialog(hWnd, FALSE);
  669. bFindOEM = TRUE;
  670. strcpy(szDrv, szOemInf);
  671. if (DialogBox(myInstance, MAKEINTRESOURCE(DLG_INSERTDISK),
  672. hWnd, AddDriversDlg) == TRUE)
  673. PostMessage(hWnd, WM_INITDIALOG, 0, 0L);
  674. else
  675. pinfOldDefault = infSetDefault(pinfOldDefault);
  676. bFindOEM = FALSE;
  677. }
  678. wsEndWait();
  679. break;
  680. case WM_COMMAND:
  681. switch ( LOWORD(wParam ))
  682. {
  683. case IDH_DLG_ADD_DRIVERS:
  684. goto DoHelp;
  685. case LB_AVAILABLE:
  686. // Hm... We've picked it.
  687. if ( HIWORD(wParam) == LBN_DBLCLK )
  688. SendMessage(hWnd, WM_COMMAND, IDOK, 0L);
  689. break;
  690. case IDOK:
  691. /*
  692. * We've made our selection
  693. */
  694. hWndA = GetDlgItem(hWnd, LB_AVAILABLE);
  695. if ( (iIndex = (int)SendMessage(hWndA, LB_GETCURSEL, 0, 0L)) != LB_ERR)
  696. {
  697. if (!iIndex)
  698. {
  699. /*
  700. * The first entry is for OEMs
  701. */
  702. int iFound;
  703. bBadOemSetup = FALSE;
  704. bFindOEM = TRUE;
  705. hMesgBoxParent = hWnd;
  706. while ((iFound = DialogBox(myInstance,
  707. MAKEINTRESOURCE(DLG_INSERTDISK), hWnd,
  708. AddDriversDlg)) == 2);
  709. if (iFound == 1)
  710. {
  711. RemoveAvailable(hWnd);
  712. SendDlgItemMessage(hWnd, LB_AVAILABLE,
  713. LB_RESETCONTENT, 0, 0L);
  714. PostMessage(hWnd, WM_INITDIALOG, 0, 0L);
  715. }
  716. bFindOEM = FALSE;
  717. }
  718. else
  719. {
  720. /*
  721. * The user selected an entry from our .inf
  722. */
  723. wsStartWait();
  724. /*
  725. * The data associated with the list item is
  726. * the driver key name (field 0 in the inf file).
  727. */
  728. pstrKey = (PSTR)SendMessage(hWndA, LB_GETITEMDATA, iIndex, 0L);
  729. bCopyingRelated = FALSE;
  730. bQueryExist = TRUE;
  731. if (InstallDrivers(hWndMain, hWnd, pstrKey))
  732. {
  733. hWndI = GetDlgItem(hWndMain, LB_INSTALLED);
  734. PostMessage(hWndI, LB_SETCURSEL, 0, 0L );
  735. PostMessage(hWndMain, WM_COMMAND,
  736. MAKELONG(LB_INSTALLED, LBN_SELCHANGE),
  737. (LONG)hWndI);
  738. wsEndWait();
  739. /*
  740. * If bRestart is true then the system must
  741. * be restarted to activate these changes
  742. */
  743. if (bRestart)
  744. {
  745. iRestartMessage= IDS_RESTART_ADD;
  746. DialogBox(myInstance,
  747. MAKEINTRESOURCE(DLG_RESTART), hWnd,
  748. RestartDlg);
  749. }
  750. }
  751. else
  752. wsEndWait();
  753. bRestart = FALSE;
  754. bRelated = FALSE;
  755. }
  756. }
  757. EndDialog(hWnd, FALSE);
  758. break;
  759. case IDCANCEL:
  760. EndDialog(hWnd, FALSE);
  761. break;
  762. default:
  763. return(FALSE);
  764. }
  765. break;
  766. case WM_DESTROY:
  767. //
  768. // free the strings added as DATAITEM to the avail list
  769. RemoveAvailable(hWnd);
  770. return(FALSE);
  771. default:
  772. if (uMsg == wHelpMessage)
  773. {
  774. DoHelp:
  775. WinHelp(hWnd, szDriversHlp, HELP_CONTEXT, IDH_DLG_ADD_DRIVERS);
  776. return TRUE;
  777. }
  778. else
  779. return FALSE;
  780. break;
  781. }
  782. return(TRUE);
  783. }
  784. /* Main CPL proc. This is for communication with CPL.EXE
  785. */
  786. LONG CPlApplet(HWND hCPlWnd, UINT uMsg, UINT lParam1, LONG lParam2)
  787. {
  788. int i;
  789. LPNEWCPLINFO lpCPlInfo;
  790. char strOldDir[MAX_PATH], strSysDir[MAX_PATH];
  791. switch( uMsg )
  792. {
  793. case CPL_INIT:
  794. wHelpMessage = RegisterWindowMessage("ShellHelp");
  795. return(TRUE);
  796. case CPL_GETCOUNT:
  797. return(1);
  798. case CPL_NEWINQUIRE:
  799. i = 0;
  800. lpCPlInfo = (LPNEWCPLINFO)lParam2;
  801. lpCPlInfo->hIcon = LoadIcon(myInstance,
  802. MAKEINTRESOURCE(applets[i].idIcon));
  803. if(!LoadString(myInstance, applets[i].idName, lpCPlInfo->szName,
  804. sizeof(lpCPlInfo->szName)))
  805. lpCPlInfo->szName[0] = 0;
  806. if(!LoadString(myInstance, applets[i].idInfo, lpCPlInfo->szInfo,
  807. sizeof(lpCPlInfo->szInfo)))
  808. lpCPlInfo->szInfo[0] = 0;
  809. lpCPlInfo->dwSize = sizeof(NEWCPLINFO);
  810. lpCPlInfo->lData = (LONG)i;
  811. lpCPlInfo->dwHelpContext = applets[i].dwContext;
  812. lstrcpy(lpCPlInfo->szHelpFile, applets[i].pszHelp);
  813. break;
  814. case CPL_DBLCLK:
  815. if (bDriversAppInUse)
  816. {
  817. MessageBeep(0);
  818. return (FALSE);
  819. }
  820. bDriversAppInUse = TRUE;
  821. pinfOldDefault = NULL;
  822. GetSystemDirectory(strSysDir, MAX_PATH);
  823. GetCurrentDirectory(MAX_PATH, strOldDir);
  824. /*
  825. * Switch to the system directory for our work
  826. */
  827. SetCurrentDirectory(strSysDir);
  828. /*
  829. * Call initialization routine
  830. */
  831. wsInfParseInit();
  832. if (DialogBox(myInstance,
  833. MAKEINTRESOURCE(DLG_INSTALLED),
  834. hCPlWnd,
  835. ListInstalledDlg)) {
  836. /*
  837. * they changed configuration of a driver and said 'yes, restart'
  838. */
  839. ReBoot(hCPlWnd);
  840. }
  841. infClose(NULL);
  842. /*
  843. * Restore current directory setting
  844. */
  845. SetCurrentDirectory(strOldDir);
  846. //SetActiveWindow(hCPlWnd);
  847. bDriversAppInUse = FALSE;
  848. return (TRUE);
  849. break;
  850. case CPL_EXIT:
  851. break;
  852. }
  853. return(0L);
  854. }
  855. BOOL DllInitialize( IN PVOID hInstance
  856. , IN DWORD ulReason
  857. , IN PCONTEXT pctx OPTIONAL
  858. )
  859. {
  860. if (ulReason != DLL_PROCESS_ATTACH)
  861. return TRUE;
  862. myInstance = hInstance;
  863. LoadString(myInstance, IDS_CLOSE, aszClose, sizeof(aszClose));
  864. LoadString(myInstance, IDS_DRIVERDESC, szDriversDesc, sizeof(szDriversDesc));
  865. LoadString(myInstance, IDS_FILE_ERROR, szFileError, sizeof(szFileError));
  866. LoadString(myInstance, IDS_INSTALLDRIVERS, szMDrivers, sizeof(szMDrivers));
  867. LoadString(myInstance, IDS_INSTALLDRIVERS32, szMDrivers32, sizeof(szMDrivers));
  868. LoadString(myInstance, IDS_RELATEDDESC, szRelatedDesc, sizeof(szRelatedDesc));
  869. LoadString(myInstance, IDS_USERINSTALLDRIVERS, szUserDrivers, sizeof(szUserDrivers));
  870. LoadString(myInstance, IDS_UNLISTED, (LPSTR)szUnlisted, sizeof(szUnlisted));
  871. LoadString(myInstance, IDS_KNOWN, szKnown, sizeof(szKnown));
  872. LoadString(myInstance, IDS_OEMSETUP, szOemInf, sizeof(szOemInf));
  873. LoadString(myInstance, IDS_SYSTEM, szSystem, sizeof(szSystem));
  874. LoadString(myInstance, IDS_OUT_OF_REMOVE_SPACE, szOutOfRemoveSpace, sizeof(szOutOfRemoveSpace));
  875. LoadString(myInstance, IDS_NO_DESCRIPTION, szNoDesc, sizeof(szNoDesc));
  876. LoadString(myInstance, IDS_ERRORBOX, szError, sizeof(szError));
  877. LoadString(myInstance, IDS_REMOVEORNOT, szRemoveOrNot, sizeof(szRemoveOrNot));
  878. LoadString(myInstance, IDS_REMOVEORNOTSTRICT, szRemoveOrNotStrict, sizeof(szRemoveOrNotStrict));
  879. LoadString(myInstance, IDS_SETUPINF, szSetupInf, sizeof(szSetupInf));
  880. LoadString(myInstance, IDS_APPNAME, szAppName, sizeof(szAppName));
  881. LoadString(myInstance, IDS_DRIVERS, szDrivers, sizeof(szDrivers));
  882. LoadString(myInstance, IDS_REMOVE, szRemove, sizeof(szRemove));
  883. LoadString(myInstance, IDS_CONTROLINI, szControlIni, sizeof(szControlIni));
  884. LoadString(myInstance, IDS_SYSINI, szSysIni, sizeof(szSysIni));
  885. LoadString(myInstance, IDS_MCI, szMCI, sizeof(szMCI));
  886. LoadString(myInstance, IDS_DEFDRIVE, szDirOfSrc, sizeof(szDirOfSrc));
  887. LoadString(myInstance, IDS_CONTROL_HLP, szDriversHlp, sizeof(szDriversHlp));
  888. LoadString(myInstance, IDS_LASTQUERY, szLastQuery, sizeof(szLastQuery));
  889. applets[0].idIcon = DRIVERS_ICON;
  890. applets[0].idName = IDS_NAME;
  891. applets[0].idInfo = IDS_INFO;
  892. applets[0].bEnabled = TRUE;
  893. applets[0].dwContext = IDH_CHILD_DRIVERS;
  894. applets[0].pszHelp = szDriversHlp;
  895. return TRUE;
  896. }
  897. void DeleteCPLCache(void)
  898. {
  899. HKEY hKeyCache;
  900. if (ERROR_SUCCESS ==
  901. RegOpenKey(HKEY_CURRENT_USER,
  902. TEXT("Control Panel\\Cache\\multimed.cpl"),
  903. &hKeyCache)) {
  904. for ( ; ; ) {
  905. TCHAR Name[50];
  906. if (ERROR_SUCCESS ==
  907. RegEnumKey(hKeyCache,
  908. 0,
  909. Name,
  910. sizeof(Name) / sizeof(Name[0]))) {
  911. HKEY hSubKey;
  912. RegDeleteKey(hKeyCache, Name);
  913. } else {
  914. break; // leave loop
  915. }
  916. }
  917. RegDeleteKey(hKeyCache, NULL);
  918. RegCloseKey(hKeyCache);
  919. }
  920. }
  921. /*
  922. ** RestartDlg()
  923. **
  924. ** Offer user the choice to (not) restart windows.
  925. */
  926. BOOL RestartDlg(HWND hDlg, unsigned uiMessage, UINT wParam, LONG lParam)
  927. {
  928. switch (uiMessage)
  929. {
  930. case WM_COMMAND:
  931. switch (LOWORD(wParam))
  932. {
  933. case IDCANCEL:
  934. //
  935. // don't restart windows
  936. //
  937. EndDialog(hDlg, FALSE);
  938. break;
  939. case IDOK:
  940. //
  941. // do restart windows, *dont* dismiss dialog incase
  942. // the user canceled it.
  943. //
  944. ReBoot(hDlg);
  945. SetActiveWindow(hDlg);
  946. //EndDialog(hDlg, TRUE);
  947. break;
  948. default:
  949. return FALSE;
  950. }
  951. return TRUE;
  952. case WM_INITDIALOG:
  953. /*
  954. ** Delete the control panel's cache so it will get it
  955. ** right!
  956. */
  957. DeleteCPLCache();
  958. if (iRestartMessage)
  959. {
  960. char szMesg1[300];
  961. char szMesg2[300];
  962. LoadString(myInstance, iRestartMessage, szMesg1, sizeof(szMesg1));
  963. wsprintf(szMesg2, szMesg1, (LPSTR)szRestartDrv);
  964. SetDlgItemText(hDlg, IDS_RESTARTTEXT, (LPSTR)szMesg2);
  965. }
  966. return TRUE;
  967. case WM_KEYUP:
  968. if (wParam == VK_F3)
  969. //
  970. // don't restart windows
  971. //
  972. EndDialog(hDlg, FALSE);
  973. break;
  974. default:
  975. break;
  976. }
  977. return FALSE;
  978. }
  979. /*
  980. * UserInstalled()
  981. *
  982. *
  983. */
  984. BOOL UserInstalled(PSTR szKey)
  985. {
  986. char buf[MAXSTR];
  987. if (*GetProfile(szUserDrivers, (LPSTR)szKey, szControlIni, buf, MAXSTR) != '\0')
  988. return(TRUE);
  989. else
  990. return(FALSE);
  991. }
  992. /*
  993. * AddUnlistedDlg()
  994. *
  995. * The following function processes requests by the user to install unlisted
  996. * or updated drivers.
  997. *
  998. * PARAMETERS: The normal Dialog box parameters
  999. * RETURN VALUE: The usual Dialog box return value
  1000. */
  1001. BOOL AddUnlistedDlg(HWND hDlg, unsigned nMsg, UINT wParam, LONG lParam)
  1002. {
  1003. switch (nMsg)
  1004. {
  1005. case WM_INITDIALOG:
  1006. {
  1007. HWND hListDrivers;
  1008. BOOL bFoundDrivers;
  1009. wsStartWait();
  1010. hListDrivers = GetDlgItem(hDlg, LB_UNLISTED);
  1011. /* Search for drivers */
  1012. bFoundDrivers = InitAvailable(hListDrivers, NO_UNLIST_LINE);
  1013. if (!bFoundDrivers)
  1014. {
  1015. //
  1016. // We weren't able to find the MMDRIVERS section of the
  1017. // setup.inf OR it was corrupt. Go ahead and query the
  1018. // user to find an oemsetup.inf to make our default. This
  1019. // is a bad state.
  1020. //
  1021. int iFound;
  1022. bFindOEM = TRUE;
  1023. bBadOemSetup = TRUE;
  1024. while ((iFound = DialogBox(myInstance,
  1025. MAKEINTRESOURCE(DLG_INSERTDISK), hMesgBoxParent,
  1026. AddDriversDlg)) == 2);
  1027. bFindOEM = FALSE;
  1028. if (iFound == 1)
  1029. {
  1030. SendDlgItemMessage(hDlg, LB_AVAILABLE,
  1031. LB_RESETCONTENT, 0, 0L);
  1032. PostMessage(hDlg, WM_INITDIALOG, 0, 0L);
  1033. }
  1034. EndDialog(hDlg, FALSE);
  1035. }
  1036. SendMessage(hListDrivers, LB_SETCURSEL, 0, 0L);
  1037. wsEndWait();
  1038. break;
  1039. }
  1040. case WM_COMMAND:
  1041. switch (LOWORD(wParam))
  1042. {
  1043. case IDH_DLG_ADD_UNKNOWN:
  1044. goto DoHelp;
  1045. case LB_UNLISTED:
  1046. if (HIWORD(wParam) != LBN_DBLCLK)
  1047. break;
  1048. // else Fall through here
  1049. case IDOK:
  1050. {
  1051. HWND hWndI, hWndA;
  1052. int iIndex;
  1053. PSTR pstrKey;
  1054. hWndA = GetDlgItem(hDlg, LB_UNLISTED);
  1055. if ( (iIndex = (int)SendMessage(hWndA, LB_GETCURSEL, 0, 0L))
  1056. != LB_ERR)
  1057. {
  1058. wsStartWait();
  1059. pstrKey = (PSTR)SendMessage(hWndA, LB_GETITEMDATA, iIndex, 0L);
  1060. bCopyingRelated = FALSE;
  1061. bQueryExist = TRUE;
  1062. if (InstallDrivers(hWndMain, hDlg, pstrKey))
  1063. {
  1064. hWndI = GetDlgItem(hWndMain, LB_INSTALLED);
  1065. PostMessage(hWndI, LB_SETCURSEL, 0, 0L );
  1066. PostMessage(hWndMain, WM_COMMAND,
  1067. MAKELONG(LB_INSTALLED, LBN_SELCHANGE),
  1068. (LONG)hWndI);
  1069. wsEndWait();
  1070. if (bRestart)
  1071. {
  1072. iRestartMessage= IDS_RESTART_ADD;
  1073. DialogBox(myInstance, MAKEINTRESOURCE(DLG_RESTART),
  1074. hDlg, RestartDlg);
  1075. }
  1076. }
  1077. else
  1078. wsEndWait();
  1079. bRelated = FALSE;
  1080. bRestart = FALSE;
  1081. }
  1082. EndDialog(hDlg, FALSE);
  1083. }
  1084. break;
  1085. case IDCANCEL:
  1086. EndDialog(hDlg, wParam);
  1087. break;
  1088. default:
  1089. return FALSE;
  1090. }
  1091. default:
  1092. if (nMsg == wHelpMessage)
  1093. {
  1094. DoHelp:
  1095. WinHelp(hDlg, szDriversHlp, HELP_CONTEXT, IDH_DLG_ADD_UNKNOWN);
  1096. break;
  1097. }
  1098. else
  1099. return FALSE;
  1100. }
  1101. return TRUE;
  1102. }
  1103. /*
  1104. * ReBoot()
  1105. *
  1106. * Restart the system. If this fails we put up a message box
  1107. */
  1108. void ReBoot(HWND hDlg)
  1109. {
  1110. DWORD Error;
  1111. BOOLEAN WasEnabled;
  1112. /*
  1113. * We must adjust our privilege level to be allowed to restart the
  1114. * system
  1115. */
  1116. RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
  1117. TRUE,
  1118. FALSE,
  1119. &WasEnabled
  1120. );
  1121. /*
  1122. * Try to reboot the system
  1123. */
  1124. if (!ExitWindowsEx(EWX_REBOOT, 0xFFFFFFFF)) {
  1125. Error = GetLastError();
  1126. /*
  1127. * Put up a message box if we failed
  1128. */
  1129. if (Error != NO_ERROR) {
  1130. char szCantRestart[80];
  1131. LoadString(myInstance,
  1132. Error == ERROR_PRIVILEGE_NOT_HELD ||
  1133. Error == ERROR_NOT_ALL_ASSIGNED ||
  1134. Error == ERROR_ACCESS_DENIED ?
  1135. IDS_CANNOT_RESTART_PRIVILEGE :
  1136. IDS_CANNOT_RESTART_UNKNOWN,
  1137. szCantRestart,
  1138. sizeof(szCantRestart));
  1139. MessageBox(hDlg, szCantRestart, szError,
  1140. MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  1141. }
  1142. }
  1143. }
  1144. /*
  1145. * CloseDrivers()
  1146. *
  1147. * Make free memory for drivers.
  1148. */
  1149. void CloseDrivers(HWND hWnd)
  1150. {
  1151. PIDRIVER pIDriver;
  1152. int iIndex;
  1153. /*
  1154. * Go through the drivers remaining in the Installed list
  1155. */
  1156. iIndex = (int)SendMessage(hWnd, LB_GETCOUNT, 0, 0L);
  1157. while ( iIndex-- > 0 )
  1158. if ( (int)(pIDriver = (PIDRIVER)SendMessage(hWnd, LB_GETITEMDATA,
  1159. iIndex, 0L)) != LB_ERR)
  1160. {
  1161. LocalFree((HLOCAL)pIDriver);
  1162. }
  1163. }
  1164. void OpenDriverError(HWND hDlg, LPSTR szDriver, LPSTR szFile)
  1165. {
  1166. char szMesg[MAXSTR];
  1167. char szMesg2[MAXSTR];
  1168. LoadString(myInstance, IDS_INSTALLING_DRIVERS, szMesg, sizeof(szMesg));
  1169. wsprintf(szMesg2, szMesg, szDriver, szFile);
  1170. MessageBox(hDlg, szMesg2, szError, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  1171. }