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

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  *  Microsoft Confidential
  3.  *  Copyright (C) Microsoft Corporation 1991
  4.  *  All Rights Reserved.
  5.  *
  6.  *
  7.  *  PIFLIB.C
  8.  *  User interface routines for PIFMGR.DLL
  9.  *
  10.  *  History:
  11.  *  Created 31-Jul-1992 3:30pm by Jeff Parsons
  12.  */
  13. #include "shellprv.h"
  14. #pragma hdrstop
  15. #ifdef WIN32
  16. #define hModule GetModuleHandle(TEXT("SHELL32.DLL"))
  17. #endif
  18. #define LIB_SIG                 0x504A
  19. #define LIB_DEFER               LOADPROPLIB_DEFER
  20. typedef struct LIBLINK {        /* ll */
  21.     struct  LIBLINK *pllNext;   //
  22.     struct  LIBLINK *pllPrev;   //
  23.     int     iSig;               // liblink signature
  24.     int     flLib;              // proplink flags (LIB_*)
  25.     HINSTANCE hDLL;             // if NULL, then load has been deferred
  26.     TCHAR    achDLL[80];        // name of DLL
  27. } LIBLINK;
  28. typedef LIBLINK *PLIBLINK;
  29. #define SHEET_SIG               0x504A
  30. typedef struct SHEETLINK {      /* sl */
  31.     struct  SHEETLINK *pslNext;
  32.     struct  SHEETLINK *pslPrev;
  33.     int     iSig;
  34.     int     iType;
  35.     PROPSHEETPAGE psi;
  36. } SHEETLINK;
  37. typedef SHEETLINK *PSHEETLINK;
  38. UINT    cEdits;                 // number of edit sessions in progress
  39. PLIBLINK pllHead;               // pointer to first lib link
  40. HANDLE   offHighestLibLink;      // highest offset of a lib link thus far recorded
  41. PSHEETLINK pslHead;             // pointer to first sheet link
  42. UINT    cSheetLinks;            // number of sheet links
  43. HANDLE  offHighestSheetLink;    // highest offset of a sheet link thus far recorded
  44. struct {                        // built-in property sheet info
  45.     LPCTSTR  lpTemplateName;
  46.     DLGPROC lpfnDlgProc;
  47.     int     iType;
  48. } const aPSInfo[] = {
  49.     { MAKEINTRESOURCE(IDD_PROGRAM), DlgPrgProc, SHEETTYPE_SIMPLE},
  50.     { MAKEINTRESOURCE(IDD_FONT),    DlgFntProc, SHEETTYPE_SIMPLE},
  51.     { MAKEINTRESOURCE(IDD_MEMORY),  DlgMemProc, SHEETTYPE_SIMPLE},
  52.     { MAKEINTRESOURCE(IDD_SCREEN),  DlgVidProc, SHEETTYPE_SIMPLE},
  53.     { MAKEINTRESOURCE(IDD_MISC),    DlgMscProc, SHEETTYPE_SIMPLE},
  54. };
  55. /** LoadPropertyLib - load new property library
  56.  *
  57.  * INPUT
  58.  *  lpszDLL -> name of DLL
  59.  *  fLoad == flags (see LOADPROPLIB_*)
  60.  *
  61.  * OUTPUT
  62.  *  handle to property library if loaded, FALSE if not
  63.  */
  64. HANDLE WINAPI LoadPropertyLib(LPCTSTR lpszDLL, int fLoad)
  65. {
  66.     HINSTANCE hDLL;
  67.     register PLIBLINK pll;
  68.     FunctionName(LoadPropertyLib);
  69.     hDLL = NULL;
  70.     if (!(fLoad & LOADPROPLIB_DEFER)) {
  71.         hDLL = LoadLibrary(lpszDLL);
  72.         if (hDLL < (HINSTANCE)HINSTANCE_ERROR)
  73.             return FALSE;
  74.     }
  75.     // Allocate new lib link
  76.     if (!(pll = (PLIBLINK)LocalAlloc(LPTR, SIZEOF(LIBLINK))))
  77.         return FALSE;
  78.     if ((HANDLE) pll > offHighestLibLink)
  79.         offHighestLibLink = pll;
  80.     // Initialize the lib link
  81.     pll->pllPrev = NULL;
  82.     pll->iSig = LIB_SIG;
  83.     pll->hDLL = hDLL;
  84.     pll->flLib = 0;
  85.     if (!hDLL)
  86.         pll->flLib |= LIB_DEFER;
  87.     lstrcpyn(pll->achDLL, lpszDLL, ARRAYSIZE(pll->achDLL));
  88.     // Link into the global lib list
  89.     if (NULL != (pll->pllNext = pllHead))
  90.         pllHead->pllPrev = pll;
  91.     pllHead = pll;
  92.     return pll;
  93. }
  94. /** EnumPropertyLibs - enumerate property libraries
  95.  *
  96.  * INPUT
  97.  *  iLib    == 0 to begin enumeration, or result of previous call
  98.  *  lphDLL  -> where to store handle (NULL if don't care)
  99.  *  lpszDLL -> where to store name of library (NULL if don't care)
  100.  *  cchszDLL == size of space (in chars) to store name
  101.  *
  102.  * OUTPUT
  103.  *  lphDLL and lpszDLL filled in as appropriate, 0 if no more libs (or error)
  104.  */
  105. HANDLE WINAPI EnumPropertyLibs(HANDLE iLib, LPHANDLE lphDLL, LPTSTR lpszDLL, int cchszDLL)
  106. {
  107.     register PLIBLINK pll;
  108.     FunctionName(EnumPropertyLibs);
  109.     if (!iLib)
  110.         pll = pllHead;
  111.     else
  112.         pll = ((PLIBLINK)iLib)->pllNext;
  113.     // Validate the handle
  114.     if (!pll)
  115.         return 0;
  116.     if ((HANDLE) pll > offHighestLibLink)
  117.         return 0;
  118.     if (pll->iSig != LIB_SIG)
  119.         return 0;
  120.     if (lphDLL)
  121.         *lphDLL = pll->hDLL;
  122.     if (lpszDLL)
  123.         lstrcpyn(lpszDLL, pll->achDLL, min(cchszDLL, ARRAYSIZE(pll->achDLL)));
  124.     return pll;
  125. }
  126. /** FreePropertyLib - free installable property library
  127.  *
  128.  * INPUT
  129.  *  hLib == handle to property library
  130.  *
  131.  * OUTPUT
  132.  *  TRUE if successful, FALSE otherwise
  133.  */
  134. BOOL WINAPI FreePropertyLib(HANDLE hLib)
  135. {
  136.     register PLIBLINK pll;
  137.     FunctionName(FreePropertyLib);
  138.     // Validate the handle
  139.     if (!hLib)
  140.         return FALSE;
  141.     if ((HANDLE)hLib > offHighestLibLink)
  142.         return FALSE;
  143.     pll = (PLIBLINK)hLib;
  144.     if (pll->iSig != LIB_SIG)
  145.         return FALSE;
  146.     // Free the associated library
  147.     if (pll->hDLL)
  148.         FreeLibrary(pll->hDLL);
  149.     // Unlink from the global list
  150.     if (pll->pllPrev)
  151.         pll->pllPrev->pllNext = pll->pllNext;
  152.     else
  153.         pllHead = pll->pllNext;
  154.     if (pll->pllNext)
  155.         pll->pllNext->pllPrev = pll->pllPrev;
  156.     EVAL(LocalFree(pll) == NULL);
  157.     return TRUE;
  158. }
  159. /** AddPropertySheet - install new property sheet
  160.  *
  161.  * INPUT
  162.  *  lppsi -> property sheet info structure
  163.  *  iType  == sheet type (see SHEETTYPE_* constants)
  164.  *
  165.  * OUTPUT
  166.  *  handle to property sheet link, or NULL if failure
  167.  */
  168. HANDLE WINAPI AddPropertySheet(const PROPSHEETPAGE *lppsi, int iType)
  169. {
  170.     register PSHEETLINK psl;
  171.     FunctionName(AddPropertySheet);
  172.     // Allocate new sheet link
  173.     if (!(psl = (PSHEETLINK)LocalAlloc(LPTR, SIZEOF(SHEETLINK))))
  174.         return FALSE;
  175.     if ((HANDLE) psl > offHighestSheetLink)
  176.         offHighestSheetLink = psl;
  177.     // Initialize the sheet link
  178.     psl->pslPrev = NULL;
  179.     psl->iSig = SHEET_SIG;
  180.     psl->psi = *lppsi;
  181.     psl->iType = iType;
  182.     // Link into the global sheet list
  183.     if (NULL != (psl->pslNext = pslHead))
  184.         pslHead->pslPrev = psl;
  185.     pslHead = psl;
  186.     cSheetLinks++;
  187.     return psl;
  188. }
  189. /** RemovePropertySheet - remove installable property sheet
  190.  *
  191.  * INPUT
  192.  *  hSheet == handle to sheet link
  193.  *
  194.  * OUTPUT
  195.  *  TRUE if successful, FALSE otherwise
  196.  */
  197. BOOL WINAPI RemovePropertySheet(HANDLE hSheet)
  198. {
  199.     register PSHEETLINK psl;
  200.     FunctionName(RemovePropertySheet);
  201.     // Validate the handle
  202.     if (!hSheet)
  203.         return FALSE;
  204.     if ((HANDLE)hSheet > offHighestSheetLink)
  205.         return FALSE;
  206.     psl = (PSHEETLINK)hSheet;
  207.     if (psl->iSig != SHEET_SIG)
  208.         return FALSE;
  209.     // Unlink from the global list
  210.     cSheetLinks--;
  211.     if (psl->pslPrev)
  212.         psl->pslPrev->pslNext = psl->pslNext;
  213.     else
  214.         pslHead = psl->pslNext;
  215.     if (psl->pslNext)
  216.         psl->pslNext->pslPrev = psl->pslPrev;
  217.     EVAL(LocalFree(psl) == NULL);
  218.     return TRUE;
  219. }
  220. /** LoadPropertySheets - load property sheets
  221.  *
  222.  * INPUT
  223.  *  hProps = property handle
  224.  *  flags = 0 (reserved)
  225.  *
  226.  * OUTPUT
  227.  *  # of sheets loaded, 0 if error
  228.  */
  229. int WINAPI LoadPropertySheets(HANDLE hProps, int flags)
  230. {
  231.     register PLIBLINK pll;
  232.     FunctionName(LoadPropertySheets);
  233.     // If this is the first edit session, do global init now
  234.     if (cEdits++ == 0)
  235.         if (!LoadGlobalEditData())
  236.             return 0;
  237.     pll = NULL;
  238.     while (NULL != (pll = (PLIBLINK)EnumPropertyLibs(pll, NULL, NULL, 0))) {
  239.         if (!pll->hDLL && (pll->flLib & LIB_DEFER)) {
  240.             pll->hDLL = LoadLibrary(pll->achDLL);
  241.             // If the load failed, to us that simply means those sheets
  242.             // will not be available; the particular error is not interesting,
  243.             // so nullify the handle
  244.             if (pll->hDLL < (HINSTANCE)HINSTANCE_ERROR)
  245.                 pll->hDLL = NULL;
  246.         }
  247.     }
  248.     return cSheetLinks + ARRAYSIZE(aPSInfo);
  249. }
  250. /** EnumPropertySheets - enumerate property sheets
  251.  *
  252.  * INPUT
  253.  *  hProps == property handle
  254.  *  iType  == sheet type (see SHEETTYPE_* constants)
  255.  *  iSheet == 0 to begin enumeration, or result of previous call
  256.  *  lppsi -> property sheet info structure to be filled in
  257.  *
  258.  * OUTPUT
  259.  *  lppsi filled in as appropriate, 0 if no more sheets (or error)
  260.  */
  261. INT_PTR WINAPI EnumPropertySheets(HANDLE hProps, int iType, INT_PTR iSheet, LPPROPSHEETPAGE lppsp)
  262. {
  263.     register PSHEETLINK psl;
  264.     FunctionName(EnumPropertySheets);
  265.     // BUGBUG -- parameter validation? (raymondc)
  266.     while (iSheet < ARRAYSIZE(aPSInfo)) {
  267.         if (aPSInfo[iSheet].iType <= iType) {
  268.             if (lppsp) {
  269.                 lppsp->dwSize      = SIZEOF(PROPSHEETPAGE);
  270.                 lppsp->dwFlags     = PSP_DEFAULT;
  271.                 lppsp->hInstance   = hModule;
  272.                 lppsp->pszTemplate = aPSInfo[iSheet].lpTemplateName;
  273.                 lppsp->pfnDlgProc  = aPSInfo[iSheet].lpfnDlgProc;
  274.                 // lppsp->pszTitle    = NULL;
  275.                 lppsp->lParam      = (LONG_PTR)hProps;
  276.             }
  277.             return ++iSheet;
  278.         }
  279.         ++iSheet;
  280.     }
  281.     if (iSheet == ARRAYSIZE(aPSInfo))
  282.         psl = pslHead;
  283.     else
  284.         psl = ((PSHEETLINK)iSheet)->pslNext;
  285.     // Validate the handle
  286.     while (psl && (HANDLE) psl <= offHighestSheetLink && psl->iSig == SHEET_SIG) {
  287.         if (psl->iType <= iType) {
  288.             *lppsp = psl->psi;
  289.             lppsp->lParam = (LONG_PTR)hProps;
  290.             return (INT_PTR) psl;
  291.         }
  292.         psl = psl->pslNext;
  293.     }
  294.     return 0;                   // no more matching sheets
  295. }
  296. /** FreePropertySheets - free property sheets
  297.  *
  298.  * INPUT
  299.  *  hProps = property handle
  300.  *  flags = 0 (reserved)
  301.  *
  302.  * OUTPUT
  303.  *  Nothing
  304.  */
  305. HANDLE WINAPI FreePropertySheets(HANDLE hProps, int flags)
  306. {
  307.     register PLIBLINK pll;
  308.     FunctionName(FreePropertySheets);
  309.     pll = NULL;
  310.     while (NULL != (pll = (PLIBLINK)EnumPropertyLibs(pll, NULL, NULL, 0))) {
  311.         if (pll->hDLL && (pll->flLib & LIB_DEFER)) {
  312.             FreeLibrary(pll->hDLL);
  313.             pll->hDLL = NULL;
  314.         }
  315.     }
  316.     // If this is the last edit session, do global un-init now
  317.     if (--cEdits == 0)
  318.         FreeGlobalEditData();
  319.     return 0;
  320. }
  321. /** InitRealModeFlag - Initialize PROP_REALMODE
  322.  *
  323.  * INPUT
  324.  *  ppl = properties
  325.  *
  326.  * OUTPUT
  327.  *  ppl->flProp PROP_REALMODE bit set if sheet is for real-mode app,
  328.  *  else clear.
  329.  */
  330. void InitRealModeFlag(PPROPLINK ppl)
  331. {
  332.     PROPPRG prg;
  333.     if (!PifMgr_GetProperties(ppl, MAKELP(0,GROUP_PRG),
  334.                         &prg, SIZEOF(prg), GETPROPS_NONE)) {
  335.         return;                 /* Weird */
  336.     }
  337.     if (prg.flPrgInit & PRGINIT_REALMODE) {
  338.         ppl->flProp |= PROP_REALMODE;
  339.     } else {
  340.         ppl->flProp &= ~PROP_REALMODE;
  341.     }
  342. }
  343. /** EditProperties - edit property info
  344.  *
  345.  * INPUT
  346.  *  hProps = handle to properties
  347.  *  lpszTitle = pointer to title to use (NULL if none)
  348.  *  uStartPage = starting property sheet #
  349.  *  hwnd = handle to window of parent (NULL if none)
  350.  *  uMsgPost = msg # to post to hwnd with change notification (0 if none)
  351.  *
  352.  * OUTPUT
  353.  *  TRUE if successful, FALSE otherwise
  354.  */
  355. int WINAPI EditProperties(HANDLE hProps, LPCTSTR lpszTitle, UINT uStartPage, HWND hwnd, UINT uMsgPost)
  356. {
  357.     int cSheets;
  358.     INT_PTR iSheet;
  359.     PPROPLINK ppl;
  360.     PROPSHEETHEADER psh;
  361.     PROPSHEETPAGE *ppsp;
  362.     register PSHEETLINK psl;
  363.     FunctionName(EditProperties);
  364.     if (!(ppl = ValidPropHandle(hProps)))
  365.         return FALSE;
  366.     if (hwnd && uMsgPost) {
  367.         ppl->hwndNotify = hwnd;
  368.         ppl->uMsgNotify = uMsgPost;
  369.     }
  370.     cSheets = LoadPropertySheets(hProps, 0);
  371.     psl = pslHead;
  372.     if (!(ppsp = (PROPSHEETPAGE *)LocalAlloc(LPTR, cSheets*SIZEOF(PROPSHEETPAGE))))
  373.         return FALSE;
  374.     psh.dwSize = SIZEOF(psh);
  375.     psh.dwFlags = PSH_PROPTITLE | PSH_PROPSHEETPAGE;
  376.     psh.hwndParent = hwnd;
  377.     if (!lpszTitle)
  378.         psh.pszCaption = ppl->szPathName+ppl->iFileName;
  379.     else
  380.         psh.pszCaption = ppl->lpszTitle = lpszTitle;
  381.     psh.nPages = 0;
  382.     psh.nStartPage = uStartPage;
  383.     psh.ppsp = ppsp;
  384.     iSheet = cSheets = 0;
  385.     while (0 != (iSheet = EnumPropertySheets(hProps, SHEETTYPE_SIMPLE, iSheet, ppsp))) {
  386.         cSheets++;
  387.         ppsp++;
  388.     }
  389.     psh.nPages = cSheets;
  390.     // Since the user wishes to *explicitly* change settings for this app
  391.     // we make sure that the DONTWRITE flag isn't going to get in his way...
  392.     ppl->flProp &= ~PROP_DONTWRITE;
  393.     InitRealModeFlag(ppl);
  394.     PropertySheet(&psh);
  395.     VERIFYFALSE(LocalFree((HLOCAL)psh.ppsp));
  396.     FreePropertySheets(hProps, 0);
  397.     if (ppl->flProp & PROP_NOTIFY) {
  398.         ppl->flProp &= ~PROP_NOTIFY;
  399.         PostMessage(ppl->hwndNotify, ppl->uMsgNotify, 0, 0);
  400.     }
  401.     ppl->hwndNotify = NULL;
  402.     ppl->uMsgNotify = 0;
  403.     ppl->lpszTitle = NULL;
  404.     return TRUE;
  405. }
  406. BOOL LoadGlobalEditData()
  407. {
  408.     FunctionName(LoadGlobalEditData);
  409.     if (!LoadGlobalFontEditData())
  410.         return FALSE;
  411.     return TRUE;
  412. }
  413. void FreeGlobalEditData()
  414. {
  415.     FunctionName(FreeGlobalEditData);
  416.     FreeGlobalFontEditData();
  417. }
  418. UINT CALLBACK PifPropPageRelease(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE lppsp)
  419. {
  420.     FunctionName(PifPropPageRelease);
  421.     if (uMsg == PSPCB_RELEASE) {
  422.         PPROPLINK ppl = (PPROPLINK)(INT_PTR)lppsp->lParam;
  423.         if ((--ppl->iSheetUsage) == 0) {
  424.             FreePropertySheets(ppl, 0);
  425.             PifMgr_CloseProperties(ppl, CLOSEPROPS_NONE);
  426.         }
  427.     }
  428.     return 1;
  429. }
  430. #define MZMAGIC      ((WORD)'M'+((WORD)'Z'<<8))
  431. //
  432. // call SHELL.DLL to get the EXE type.
  433. //
  434. BOOL IsWinExe(LPCTSTR lpszFile)
  435. {
  436.     DWORD dw = (DWORD) SHGetFileInfo(lpszFile, 0, NULL, 0, SHGFI_EXETYPE);
  437.     return dw && LOWORD(dw) != MZMAGIC;
  438. }
  439. BOOL WINAPI PifPropGetPages(LPVOID lpv,
  440.                             LPFNADDPROPSHEETPAGE lpfnAddPage,
  441.                             LPARAM lParam)
  442. {
  443. #define hDrop   (HDROP)lpv
  444.     PPROPLINK ppl;
  445.     PROPSHEETPAGE psp;
  446.     int iType, cSheets;
  447.     INT_PTR iSheet;
  448.     HPROPSHEETPAGE hpage;
  449.     TCHAR szFileName[MAXPATHNAME];
  450.     FunctionName(PifPropGetPages);
  451.     // only process things if hDrop contains only one file
  452.     if (DragQueryFile(hDrop, (UINT)-1, NULL, 0) != 1)
  453.     {
  454.         return TRUE;
  455.     }
  456.     // get the name of the file
  457.     DragQueryFile(hDrop, 0, szFileName, ARRAYSIZE(szFileName));
  458. #ifdef WINNT
  459.     if (GetFileAttributes( szFileName) & FILE_ATTRIBUTE_OFFLINE)
  460.     {
  461.         return FALSE;
  462.     }
  463. #endif
  464.     // if this is a windows app, don't do no properties
  465.     if (IsWinExe(szFileName))
  466.         return TRUE;
  467.     // if we can't get a property handle, don't do no properties either
  468.     if (!(ppl = (PPROPLINK)PifMgr_OpenProperties(szFileName, NULL, 0, OPENPROPS_NONE)))
  469.         return TRUE;
  470.     InitRealModeFlag(ppl);
  471.     if (!(cSheets = LoadPropertySheets(ppl, 0)))
  472.         goto CloseProps;
  473.     // Since the user wishes to *explicitly* change settings for this app
  474.     // we make sure that the DONTWRITE flag isn't going to get in his way...
  475.     ppl->flProp &= ~PROP_DONTWRITE;
  476.     iSheet = cSheets = 0;
  477.     iType = (GetKeyState(VK_CONTROL) >= 0? SHEETTYPE_SIMPLE : SHEETTYPE_ADVANCED);
  478.     while (TRUE) {
  479.         if (!(iSheet = EnumPropertySheets(ppl, iType, iSheet, &psp))) {
  480.             // done with enumeration
  481.             break;
  482.         }
  483. #ifndef WINNT
  484.         psp.dwFlags |= PSP_USECALLBACK | PSP_USEREFPARENT;
  485.         psp.pfnCallback = PifPropPageRelease;
  486.         psp.pcRefParent = &s_cRefThisDll;
  487. #else
  488.         psp.dwFlags |= PSP_USECALLBACK;
  489.         psp.pfnCallback = PifPropPageRelease;
  490.         psp.pcRefParent = 0;
  491. #endif
  492.         hpage = CreatePropertySheetPage(&psp);
  493.         if (hpage)
  494.         {
  495.             // the PROPLINK is now being used by this property sheet as well
  496.             if (lpfnAddPage(hpage, lParam))
  497.             {
  498.                 ppl->iSheetUsage++;
  499.                 cSheets++;
  500.             }
  501.             else
  502.             {
  503.                 PifPropPageRelease(NULL, PSPCB_RELEASE, &psp);
  504.             }
  505.         }
  506.     }
  507.     if (!cSheets) {
  508.         FreePropertySheets(ppl, 0);
  509. CloseProps:
  510.         PifMgr_CloseProperties(ppl, CLOSEPROPS_NONE);
  511.     }
  512.     return TRUE;
  513. }
  514. #undef hDrop