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

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * control - Dialog box property sheet for "control panel"
  3.  */
  4. #include "tweakui.h"
  5. /*
  6.  * cchFriendlyMax is used to hold control panel file descriptions.
  7.  */
  8. #define cchFriendlyMax 256
  9. typedef struct CPL {            /* control panel */
  10.     TCHAR tszFile[MAX_PATH];    /* File name */
  11. } CPL, *PCPL;
  12. #define icplPlvi(plvi) ((UINT)(plvi)->lParam)
  13. #define pcplIcpl(icpl) (&pcpii->pcpl[icpl])
  14. #define pcplPlvi(plvi) pcplIcpl(icplPlvi(plvi))
  15. typedef struct CPII {
  16.     Declare_Gxa(CPL, cpl);
  17. } CPII, *PCPII;
  18. CPII cpii;
  19. #define pcpii (&cpii)
  20. TCHAR g_tszBoring[64];
  21. #pragma BEGIN_CONST_DATA
  22. const static DWORD CODESEG rgdwHelp[] = {
  23.         0,                      0,
  24. };
  25. /*****************************************************************************
  26.  *
  27.  *  Control_VerQueryDescription
  28.  *
  29.  *  Suck out the file description if we have one.
  30.  *
  31.  *****************************************************************************/
  32. BOOL PASCAL
  33. Control_VerQueryDescription(LPVOID pvData, UINT uiLang, UINT uiCharSet,
  34.                             LPTSTR ptszBuf, UINT ctch)
  35. {
  36.     TCHAR tsz[128];
  37.     LPWSTR pwsz;
  38.     BOOL fRc;
  39.     UINT cb;
  40.     wsprintf(tsz, TEXT("\StringFileInfo\%04X%04X\")
  41.                   TEXT("FileDescription"), uiLang, uiCharSet);
  42.     fRc = VerQueryValue(pvData, tsz, (LPVOID)&pwsz, &cb);
  43.     if (fRc && cb > 0) {
  44. #ifdef UNICODE
  45.         lstrcpyn(ptszBuf, pwsz, ctch);
  46. #else
  47.         WideCharToMultiByte(CP_ACP, 0, pwsz, cb / cbX(WCHAR),
  48.                             ptszBuf, MAX_PATH, NULL, NULL);
  49.         lstrcpyn(ptszBuf, (LPSTR)pwsz, ctch);
  50. #endif
  51.     }
  52.     return fRc;
  53. }
  54. /*****************************************************************************
  55.  *
  56.  *  Control_GetFileDescription
  57.  *
  58.  *  Suck out the file description if we have one.
  59.  *
  60.  *****************************************************************************/
  61. void PASCAL
  62. Control_GetFileDescription(LPTSTR ptszFile, LPTSTR ptszBuf, UINT ctch)
  63. {
  64.     DWORD dwHandle;
  65.     UINT cb;
  66.     /*
  67.      *  Assume it doesn't work.
  68.      */
  69.     ptszBuf[0] = TEXT('');
  70.     cb = GetFileVersionInfoSize(ptszFile, &dwHandle);
  71.     if (cb) {
  72.         LPVOID pvData = lAlloc(cb);
  73.         if (pvData) {
  74.             LPWORD rgwTrans;
  75.             UINT uiSize;
  76.             if (GetFileVersionInfo(ptszFile, dwHandle, cb, pvData) &&
  77.                 VerQueryValue(pvData, TEXT("\VarFileInfo\Translation"),
  78.                               (LPVOID)&rgwTrans, &uiSize)) {
  79.                 if (Control_VerQueryDescription(pvData,
  80.                                                 rgwTrans[0], rgwTrans[1],
  81.                                                 ptszBuf, ctch) ||
  82.                     /*
  83.                      *  Lots of morons forget to set the language properly,
  84.                      *  so we will try English/USA regardless.  And if that
  85.                      *  doesn't work, try English/NULL because some people
  86.                      *  do that too.
  87.                      */
  88.                     Control_VerQueryDescription(pvData,
  89.                                                 0x0409, 0x040E,
  90.                                                 ptszBuf, ctch) ||
  91.                     Control_VerQueryDescription(pvData,
  92.                                                 0x0409, 0x0000,
  93.                                                 ptszBuf, ctch)) {
  94.                 }
  95.             }
  96.             lFree(pvData);
  97.         }
  98.     }
  99. }
  100. /*****************************************************************************
  101.  *
  102.  *  Control_GetShowState
  103.  *
  104.  *  Determine whether a *.CPL file is currently shown in the
  105.  *  Control Panel.
  106.  *
  107.  *****************************************************************************/
  108. BOOL PASCAL
  109. Control_GetShowState(LPCTSTR ptszName)
  110. {
  111.     TCHAR tsz[10];
  112.     GetPrivateProfileString(c_tszDontLoad, ptszName,
  113.                             c_tszNil, tsz, cA(tsz), c_tszControlIni);
  114.     return tsz[0] ? FALSE : TRUE;
  115. }
  116. /*****************************************************************************
  117.  *
  118.  *  Control_SetShowState
  119.  *
  120.  *  Set the registry/INI flag that tells us to hide/show the *.CPL file.
  121.  *
  122.  *****************************************************************************/
  123. void PASCAL
  124. Control_SetShowState(LPCTSTR ptszName, BOOL fShow)
  125. {
  126.     // BUGBUG -- string.c
  127.     WritePrivateProfileString(c_tszDontLoad, ptszName,
  128.                               fShow ? NULL : c_tszNo, c_tszControlIni);
  129. }
  130. /*****************************************************************************
  131.  *
  132.  *  Control_AddCpl
  133.  *
  134.  *  Add a single *.CPL to the list.
  135.  *
  136.  *  The display name is the CPL filename, followed by an optional
  137.  *  parenthesized version description string.  For control panels
  138.  *  that ship with Windows 95 whose version strings suck, we substitute
  139.  *  our own.
  140.  *
  141.  *****************************************************************************/
  142. #pragma BEGIN_CONST_DATA
  143. LPCTSTR c_rgpszCpl[] = {
  144.     c_tszAppWizCpl,
  145.     c_tszDeskCpl,
  146.     c_tszIntlCpl,
  147.     c_tszMainCpl,
  148.     c_tszTimeDateCpl,
  149. };
  150. int PASCAL
  151. Control_AddCpl(HWND hwnd, LPTSTR ptszName)
  152. {
  153.     PCPL pcpl = Misc_AllocPx(&pcpii->gxa);
  154.     TCHAR tszDesc[MAX_PATH];
  155.     TCHAR tszFull[MAX_PATH + 3 + MAX_PATH]; /* 3 = " - " */
  156.     lstrcpy(pcpl->tszFile, ptszFilenameCqn(ptszName));
  157.     CharLower(pcpl->tszFile);
  158.     Control_GetFileDescription(ptszName, tszDesc, MAX_PATH);
  159.     /*
  160.      *  Now clean up various weird cases.
  161.      */
  162.     if (lstrcmpi(tszDesc, g_tszBoring) == 0) {
  163.         int i;
  164.         for (i = 0; i < cA(c_rgpszCpl); i++) {
  165.             if (lstrcmpi(pcpl->tszFile, c_rgpszCpl[i]) == 0) {
  166.                 LoadString(hinstCur, IDS_CPL_ADDRM + i, tszDesc, cA(tszDesc));
  167.                 break;
  168.             }
  169.         }
  170.     }
  171.     wsprintf(tszFull, TEXT("%s - %s"), pcpl->tszFile, tszDesc);
  172.     return LV_AddItem(hwnd, pcpii->ccpl++, tszFull, -1,
  173.                       Control_GetShowState(pcpl->tszFile));
  174. }
  175. /*****************************************************************************
  176.  *
  177.  *  Control_InitControls2
  178.  *
  179.  *  Enumerate all the special DLLs in the MMCPL section and add them
  180.  *  to the list.  Note that the buffer sizes are exactly the same sizes
  181.  *  that SHELL32 uses, so we won't miss anything that the shell itself
  182.  *  doesn't.
  183.  *
  184.  *****************************************************************************/
  185. void PASCAL
  186. Control_InitControls2(HWND hwnd)
  187. {
  188.     LPTSTR ptsz;
  189.     TCHAR tszKeys[512];
  190.     TCHAR tszName[64];
  191.     /* BUGBUG -- add string */
  192.     GetPrivateProfileString(TEXT("MMCPL"), NULL, c_tszNil,
  193.                             tszKeys, cA(tszKeys), c_tszControlIni);
  194.     for (ptsz = tszKeys; ptsz[0]; ptsz += lstrlen(ptsz) + 1) {
  195.         /*
  196.          *  Some legacy keys to ignore:
  197.          *
  198.          *  NumApps=        <number of applets>
  199.          *  H=              <height>
  200.          *  W=              <width>
  201.          *  X=              <x coordinate>
  202.          *  Y=              <y coordinate>
  203.          */
  204.         /* BUGBUG -- Add string */
  205.         if (lstrcmpi(ptsz, TEXT("NumApps")) == 0) {
  206.             continue;
  207.         }
  208.         if (ptsz[1] == TEXT('')) {
  209.             switch (ptsz[0]) {
  210.             case 'H':
  211.             case 'W':
  212.             case 'X':
  213.             case 'Y': continue;
  214.             }
  215.         }
  216.         /*
  217.          *  End of wacky legacy keys.
  218.          */
  219.         GetPrivateProfileString(TEXT("MMCPL"), ptsz, c_tszNil,
  220.                                 tszName, cA(tszName), c_tszControlIni);
  221.         Control_AddCpl(hwnd, tszName);
  222.     }
  223. }
  224. /*****************************************************************************
  225.  *
  226.  *  Control_InitControls3
  227.  *
  228.  *  Enumerate all the *.CPL files in the System folder
  229.  *  and add them to the list.
  230.  *
  231.  *****************************************************************************/
  232. void PASCAL
  233. Control_InitControls3(HWND hwnd)
  234. {
  235.     WIN32_FIND_DATA wfd;
  236.     HANDLE h;
  237.     TCHAR tszSystemDir[MAX_PATH];
  238.     TCHAR tszPrevDir[MAX_PATH];
  239.     GetCurrentDirectory(cA(tszPrevDir), tszPrevDir); /* For restore */
  240.     GetSystemDirectory(tszSystemDir, MAX_PATH);
  241.     if (SetCurrentDirectory(tszSystemDir)) {
  242.         h = FindFirstFile(c_tszStarCpl, &wfd);
  243.         if (h != INVALID_HANDLE_VALUE) {
  244.             do {
  245.                 Control_AddCpl(hwnd, wfd.cFileName);
  246.             } while (FindNextFile(h, &wfd)) ;
  247.             FindClose(h);
  248.         }
  249.         SetCurrentDirectory(tszPrevDir);
  250.     }
  251. }
  252. /*****************************************************************************
  253.  *
  254.  *  Control_OnInitDialog
  255.  *
  256.  *  Enumerate all the *.CPL files and add them to the list.
  257.  *
  258.  *****************************************************************************/
  259. BOOL PASCAL
  260. Control_OnInitDialog(HWND hwnd)
  261. {
  262.     HCURSOR hcurPrev = GetCursor();
  263.     SetCursor(LoadCursor(0, IDC_WAIT));
  264.     ZeroMemory(pcpii, cbX(*pcpii));
  265.     LoadString(hinstCur, IDS_CPL_BORING, g_tszBoring, cA(g_tszBoring));
  266.     if (Misc_InitPgxa(&pcpii->gxa, cbX(CPL))) {
  267.         Control_InitControls2(hwnd);
  268.         Control_InitControls3(hwnd);
  269.     }
  270.     SetCursor(hcurPrev);
  271.     return 1;
  272. }
  273. /*****************************************************************************
  274.  *
  275.  *  Control_OnDestroy
  276.  *
  277.  *  Free the memory we allocated.
  278.  *
  279.  *****************************************************************************/
  280. BOOL PASCAL
  281. Control_OnDestroy(HWND hdlg)
  282. {
  283.     Misc_FreePgxa(&pcpii->gxa);
  284.     return 1;
  285. }
  286. /*****************************************************************************
  287.  *
  288.  *  Control_LV_Dirtify
  289.  *
  290.  *      Mark this item as having been changed during the property sheet
  291.  * page's lifetime.
  292.  *
  293.  *****************************************************************************/
  294. void PASCAL
  295. Control_LV_Dirtify(LPARAM icpl)
  296. {
  297. //    pcpii->pcpl[icpl].cplfl |= cplflEdited;
  298. }
  299. /*****************************************************************************
  300.  *
  301.  *  Control_OnApply
  302.  *
  303.  *      Write the changes out.
  304.  *
  305.  *****************************************************************************/
  306. void PASCAL
  307. Control_OnApply(HWND hdlg)
  308. {
  309.     HWND hwnd = GetDlgItem(hdlg, IDC_ICONLV);
  310.     int cItems = ListView_GetItemCount(hwnd);
  311.     BOOL fChanged = 0;
  312.     LV_ITEM lvi;
  313.     for (lvi.iItem = 0; lvi.iItem < cItems; lvi.iItem++) {
  314.         PCPL pcpl;
  315.         lvi.stateMask = LVIS_STATEIMAGEMASK;
  316.         Misc_LV_GetItemInfo(hwnd, &lvi, lvi.iItem, LVIF_PARAM | LVIF_STATE);
  317.         pcpl = pcplPlvi(&lvi);
  318.         if (Control_GetShowState(pcpl->tszFile) != LV_IsChecked(&lvi)) {
  319.             fChanged = 1;
  320.             Control_SetShowState(pcpl->tszFile, LV_IsChecked(&lvi));
  321.         }
  322.     }
  323.     if (fChanged) {
  324.         PIDL pidlCpl;
  325.         if (SHGetSpecialFolderLocation(hdlg, CSIDL_CONTROLS, &pidlCpl)) {
  326.             SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidlCpl, 0L);
  327.             Ole_Free(pidlCpl);
  328.         }
  329.     }
  330. }
  331. /*****************************************************************************
  332.  *
  333.  *  Oh yeah, we need this too.
  334.  *
  335.  *****************************************************************************/
  336. #pragma BEGIN_CONST_DATA
  337. LVV lvvControl = {
  338.     0,                          /* Control_OnCommand */
  339.     0,                          /* Control_LV_OnInitContextMenu */
  340.     Control_LV_Dirtify,
  341.     0,                          /* Control_LV_GetIcon */
  342.     Control_OnInitDialog,
  343.     Control_OnApply,
  344.     Control_OnDestroy,
  345.     0,                          /* Control_OnSelChange */
  346.     7,                          /* iMenu */
  347.     rgdwHelp,
  348.     0, /* Double-click action */
  349.     lvvflCanCheck,              /* We need check boxes */
  350.     {
  351. { 0, 0 },
  352.     }
  353. };
  354. #pragma END_CONST_DATA
  355. /*****************************************************************************
  356.  *
  357.  *  Our window procedure.
  358.  *
  359.  *****************************************************************************/
  360. BOOL EXPORT
  361. Control_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  362. {
  363.     return LV_DlgProc(&lvvControl, hdlg, wm, wParam, lParam);
  364. }