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

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * template - Dialog box property sheet for "Templates"
  3.  */
  4. #include "tweakui.h"
  5. #define ctchProgMax 80
  6. #pragma BEGIN_CONST_DATA
  7. const static DWORD CODESEG rgdwHelp[] = {
  8. IDC_TEMPLATETEXT, IDH_TEMPLATE,
  9. IDC_TEMPLATE, IDH_TEMPLATE,
  10. IDC_LVDELETE, IDH_TEMPLATEDEL,
  11. 0, 0,
  12. };
  13. #pragma END_CONST_DATA
  14. typedef struct TI { /* ti - template info */
  15.     BYTE isi; /* Index to state icon */
  16.     HKEY hkRoot; /* Root for locating the key */
  17. /* HKCR or HKCRCLSID */
  18.     TCH tszExt[10]; /* Filename extension (for icon refresh) */
  19.     TCH tszKey[ctchKeyMax + 6]; /* 6 = strlen("\CLSID") */
  20. } TI, *PTI;
  21. #define itiPlvi(plvi) ((UINT)(plvi)->lParam)
  22. #define ptiIti(iti) (&ptdii->pti[iti])
  23. #define ptiPlvi(plvi) ptiIti(itiPlvi(plvi))
  24. typedef struct TDII {
  25.     Declare_Gxa(TI, ti);
  26.     WNDPROC wpTemplate;
  27.     BOOL fRundll; /* Need to run Rundll on Apply */
  28. } TDII, *PTDII;
  29. TDII tdii;
  30. #define ptdii (&tdii)
  31. /*****************************************************************************
  32.  *
  33.  *  ptszStrRChr
  34.  *
  35.  * Get the rightmost occurrence.
  36.  *
  37.  *****************************************************************************/
  38. PTSTR PASCAL
  39. ptszStrRChr(PCTSTR ptsz, TCH tch)
  40. {
  41.     PTSTR ptszRc = 0;
  42.     for (ptsz = ptszStrChr(ptsz, tch); ptsz; ptsz = ptszStrChr(ptsz + 1, tch)) {
  43. ptszRc = (PTSTR)ptsz;
  44.     }
  45.     return ptszRc;
  46. }
  47. /*****************************************************************************
  48.  *
  49.  *  ptszFilenameCqn
  50.  *
  51.  * Get the filename part of a cqn.
  52.  *
  53.  *****************************************************************************/
  54. PTSTR PASCAL
  55. ptszFilenameCqn(PCTSTR cqn)
  56. {
  57.     PTSTR ptsz = ptszStrRChr(cqn, TEXT('\'));
  58.     return ptsz ? ptsz + 1 : (PTSTR)cqn;
  59. }
  60. /*****************************************************************************
  61.  *
  62.  *  Template_NudgeExplorer
  63.  *
  64.  *  Explorer doesn't recognize changes to templates until an application
  65.  *  terminates, so we simply execute Rundll spuriously.  It realizes that
  66.  *  there is nothing to do and exits.  This exit triggers Explorer to
  67.  *  rebuild the filename extension list.
  68.  *
  69.  *****************************************************************************/
  70. #pragma BEGIN_CONST_DATA
  71. ConstString(c_tszRundll, "rundll32");
  72. #pragma END_CONST_DATA
  73. void PASCAL
  74. Template_NudgeExplorer(void)
  75. {
  76.     WinExec(c_tszRundll, SW_HIDE);
  77. }
  78. /*****************************************************************************
  79.  *
  80.  *  Template_SubkeyExists
  81.  *
  82.  *****************************************************************************/
  83. BOOL PASCAL
  84. Template_SubkeyExists(HKEY hk, PCTSTR ptszSubkey)
  85. {
  86.     return GetRegStr(hk, 0, ptszSubkey, 0, 0);
  87. }
  88. /*****************************************************************************
  89.  *
  90.  *  Template_AddTemplateInfo
  91.  *
  92.  *  pti must be the next ti in the array (i.e., Misc_AllocPx)
  93.  *
  94.  *  Returns the icon index, if successful, or -1 on error.
  95.  *
  96.  *****************************************************************************/
  97. int PASCAL
  98. Template_AddTemplateInfo(HWND hwnd, PCTSTR ptszExt, PTI pti, BOOL fCheck)
  99. {
  100.     int iRc;
  101.     SHFILEINFO sfi;
  102.     if (SHGetFileInfo(ptszExt, 0, &sfi, cbX(sfi),
  103. SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES |
  104. SHGFI_SYSICONINDEX | SHGFI_SMALLICON)) {
  105. pti->isi = fCheck + 1;
  106. iRc = LV_AddItem(hwnd, ptdii->cti++, sfi.szTypeName, sfi.iIcon, fCheck);
  107.     } else {
  108. iRc = -1;
  109.     }
  110.     return iRc;
  111. }
  112. /*****************************************************************************
  113.  *
  114.  *  TemplateCallbackInfo
  115.  *
  116.  *  Information handed to a template callback.
  117.  *
  118.  *  hk - The ptszShellNew subkey itself
  119.  *
  120.  *****************************************************************************/
  121. typedef BOOL (PASCAL *TCICALLBACK)(struct TCI *ptci, HKEY hk,
  122.    PCTSTR ptszShellNew);
  123. typedef struct TCI {
  124.     TCICALLBACK pfn;
  125.     PTI pti; /* Template info containing result */
  126.     HWND hwnd; /* Listview window handle */
  127.     PCTSTR ptszExt; /* The .ext being studied */
  128. } TCI, *PTCI;
  129. /*****************************************************************************
  130.  *
  131.  *  Template_CheckShellNew
  132.  *
  133.  * Look for the ShellNew stuff (or ShellNew- if temporarily disabled).
  134.  *
  135.  * Returns boolean success/failure.
  136.  *
  137.  * If ptszExt exists, then we create the key, too.
  138.  *
  139.  *****************************************************************************/
  140. BOOL PASCAL
  141. Template_CheckShellNew(PTCI ptci, HKEY hkBase, PCTSTR ptszShellNew)
  142. {
  143.     HKEY hk;
  144.     BOOL fRc;
  145.     if (_RegOpenKey(hkBase, ptszShellNew, &hk) == 0) {
  146. if (Template_SubkeyExists(hk, c_tszNullFile) ||
  147.     Template_SubkeyExists(hk, c_tszFileName) ||
  148.     Template_SubkeyExists(hk, c_tszCommand) ||
  149.     Template_SubkeyExists(hk, c_tszData)) {
  150.     fRc = ptci->pfn(ptci, hk, ptszShellNew);
  151. } else {
  152.     fRc = 0;
  153. }
  154. RegCloseKey(hk);
  155.     } else {
  156. fRc = 0;
  157.     }
  158.     return fRc;
  159. }
  160. /*****************************************************************************
  161.  *
  162.  *  Template_AddHkeyTemplate
  163.  *
  164.  * We have a candidate location for a ShellNew.
  165.  *
  166.  * There is some weirdness here.  The actual ShellNew can live at
  167.  * a sublevel.  For example, the ".doc" extension contains several
  168.  * ShellNew's:
  169.  *
  170.  * HKCR.doc = WordPad.Document.1
  171.  * HKCR.docWordDocumentShellNew
  172.  * HKCR.docWord.Document.6ShellNew
  173.  * HKCR.docWordPad.Document.1ShellNew
  174.  *
  175.  * Based on the main value (HKCR.doc), we choose to use the template
  176.  * for "Wordpad.Document.1".
  177.  *
  178.  * pti->hkRoot - hkey at which to start (either HKCR or HKCRCLSID)
  179.  * pti->tszKey - subkey to open (.ext or {guid})
  180.  *
  181.  * pti->hkRootpti->tszKey = actual key to open
  182.  *
  183.  * hkBase = the key at hkRootptszKey
  184.  * hk     = the key where ShellNew actually lives
  185.  *
  186.  *****************************************************************************/
  187. BOOL PASCAL
  188. Template_AddHkeyTemplate(PTCI ptci)
  189. {
  190.     HKEY hkBase;
  191.     BOOL fRc;
  192.     PTI pti = ptci->pti;
  193.     if (_RegOpenKey(pti->hkRoot, pti->tszKey, &hkBase) == 0) {
  194. TCH tszProg[ctchProgMax+1];
  195. if (GetRegStr(hkBase, 0, 0, tszProg, cbX(tszProg))) {
  196.     HKEY hk;
  197.     if (_RegOpenKey(hkBase, tszProg, &hk) == 0) {
  198. lstrcatnBsA(pti->tszKey, tszProg);
  199.     } else {
  200. _RegOpenKey(hkBase, 0, &hk); /* hk = AddRef(hkBase) */
  201.     }
  202.     /* Now open the ShellNew subkey or the ShellNew- subkey */
  203.     fRc = fLorFF(Template_CheckShellNew(ptci, hk, c_tszShellNew),
  204.          Template_CheckShellNew(ptci, hk, c_tszShellNewDash));
  205.             RegCloseKey(hk);
  206. } else {
  207.     fRc = 0;
  208. }
  209.     } else {
  210. fRc = 0;
  211.     }
  212.     return fRc;
  213. }
  214. /*****************************************************************************
  215.  *
  216.  *  Template_LocateExtension
  217.  *
  218.  * We have a filename extension (ptci->ptszExt).
  219.  *
  220.  * Get its program id (progid).
  221.  *
  222.  * We look in two places.  If the progid has a registered CLSID
  223.  * (HKCRprogidCLSID), then we look in HKCRCLSID{guid}.
  224.  *
  225.  * If the CLSID fails to locate anything, then we look under
  226.  * HKCR.ext directly.
  227.  *
  228.  *****************************************************************************/
  229. BOOL PASCAL
  230. Template_LocateExtension(PTCI ptci)
  231. {
  232.     BOOL fRc;
  233.     PTI pti = ptci->pti = Misc_AllocPx(&ptdii->gxa);
  234.     if (pti) {
  235. TCH tszProg[ctchProgMax + ctchKeyMax + 6]; /* 6 = strlen(\CLSID) */
  236. lstrcpyn(pti->tszExt, ptci->ptszExt, cA(pti->tszExt));
  237. if (GetRegStr(hkCR, ptci->ptszExt, 0, tszProg, cbCtch(ctchProgMax)) &&
  238.     tszProg[0]) {
  239.     DWORD cb;
  240.     /*
  241.      * Make sure the progid exists, or we end up putting garbage
  242.      * into the listview.
  243.      */
  244.     if (RegQueryValue(hkCR, tszProg, 0, &cb) == 0) {
  245. /*
  246.  *  Is this an OLE class?
  247.  */
  248. lstrcatnBsA(tszProg, c_tszClsid);
  249. if (GetRegStr(hkCR, tszProg, 0,
  250.       pti->tszKey, cbX(pti->tszKey))) {
  251.     pti->hkRoot = pcdii->hkClsid;
  252.     fRc = Template_AddHkeyTemplate(ptci);
  253. } else {
  254.     fRc = 0;
  255. }
  256. /*
  257.  *  If we haven't succeeded yet, then try under the extension
  258.  *  itself.
  259.  */
  260. if (!fRc) {
  261.     pti->hkRoot = hkCR;
  262.     lstrcpyn(pti->tszKey, ptci->ptszExt, cA(pti->tszKey));
  263.     fRc = Template_AddHkeyTemplate(ptci);
  264. }
  265.     } else {
  266. fRc = 0;
  267.     }
  268. } else {
  269.     fRc = 0;
  270. }
  271.     } else {
  272. fRc = 0;
  273.     }
  274.     return fRc;
  275. }
  276. /*****************************************************************************
  277.  *
  278.  *  Template_AddTemplates_AddMe
  279.  *
  280.  * Add any templates that exist.
  281.  *
  282.  * For each filename extension, get its corresponding class.
  283.  * Then ask Template_LocateExtension to do the rest.
  284.  *
  285.  *****************************************************************************/
  286. BOOL PASCAL
  287. Template_AddTemplates_AddMe(PTCI ptci, HKEY hk, PCTSTR ptszShellNew)
  288. {
  289.     return Template_AddTemplateInfo(ptci->hwnd, ptci->ptszExt,
  290.     ptci->pti,
  291.     ptszShellNew == c_tszShellNew) + 1;
  292. }
  293. /*****************************************************************************
  294.  *
  295.  *  Template_AddTemplates
  296.  *
  297.  * Add any templates that exist.
  298.  *
  299.  * For each filename extension, get its corresponding class.
  300.  * Then ask Template_LocateExtension to do the rest.
  301.  *
  302.  *****************************************************************************/
  303. void PASCAL
  304. Template_AddTemplates(HWND hwnd)
  305. {
  306.     int i;
  307.     TCI tci;
  308.     TCH tszExt[10];
  309.     tci.pfn = Template_AddTemplates_AddMe;
  310.     tci.hwnd = hwnd;
  311.     tci.ptszExt = tszExt;
  312.     for (i = 0; ; i++) {
  313. switch (RegEnumKey(HKEY_CLASSES_ROOT, i, tszExt, cbX(tszExt))) {
  314. case ERROR_SUCCESS:
  315.     /*
  316.      *  Don't show ".lnk" in the templates list because it's weird.
  317.      */
  318.     if (tszExt[0] == TEXT('.') && lstrcmpi(tszExt, c_tszDotLnk)) {
  319. Template_LocateExtension(&tci);
  320.     }
  321.     break;
  322. case ERROR_MORE_DATA: /* Can't be a .ext if > 10 */
  323.     break;
  324. default: goto endenum;
  325. }
  326.     }
  327.     endenum:;
  328. }
  329. /*****************************************************************************
  330.  *
  331.  *  File template callback info
  332.  *
  333.  *****************************************************************************/
  334. typedef struct FTCI {
  335.     TCI tci;
  336.     PCTSTR ptszSrc;
  337.     PCTSTR ptszDst;
  338.     PCTSTR ptszLastBS;
  339.     PCTSTR ptszShellNew;
  340. } FTCI, *PFTCI;
  341. /*****************************************************************************
  342.  *
  343.  *  Template_CopyFile
  344.  *
  345.  * Copy a file with the hourglass.
  346.  *
  347.  *****************************************************************************/
  348. BOOL PASCAL
  349. Template_CopyFile(PFTCI pftci)
  350. {
  351.     HCURSOR hcurPrev;
  352.     BOOL fRc;
  353.     hcurPrev = SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_WAIT)));
  354.     fRc = CopyFile(pftci->ptszSrc, pftci->ptszDst, 0);
  355.     SetCursor(hcurPrev);
  356.     return fRc;
  357. }
  358. /*****************************************************************************
  359.  *
  360.  *  Template_AddFileTemplate_CheckMe
  361.  *
  362.  * Make sure the key isn't a Command key.
  363.  *
  364.  *****************************************************************************/
  365. BOOL PASCAL
  366. Template_AddFileTemplate_CheckMe(PTCI ptci, HKEY hk, PCTSTR ptszShellNew)
  367. {
  368.     PFTCI pftci = (PFTCI)ptci;
  369.     pftci->ptszShellNew = ptszShellNew;
  370.     if (Template_SubkeyExists(hk, c_tszCommand)) {
  371. ptci->ptszExt = 0;
  372.     }
  373.     return 1;
  374. }
  375. /*****************************************************************************
  376.  *
  377.  *  Template_IsTemplatable
  378.  *
  379.  * Determine whether there is an application that can handle this
  380.  * extension.
  381.  *
  382.  * The incoming hk is the HKEY_CLASSES_ROOT<extension> key.
  383.  *
  384.  * BUGBUG -- should also fail if the app is "%1", meaning that
  385.  * the document is self-running.
  386.  *
  387.  *****************************************************************************/
  388. /* BUGBUG -- FindExecutable? */
  389. /* BUGBUG -- some bozos leave c_tszShell blank */
  390. BOOL PASCAL
  391. Template_IsTemplatable(HKEY hk)
  392. {
  393.     LONG cb;
  394.     TCH tsz[MAX_PATH];
  395.     cb = cbX(tsz);
  396.     if (RegQueryValue(hk, 0, tsz, &cb) == 0) {
  397. HKEY hkClass;
  398. if (_RegOpenKey(HKEY_CLASSES_ROOT, tsz, &hkClass) == 0) {
  399.     BOOL fRc;
  400.     cb = cbX(tsz);
  401.     fRc = RegQueryValue(hkClass, c_tszShell, 0, &cb) == 0;
  402.     RegCloseKey(hkClass);
  403.     return fRc;
  404. } else {
  405.     return 0;
  406. }
  407.     } else {
  408. return 0;
  409.     }
  410. }
  411. /*****************************************************************************
  412.  *
  413.  *  Template_ReplaceTemplate
  414.  *
  415.  * Replace the current template with the new one.
  416.  *
  417.  *****************************************************************************/
  418. UINT PASCAL
  419. Template_ReplaceTemplate(PFTCI pftci)
  420. {
  421. #define ptci (&pftci->tci)
  422.     UINT id;
  423.     if (ptci->ptszExt) {
  424. if (MessageBoxId(GetParent(ptci->hwnd), IDS_CONFIRMNEWTEMPLATE,
  425.  pftci->ptszSrc,
  426.  MB_YESNO | MB_DEFBUTTON2 | MB_SETFOREGROUND)
  427. == IDYES) {
  428.     HKEY hk;
  429.     lstrcatnBsA(ptci->pti->tszKey, pftci->ptszShellNew);
  430.     if (_RegOpenKey(ptci->pti->hkRoot, ptci->pti->tszKey, &hk) == 0) {
  431. if (Template_CopyFile(pftci)) {
  432.     RegDeleteValue(hk, c_tszNullFile);
  433.     RegDeleteValue(hk, c_tszData);
  434.     RegSetValuePtsz(hk, c_tszFileName, pftci->ptszLastBS+1);
  435.     id = 0;
  436. } else {
  437.     id = IDS_COPYFAIL;
  438. }
  439. RegCloseKey(hk);
  440.     } else {
  441. id = IDS_REGFAIL;
  442.     }
  443. } else {
  444.     id = 0;
  445. }
  446.     } else {
  447. id = IDS_CANNOTTEMPLATE;
  448.     }
  449.     return id;
  450. }
  451. #undef ptci
  452. /*****************************************************************************
  453.  *
  454.  *  Template_AddFileTemplate
  455.  *
  456.  * Add the file as a new template type.
  457.  *
  458.  *****************************************************************************/
  459. UINT PASCAL
  460. Template_AddFileTemplate(HWND hwnd, PCTSTR ptszSrc)
  461. {
  462. #define pftci (&ftci)
  463.     UINT id;
  464.     FTCI ftci;
  465.     pftci->tci.pfn = Template_AddFileTemplate_CheckMe;
  466.     pftci->tci.hwnd = hwnd;
  467.     pftci->ptszSrc = ptszSrc;
  468.     pftci->ptszLastBS = ptszFilenameCqn(ptszSrc) - 1; /* -> filename.ext */
  469.     if (pftci->ptszLastBS) {
  470. pftci->tci.ptszExt = ptszStrRChr(pftci->ptszLastBS, '.'); /* -> .ext */
  471. if (pftci->tci.ptszExt) {
  472.     HKEY hk;
  473.     if (_RegOpenKey(hkCR, pftci->tci.ptszExt, &hk) == 0) {
  474. if (Template_IsTemplatable(hk)) {
  475.     PTI pti;
  476.     TCH tszDst[MAX_PATH];
  477.     pftci->ptszDst = tszDst;
  478.     SHGetPathFromIDList(pcdii->pidlTemplates, tszDst);
  479.     lstrcatnBsA(tszDst, pftci->ptszLastBS+1);
  480.     /* Snoop at the next pti to ensure we can get it later */
  481.     pti = Misc_AllocPx(&ptdii->gxa);
  482.     if (pti) {
  483. if (Template_LocateExtension(&pftci->tci)) {
  484.     id = Template_ReplaceTemplate(pftci);
  485. } else {
  486.     if (Template_CopyFile(pftci)) {
  487. HKEY hk2;
  488. if (RegCreateKey(hk, c_tszShellNew, &hk2) == 0) {
  489.     RegSetValuePtsz(hk2, c_tszFileName, pftci->ptszLastBS+1);
  490.     RegCloseKey(hk2);
  491.     Misc_LV_SetCurSel(hwnd,
  492.     Template_AddTemplateInfo(hwnd,
  493. pftci->tci.ptszExt, pti, 1));
  494.     Template_NudgeExplorer();
  495.     id = 0; /* No problemo */
  496. } else {
  497.     id = IDS_REGFAIL;
  498. }
  499.     } else {
  500. id = IDS_COPYFAIL;
  501.     }
  502. }
  503.     } else {
  504. id = 0; /* out of memory! */
  505.     }
  506. } else {
  507.     id = IDS_BADEXT;
  508. }
  509. RegCloseKey(hk);
  510.     } else {
  511. id = IDS_BADEXT;
  512.     }
  513. } else {
  514.     id = IDS_BADEXT;
  515. }
  516.     } else {
  517. id = 0; /* This can't happen! */
  518.     }
  519.     return id;
  520. }
  521. /*****************************************************************************
  522.  *
  523.  *  Tools_Template_OnDropFiles
  524.  *
  525.  * Put the file into the template edit control.
  526.  *
  527.  *****************************************************************************/
  528. void PASCAL
  529. Tools_Template_OnDropFiles(HWND hwnd, HDROP hdrop)
  530. {
  531.     if (DragQueryFile(hdrop, (UINT)-1, 0, 0) == 1) {
  532. UINT id;
  533. TCH tszSrc[MAX_PATH];
  534. DragQueryFile(hdrop, 0, tszSrc, cA(tszSrc));
  535. id = Template_AddFileTemplate(hwnd, tszSrc);
  536. if (id) {
  537.     MessageBoxId(GetParent(hwnd), id, tszSrc, MB_OK | MB_SETFOREGROUND);
  538. }
  539.     } else {
  540. MessageBoxId(GetParent(hwnd), IDS_TOOMANY, g_tszName,
  541.      MB_OK | MB_SETFOREGROUND);
  542.     }
  543.     DragFinish(hdrop);
  544. }
  545. /*****************************************************************************
  546.  *
  547.  *  Tools_Template_WndProc
  548.  *
  549.  * Subclass procedure so we can handle drag-drop to the template
  550.  * edit control.
  551.  *
  552.  *****************************************************************************/
  553. LRESULT EXPORT
  554. Tools_Template_WndProc(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
  555. {
  556.     switch (wm) {
  557.     case WM_DROPFILES:
  558. Tools_Template_OnDropFiles(hwnd, (HDROP)wParam);
  559. return 0;
  560.     }
  561.     return CallWindowProc(ptdii->wpTemplate, hwnd, wm, wParam, lParam);
  562. }
  563. /*****************************************************************************
  564.  *
  565.  *  Template_GetIcon
  566.  *
  567.  * Produce the icon associated with an item.  This is called when
  568.  * we need to rebuild the icon list after the icon cache has been
  569.  * purged.
  570.  *
  571.  *****************************************************************************/
  572. int PASCAL
  573. Template_GetIcon(LPARAM iti)
  574. {
  575.     SHFILEINFO sfi;
  576.     PTI pti = ptiIti(iti);
  577.     sfi.iIcon = 0;
  578. OutputDebugString(pti->tszExt);
  579.     SHGetFileInfo(pti->tszExt, 0, &sfi, cbX(sfi),
  580. SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  581.     return sfi.iIcon;
  582. }
  583. /*****************************************************************************
  584.  *
  585.  *  Template_OnInitDialog
  586.  *
  587.  *  Turn the "drop a file here" gizmo into a valid drop target.
  588.  *
  589.  *****************************************************************************/
  590. BOOL PASCAL
  591. Template_OnInitDialog(HWND hwnd)
  592. {
  593.     ptdii->wpTemplate = SubclassWindow(hwnd, Tools_Template_WndProc);
  594.     DragAcceptFiles(hwnd, 1);
  595.     if (Misc_InitPgxa(&ptdii->gxa, cbX(TI))) {
  596. Template_AddTemplates(hwnd);
  597.     }
  598.     return 1;
  599. }
  600. /*****************************************************************************
  601.  *
  602.  *  Template_OnDelete
  603.  *
  604.  * Really nuke it.  The interaction between this and adding a new
  605.  * template is sufficiently weird that I don't want to try to do
  606.  * delayed-action.
  607.  *
  608.  *****************************************************************************/
  609. void PASCAL
  610. Template_OnDelete(HWND hwnd, int iItem)
  611. {
  612.     LV_ITEM lvi;
  613.     HKEY hk;
  614.     PTI pti;
  615.     TCH tszDesc[MAX_PATH];
  616.     lvi.pszText = tszDesc;
  617.     lvi.cchTextMax = cA(tszDesc);
  618.     Misc_LV_GetItemInfo(hwnd, &lvi, iItem, LVIF_PARAM | LVIF_TEXT);
  619.     pti = ptiPlvi(&lvi);
  620.     if (MessageBoxId(GetParent(hwnd), IDS_TEMPLATEDELETEWARN,
  621.     lvi.pszText, MB_YESNO | MB_DEFBUTTON2) == IDYES) {
  622. if (_RegOpenKey(pti->hkRoot, pti->tszKey, &hk) == 0) {
  623.     RegDeleteTree(hk, c_tszShellNewDash);
  624.     RegDeleteTree(hk, c_tszShellNew);
  625.     ListView_DeleteItem(hwnd, iItem);
  626.     Misc_LV_EnsureSel(hwnd, iItem);
  627.     Common_SetDirty(GetParent(hwnd));
  628.     RegCloseKey(hk);
  629. }
  630.     }
  631. }
  632. /*****************************************************************************
  633.  *
  634.  *  Template_OnSelChange
  635.  *
  636.  * Disable the Remove button if we can't remove the thing.
  637.  *
  638.  *****************************************************************************/
  639. void PASCAL
  640. Template_OnSelChange(HWND hwnd, int iItem)
  641. {
  642.     PTI pti = ptiIti(Misc_LV_GetParam(hwnd, iItem));
  643.     HKEY hk;
  644.     BOOL fEnable;
  645.     if (_RegOpenKey(pti->hkRoot, pti->tszKey, &hk) == 0) {
  646. if (GetRegStr(hk, pti->isi == isiUnchecked ?
  647. c_tszShellNewDash : c_tszShellNew, c_tszCommand, 0, 0)) {
  648.     fEnable = 0;
  649. } else {
  650.     fEnable = 1;
  651. }
  652. RegCloseKey(hk);
  653.     } else {
  654. fEnable = 0;
  655.     }
  656.     EnableWindow(GetDlgItem(GetParent(hwnd), IDC_LVDELETE), fEnable);
  657. }
  658. /*****************************************************************************
  659.  *
  660.  *  Template_OnApply
  661.  *
  662.  *****************************************************************************/
  663. void PASCAL
  664. Template_OnApply(HWND hdlg)
  665. {
  666.     HWND hwnd = GetDlgItem(hdlg, IDC_TEMPLATE);
  667.     int cItems = ListView_GetItemCount(hwnd);
  668.     BOOL fDirty;
  669.     LV_ITEM lvi;
  670.     fDirty = 0;
  671.     for (lvi.iItem = 0; lvi.iItem < cItems; lvi.iItem++) {
  672. PTI pti;
  673. lvi.stateMask = LVIS_STATEIMAGEMASK;
  674. Misc_LV_GetItemInfo(hwnd, &lvi, lvi.iItem, LVIF_PARAM | LVIF_STATE);
  675. pti = ptiPlvi(&lvi);
  676. if (pti->isi != isiPlvi(&lvi)) {
  677.     PCTSTR ptszFrom, ptszTo;
  678.     if (pti->isi == isiUnchecked) {
  679. ptszFrom = c_tszShellNewDash;
  680. ptszTo   = c_tszShellNew;
  681.     } else {
  682. ptszFrom = c_tszShellNew;
  683. ptszTo   = c_tszShellNewDash;
  684.     }
  685.             if (Misc_RenameReg(pti->hkRoot, pti->tszKey, ptszFrom, ptszTo)) {
  686.                 pti->isi = isiPlvi(&lvi);
  687.     }
  688.     fDirty = 1;
  689. }
  690.     }
  691.     if (fDirty) {
  692. Template_NudgeExplorer();
  693.     }
  694. }
  695. /*****************************************************************************
  696.  *
  697.  *  Template_OnDestroy
  698.  *
  699.  * Free the memory we allocated.
  700.  *
  701.  *****************************************************************************/
  702. void PASCAL
  703. Template_OnDestroy(HWND hdlg)
  704. {
  705.     Misc_FreePgxa(&ptdii->gxa);
  706. }
  707. /*****************************************************************************
  708.  *
  709.  *  Oh yeah, we need this too.
  710.  *
  711.  *****************************************************************************/
  712. #pragma BEGIN_CONST_DATA
  713. LVV lvvTemplate = {
  714.     0, /* Template_OnCommand */
  715.     0, /* Template_OnInitContextMenu */
  716.     0, /* Template_Dirtify */
  717.     Template_GetIcon,
  718.     Template_OnInitDialog,
  719.     Template_OnApply,
  720.     Template_OnDestroy,
  721.     Template_OnSelChange,
  722.     3,
  723.     rgdwHelp,
  724.     0,                          /* Double-click action */
  725.     lvvflIcons |                /* We need icons */
  726.     lvvflCanCheck |             /* And check boxes */
  727.     lvvflCanDelete,             /* and you can delete them too */
  728.     {
  729. { IDC_LVDELETE, Template_OnDelete },
  730. { 0, 0 },
  731.     },
  732. };
  733. #pragma END_CONST_DATA
  734. /*****************************************************************************
  735.  *
  736.  *  Our window procedure.
  737.  *
  738.  *****************************************************************************/
  739. BOOL EXPORT
  740. Template_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  741. {
  742.     return LV_DlgProc(&lvvTemplate, hdlg, wm, wParam, lParam);
  743. }