repair.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 18k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * repair - Dialog box property sheet for "Repair"
  3.  */
  4. #include "tweakui.h"
  5. #pragma BEGIN_CONST_DATA
  6. KL const c_klRegView = { &g_hkCUSMWCV, c_tszRegedit, c_tszView };
  7. const static DWORD CODESEG rgdwHelp[] = {
  8. #if 0
  9. IDC_REBUILDCACHEICON, IDH_REPAIRICON,
  10. IDC_REBUILDCACHE, IDH_REPAIRICON,
  11. IDC_REPAIRFONTFLDICON, IDH_REPAIRFONTFLD,
  12. IDC_REPAIRFONTFLD, IDH_REPAIRFONTFLD,
  13. IDC_REPAIRREGEDITICON, IDH_REPAIRREGEDIT,
  14. IDC_REPAIRREGEDIT, IDH_REPAIRREGEDIT,
  15. IDC_REPAIRASSOCICON, IDH_REPAIRASSOC,
  16. IDC_REPAIRASSOC, IDH_REPAIRASSOC,
  17. IDC_REPAIRDLLSICON, IDH_REPAIRDLLS,
  18. IDC_REPAIRDLLS, IDH_REPAIRDLLS,
  19. #endif
  20. 0,      0,
  21. };
  22. typedef UINT (PASCAL *REPAIRPATHPROC)(HWND hdlg, LPTSTR ptszBuf);
  23. /*****************************************************************************
  24.  *
  25.  *  _Repair_FileFromResource
  26.  *
  27.  * Given a resource ID and a file name, extract the c_tszExe resource
  28.  * into that file.
  29.  *
  30.  *****************************************************************************/
  31. BOOL PASCAL
  32. _Repair_FileFromResource(UINT idx, LPCTSTR ptszFileName)
  33. {
  34.     BOOL fRc;
  35.     HRSRC hrsrc = FindResource(hinstCur, (LPVOID)idx, c_tszExe);
  36.     if (hrsrc) {
  37. HGLOBAL hglob = LoadResource(hinstCur, hrsrc);
  38. if (hglob) {
  39.     PV pv = LockResource(hglob);
  40.     if (pv) {
  41. HFILE hf = _lcreat(ptszFileName, 0);
  42. if (hf != HFILE_ERROR) {
  43.     UINT cb = SizeofResource(hinstCur, hrsrc);
  44.     fRc = _lwrite(hf, pv, cb) == cb;
  45.     _lclose(hf);
  46.     if (fRc) {
  47.     } else {
  48. DeleteFile(ptszFileName);
  49.     }
  50. }
  51.     } else {
  52. fRc = 0;
  53.     }
  54. } else {
  55.     fRc = 0;
  56. }
  57.     } else {
  58. fRc = 0;
  59.     }
  60.     return fRc;
  61. }
  62. /*****************************************************************************
  63.  *
  64.  *  Repair_RunSetupCqn
  65.  *
  66.  * Put the Setup program into the specified directory and run it.
  67.  * WithTempDirectory will clean up the file when we return.
  68.  *
  69.  *****************************************************************************/
  70. BOOL PASCAL
  71. Repair_RunSetupCqn(LPCTSTR cqn, LPVOID pv)
  72. {
  73.     BOOL fRc;
  74.     fRc = _Repair_FileFromResource(IDX_SETUP, c_tszSetupExe);
  75.     if (fRc) {
  76. STARTUPINFO si;
  77. PROCESS_INFORMATION pi;
  78. ZeroMemory(&si, sizeof(si));
  79. si.cb = sizeof(si);
  80. fRc = CreateProcess(0, c_tszSetupExe, 0, 0, 0, 0, 0, 0, &si, &pi);
  81. if (fRc) {
  82.     CloseHandle(pi.hThread);
  83.     WaitForSingleObject(pi.hProcess, INFINITE);
  84.     CloseHandle(pi.hProcess);
  85. }
  86.     }
  87.     return fRc;
  88. }
  89. #ifndef WINNT
  90. /*****************************************************************************
  91.  *
  92.  *  Repair_MoveFileExWininit
  93.  *
  94.  * Rename a file via wininit.ini.
  95.  *
  96.  *****************************************************************************/
  97. #pragma BEGIN_CONST_DATA
  98. TCHAR c_tszPercentSEqualsPercentS[] = TEXT("%s=%s");
  99. #pragma END_CONST_DATA
  100. void PASCAL
  101. Repair_MoveFileExWininit(LPCTSTR ptszDst, LPCTSTR ptszSrc)
  102. {
  103.     TCHAR tszWininit[MAX_PATH];
  104.     DWORD cb;
  105.     LPSTR pszBuf;
  106.     WIN32_FIND_DATA wfd;
  107.     HANDLE h;
  108.     GetWindowsDirectory(tszWininit, cA(tszWininit));
  109.     lstrcatnBs(tszWininit, c_tszWininit, MAX_PATH);
  110.     /* INI files are always in ANSI */
  111.     h = FindFirstFile(ptszSrc, &wfd);
  112.     if (h != INVALID_HANDLE_VALUE) {
  113. FindClose(h);
  114.     } else {
  115. wfd.nFileSizeLow = 0;
  116.     }
  117.     cb = wfd.nFileSizeLow + MAX_PATH + 1 + MAX_PATH + 3;
  118.     pszBuf = lAlloc(cb);
  119.     if (pszBuf) {
  120. LPSTR psz;
  121. if (!GetPrivateProfileSection(c_tszRename, pszBuf, cb, tszWininit)) {
  122.     /* No such section; create one */
  123.     /* Already done by LocalAlloc (zero-init) */
  124. }
  125. for (psz = pszBuf; psz[0]; psz += lstrlenA(psz) + 1);
  126. psz += wsprintf(psz, c_tszPercentSEqualsPercentS, ptszDst, ptszSrc);
  127. psz[1] = '';
  128. WritePrivateProfileSection(c_tszRename, pszBuf, tszWininit);
  129. lFree(pszBuf);
  130.     }
  131. }
  132. #endif
  133. /*****************************************************************************
  134.  *
  135.  *  Repair_MoveFileEx
  136.  *
  137.  * Try to rename the file from existing.dll to existing.bak,
  138.  * using MoveFileEx or wininit.ini as necessary.
  139.  *
  140.  * Note that we must use the short name because that's all that
  141.  * wininit.ini understands.
  142.  *
  143.  *****************************************************************************/
  144. void PASCAL
  145. Repair_MoveFileEx(LPTSTR ptszSrc)
  146. {
  147.     TCHAR tszDst[MAX_PATH];
  148.     GetShortPathName(ptszSrc, ptszSrc, MAX_PATH);
  149.     lstrcpy(tszDst, ptszSrc);
  150.     lstrcpy(tszDst + lstrlen(tszDst) - 4, c_tszDotBak);
  151.     DeleteFile(tszDst);
  152.     if (MoveFile(ptszSrc, tszDst)) {
  153. /* All done */
  154.     } else if (MoveFileEx(ptszSrc, tszDst, MOVEFILE_DELAY_UNTIL_REBOOT)) {
  155. /* All done */
  156. #ifndef WINNT
  157.     } else if (g_fNT) {
  158. /* I did my best */
  159.     } else { /* Stupid wininit.ini for Windows 95 */
  160. Repair_MoveFileExWininit(tszDst, ptszSrc);
  161. #endif
  162.     }
  163. }
  164. /*****************************************************************************
  165.  *
  166.  *  _Repair_RunSetup
  167.  *
  168.  * Check if there are any hidden DLLs on the desktop.
  169.  *
  170.  * Extract the tiny little "setup" program attached via our resources,
  171.  * run it, delete it, then tell the user they she may need to restart
  172.  * the computer for the full effect to kick in.
  173.  *
  174.  *****************************************************************************/
  175. #pragma BEGIN_CONST_DATA
  176. TCHAR c_tszStarDotDll[] = TEXT("*.DLL");
  177. #pragma END_CONST_DATA
  178. BOOL PASCAL
  179. _Repair_RunSetup(HWND hdlg, REPAIRPATHPROC GetRepairPath)
  180. {
  181.     PIDL pidl;
  182.     if (SUCCEEDED(SHGetSpecialFolderLocation(hdlg, CSIDL_DESKTOPDIRECTORY,
  183.      &pidl))) {
  184. HANDLE h;
  185. TCHAR tszDesktop[MAX_PATH];
  186. TCHAR tszSrc[MAX_PATH];
  187. WIN32_FIND_DATA wfd;
  188. SHGetPathFromIDList(pidl, tszDesktop);
  189. lstrcpy(tszSrc, tszDesktop);
  190. lstrcatnBsA(tszSrc, c_tszStarDotDll);
  191. h = FindFirstFile(tszSrc, &wfd);
  192. if (h != INVALID_HANDLE_VALUE) {
  193.     do {
  194. lstrcpy(tszSrc, tszDesktop);
  195. lstrcatnBsA(tszSrc, wfd.cFileName);
  196. Repair_MoveFileEx(tszSrc);
  197.     } while (FindNextFile(h, &wfd));
  198.     FindClose(h);
  199. }
  200. Ole_Free(pidl);
  201.     }
  202.     WithTempDirectory(Repair_RunSetupCqn, 0);
  203.     return IDS_MAYBEREBOOT;
  204. }
  205. /*****************************************************************************
  206.  *
  207.  *  _Repair_GetFontPath
  208.  *
  209.  *      Obtain the path to the Fonts folder.
  210.  *
  211.  *****************************************************************************/
  212. BOOL PASCAL
  213. _Repair_GetFontPath(HWND hdlg, LPTSTR ptszBuf)
  214. {
  215.     PIDL pidlFonts;
  216.     SHGetSpecialFolderLocation(hdlg, CSIDL_FONTS, &pidlFonts);
  217.     SHGetPathFromIDListA(pidlFonts, ptszBuf);
  218.     Ole_Free(pidlFonts);
  219.     return IDX_FONTFOLDER;
  220. }
  221. /*****************************************************************************
  222.  *
  223.  *  _Repair_GetIEPath
  224.  *
  225.  *      Obtain the path to some IE special folder.
  226.  *
  227.  *      If we can't get it from the registry, then it's just
  228.  *      "%windir%ptszSubdir".
  229.  *
  230.  *****************************************************************************/
  231. void PASCAL
  232. _Repair_GetIEPath(LPTSTR ptszBuf, LPCTSTR ptszKey, LPCTSTR ptszSubdir)
  233. {
  234.     HKEY hk;
  235.     ptszBuf[0] = TEXT('');
  236.     if (RegOpenKeyEx(g_hkLMSMWCV, ptszKey, 0, KEY_QUERY_VALUE, &hk)
  237.         == ERROR_SUCCESS) {
  238.         DWORD cb = cbCtch(MAX_PATH);
  239.         RegQueryValueEx(hk, c_tszDirectory, 0, 0, (LPBYTE)ptszBuf,
  240.                         &cb);
  241.         RegCloseKey(hk);
  242.     }
  243.     if (ptszBuf[0] == TEXT('')) {
  244.         GetWindowsDirectory(ptszBuf, MAX_PATH - lstrlen(ptszSubdir) - 1);
  245.         ptszBuf = TweakUi_TrimTrailingBs(ptszBuf);
  246.         *ptszBuf++ = TEXT('\');
  247.         lstrcpy(ptszBuf, ptszSubdir);
  248.     }
  249. }
  250. /*****************************************************************************
  251.  *
  252.  *  _Repair_GetHistoryPath
  253.  *
  254.  *      Obtain the path to the URL History folder.
  255.  *
  256.  *      If we can't get it from the registry, then it's just
  257.  *      "%windir%History".
  258.  *
  259.  *****************************************************************************/
  260. UINT PASCAL
  261. _Repair_GetHistoryPath(HWND hdlg, LPTSTR ptszBuf)
  262. {
  263.     _Repair_GetIEPath(ptszBuf, c_tszUrlHist, c_tszHistory);
  264.     return IDX_HISTORY;
  265. }
  266. /*****************************************************************************
  267.  *
  268.  *  _Repair_GetCachePath
  269.  *
  270.  *      Obtain the path to the Temporary Internet Files folder.
  271.  *
  272.  *      If we can't get it from the registry, then it's just
  273.  *      "%windir%Temporary Internet Files".
  274.  *
  275.  *****************************************************************************/
  276. UINT PASCAL
  277. _Repair_GetCachePath(HWND hdlg, LPTSTR ptszBuf)
  278. {
  279.     _Repair_GetIEPath(ptszBuf, c_tszIECache, c_tszTempInet);
  280.     return IDX_TEMPINET;
  281. }
  282. /*****************************************************************************
  283.  *
  284.  *  _Repair_RepairJunction
  285.  *
  286.  *      Hack at a junction to make it magic again.
  287.  *
  288.  *****************************************************************************/
  289. UINT PASCAL
  290. _Repair_RepairJunction(HWND hdlg, REPAIRPATHPROC GetRepairPath)
  291. {
  292.     PIDL pidlFonts;
  293.     TCHAR tsz[MAX_PATH];
  294.     UINT ids;
  295.     tsz[0] = TEXT('');
  296.     ids = GetRepairPath(hdlg, tsz);
  297.     if (ids && tsz[0]) {
  298.         /* Ignore error; might already exist */
  299.         CreateDirectory(tsz, 0);
  300.         /* Ignore error; might not have permission to change attributes */
  301.         SetFileAttributes(tsz, FILE_ATTRIBUTE_SYSTEM);
  302.         lstrcpy(TweakUi_TrimTrailingBs(tsz), c_tszBSDesktopIni);
  303.         _Repair_FileFromResource(ids, tsz);
  304.     }
  305.     return IDS_MAYBEREBOOT;
  306. }
  307. /*****************************************************************************
  308.  *
  309.  *  _Repair_RepairIconCache
  310.  *
  311.  *      Rebuild the icon cache.
  312.  *
  313.  *****************************************************************************/
  314. UINT PASCAL
  315. _Repair_RepairIconCache(HWND hdlg, REPAIRPATHPROC GetRepairPath)
  316. {
  317.     Misc_RebuildIcoCache();
  318.     return 0;
  319. }
  320. /*****************************************************************************
  321.  *
  322.  *  _Repair_RepairRegedit
  323.  *
  324.  *      Nuke the saved view goo so Regedit won't be hosed.
  325.  *
  326.  *****************************************************************************/
  327. UINT PASCAL
  328. _Repair_RepairRegedit(HWND hdlg, REPAIRPATHPROC GetRepairPath)
  329. {
  330.     DelPkl(&c_klRegView);
  331.     return 0;
  332. }
  333. /*****************************************************************************
  334.  *
  335.  *  _Repair_RepairAssociations
  336.  *
  337.  *      Rebuild the associations.
  338.  *
  339.  *****************************************************************************/
  340. UINT PASCAL
  341. _Repair_RepairAssociations(HWND hdlg, REPAIRPATHPROC GetRepairPath)
  342. {
  343.     if (MessageBoxId(hdlg, IDS_DESKTOPRESETOK,
  344.                      g_tszName, MB_YESNO + MB_DEFBUTTON2) == IDYES) {
  345.         pcdii->fRunShellInf = 1;
  346.         Common_NeedLogoff(hdlg);
  347.         PropSheet_Apply(GetParent(hdlg));
  348.     }
  349.     return 0;
  350. }
  351. /*****************************************************************************
  352.  *
  353.  *  Repair_IsWin95
  354.  *
  355.  *      Nonzero if we are on Windows 95.
  356.  *
  357.  *****************************************************************************/
  358. BOOL PASCAL
  359. Repair_IsWin95(void)
  360. {
  361.     return !g_fNT;
  362. }
  363. /*****************************************************************************
  364.  *
  365.  *  Repair_IsIE3
  366.  *
  367.  *      Nonzero if we are on Windows 95.
  368.  *
  369.  *****************************************************************************/
  370. BOOL PASCAL
  371. Repair_IsIE3(void)
  372. {
  373.     return (BOOL)g_hkCUSMIE;
  374. }
  375. /*****************************************************************************
  376.  *
  377.  *  REPAIRINFO
  378.  *
  379.  *****************************************************************************/
  380. typedef struct REPAIRINFO {
  381.     BOOL (PASCAL *CanRepair)(void);
  382.     UINT (PASCAL *Repair)(HWND hdlg, REPAIRPATHPROC GetRepairPath);
  383.     REPAIRPATHPROC GetRepairPath;
  384. } REPAIRINFO, *PREPAIRINFO;
  385. /*
  386.  *  Note that this needs to be in sync with the IDS_REPAIR strings.
  387.  */
  388. struct REPAIRINFO c_rgri[] = {
  389.     {   0,
  390.         _Repair_RepairIconCache,
  391.         0,
  392.     },                                  /* Rebuild Icons */
  393.     {   0,
  394.         _Repair_RepairJunction,
  395.         _Repair_GetFontPath,
  396.     },                                  /* Repair Font Folder */
  397.     {   0,
  398.         _Repair_RunSetup,
  399.         0,
  400.     },                                  /* Repair System Files */
  401.     {   0,
  402.         _Repair_RepairRegedit,
  403.         0,
  404.     },                                  /* Rebuild Regedit */
  405.     {   Repair_IsWin95,
  406.         _Repair_RepairAssociations,
  407.         0,
  408.     },                                  /* Repair Associations */
  409.     {   Repair_IsIE3,
  410.         _Repair_RepairJunction,
  411.         _Repair_GetHistoryPath,
  412.     },                                  /* Repair URL History */
  413.     {   Repair_IsIE3,
  414.         _Repair_RepairJunction,
  415.         _Repair_GetCachePath,
  416.     },                                  /* Repair Temporary Internet Files */
  417. };
  418. #pragma END_CONST_DATA
  419. /*****************************************************************************
  420.  *
  421.  *  Repair_GetCurSelIndex
  422.  *
  423.  *      Get the index of the selected item.
  424.  *
  425.  *****************************************************************************/
  426. int PASCAL
  427. Repair_GetCurSelIndex(HWND hdlg)
  428. {
  429.     HWND hwnd = GetDlgItem(hdlg, IDC_REPAIRCOMBO);
  430.     int iItem = ComboBox_GetCurSel(hwnd);
  431.     if (iItem >= 0) {
  432.         return ComboBox_GetItemData(hwnd, iItem);
  433.     } else {
  434.         return iItem;
  435.     }
  436. }
  437. /*****************************************************************************
  438.  *
  439.  *  Repair_OnSelChange
  440.  *
  441.  *      Ooh, the selection changed.
  442.  *
  443.  *****************************************************************************/
  444. void PASCAL
  445. Repair_OnSelChange(HWND hdlg)
  446. {
  447.     HWND hwnd = GetDlgItem(hdlg, IDC_REPAIRCOMBO);
  448.     int dids = Repair_GetCurSelIndex(hdlg);
  449.     if (dids >= 0) {
  450.         TCHAR tsz[1024];
  451.         LoadString(hinstCur, IDS_REPAIRHELP+dids, tsz, cA(tsz));
  452.         SetDlgItemText(hdlg, IDC_REPAIRHELP, tsz);
  453.     }
  454. }
  455. /*****************************************************************************
  456.  *
  457.  *  Repair_OnInitDialog
  458.  *
  459.  * Disable the shell.inf thing on NT, because NT doesn't have one.
  460.  *
  461.  *****************************************************************************/
  462. BOOL PASCAL
  463. Repair_OnInitDialog(HWND hdlg)
  464. {
  465.     HWND hwnd = GetDlgItem(hdlg, IDC_REPAIRCOMBO);
  466.     int dids;
  467.     for (dids = 0; dids < cA(c_rgri); dids++) {
  468.         if (c_rgri[dids].CanRepair == 0 ||
  469.             c_rgri[dids].CanRepair()) {
  470.             TCHAR tsz[MAX_PATH];
  471.             int iItem;
  472.             LoadString(hinstCur, IDS_REPAIR+dids, tsz, cA(tsz));
  473.             iItem = ComboBox_AddString(hwnd, tsz);
  474.             ComboBox_SetItemData(hwnd, iItem, dids);
  475.         }
  476.     }
  477.     ComboBox_SetCurSel(hwnd, 0);
  478.     Repair_OnSelChange(hdlg);
  479.     return 1;
  480. }
  481. /*****************************************************************************
  482.  *
  483.  *  Repair_OnRepairNow
  484.  *
  485.  *      Ooh, go repair something.
  486.  *
  487.  *****************************************************************************/
  488. void PASCAL
  489. Repair_OnRepairNow(HWND hdlg)
  490. {
  491.     HWND hwnd = GetDlgItem(hdlg, IDC_REPAIRCOMBO);
  492.     int dids = Repair_GetCurSelIndex(hdlg);
  493.     if (dids >= 0) {
  494.         UINT ids = c_rgri[dids].Repair(hdlg, c_rgri[dids].GetRepairPath);
  495.         if (ids) {
  496.             MessageBoxId(hdlg, ids, g_tszName, MB_OK);
  497.         }
  498.     }
  499. }
  500. /*****************************************************************************
  501.  *
  502.  *  Repair_OnCommand
  503.  *
  504.  * Ooh, we got a command.
  505.  *
  506.  *****************************************************************************/
  507. BOOL PASCAL
  508. Repair_OnCommand(HWND hdlg, int id, UINT codeNotify)
  509. {
  510.     switch (id) {
  511.     case IDC_REPAIRCOMBO:
  512.         if (codeNotify == CBN_SELCHANGE) {
  513.             Repair_OnSelChange(hdlg);
  514.         }
  515.         break;
  516.     case IDC_REPAIRNOW:
  517.         if (codeNotify == BN_CLICKED) {
  518.             Repair_OnRepairNow(hdlg);
  519.         }
  520.     }
  521. #if 0
  522.     switch (id) {
  523.     case IDC_REBUILDCACHE:
  524. if (codeNotify == BN_CLICKED) {
  525.     Misc_RebuildIcoCache();
  526.     MessageBoxId(hdlg, IDS_ICONSREBUILT, g_tszName, MB_OK);
  527. }
  528. break;
  529.     case IDC_REPAIRFONTFLD:
  530. if (codeNotify == BN_CLICKED) {
  531.     if (_Repair_RepairFontFolder(hdlg)) {
  532. MessageBoxId(hdlg, IDS_MAYBEREBOOT, g_tszName, MB_OK);
  533.     }
  534. }
  535. break;
  536.     case IDC_REPAIRREGEDIT:
  537. if (codeNotify == BN_CLICKED) {
  538.     DelPkl(&c_klRegView);
  539. }
  540. break;
  541.     case IDC_REPAIRASSOC:
  542. if (codeNotify == BN_CLICKED) {
  543.     if (MessageBoxId(hdlg, IDS_DESKTOPRESETOK,
  544.      g_tszName, MB_YESNO + MB_DEFBUTTON2) == IDYES) {
  545. pcdii->fRunShellInf = 1;
  546. Common_NeedLogoff(hdlg);
  547. PropSheet_Apply(GetParent(hdlg));
  548.     }
  549. }
  550. break;
  551.     case IDC_REPAIRDLLS:
  552. if (codeNotify == BN_CLICKED) {
  553.     if (_Repair_RunSetup(hdlg)) {
  554. MessageBoxId(hdlg, IDS_MAYBEREBOOT, g_tszName, MB_OK);
  555.     }
  556. }
  557. break;
  558.     }
  559. #endif
  560.     return 0;
  561. }
  562. #if 0
  563. /*****************************************************************************
  564.  *
  565.  *  Repair_OnNotify
  566.  *
  567.  * Ooh, we got a notification.
  568.  *
  569.  *****************************************************************************/
  570. BOOL PASCAL
  571. Repair_OnNotify(HWND hdlg, NMHDR FAR *pnm)
  572. {
  573.     switch (pnm->code) {
  574.     case PSN_APPLY:
  575. Repair_Apply(hdlg);
  576. break;
  577.     }
  578.     return 0;
  579. }
  580. #endif
  581. /*****************************************************************************
  582.  *
  583.  *  Our window procedure.
  584.  *
  585.  *****************************************************************************/
  586. /*
  587.  * The HANDLE_WM_* macros weren't designed to be used from a dialog
  588.  * proc, so we need to handle the messages manually.  (But carefully.)
  589.  */
  590. BOOL EXPORT
  591. Repair_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  592. {
  593.     switch (wm) {
  594.     case WM_INITDIALOG: return Repair_OnInitDialog(hdlg);
  595.     case WM_COMMAND:
  596. return Repair_OnCommand(hdlg,
  597.        (int)GET_WM_COMMAND_ID(wParam, lParam),
  598.        (UINT)GET_WM_COMMAND_CMD(wParam, lParam));
  599. #if 0
  600.     case WM_NOTIFY:
  601. return Repair_OnNotify(hdlg, (NMHDR FAR *)lParam);
  602. #endif
  603.     case WM_HELP: Common_OnHelp(lParam, &rgdwHelp[0]); break;
  604.     case WM_CONTEXTMENU: Common_OnContextMenu(wParam, &rgdwHelp[0]); break;
  605.     default: return 0; /* Unhandled */
  606.     }
  607.     return 1; /* Handled */
  608. }