/* * Microsoft Confidential * Copyright (C) Microsoft Corporation 1991 * All Rights Reserved. * * * PIFLIB.C * User interface routines for PIFMGR.DLL * * History: * Created 31-Jul-1992 3:30pm by Jeff Parsons */ #include "shellprv.h" #pragma hdrstop #ifdef _X86_ #define LIB_SIG 0x504A #define LIB_DEFER LOADPROPLIB_DEFER typedef struct LIBLINK { /* ll */ struct LIBLINK *pllNext; // struct LIBLINK *pllPrev; // int iSig; // liblink signature int flLib; // proplink flags (LIB_*) HINSTANCE hDLL; // if NULL, then load has been deferred TCHAR achDLL[80]; // name of DLL } LIBLINK; typedef LIBLINK *PLIBLINK; #define SHEET_SIG 0x504A typedef struct SHEETLINK { /* sl */ struct SHEETLINK *pslNext; struct SHEETLINK *pslPrev; int iSig; int iType; PROPSHEETPAGE psi; } SHEETLINK; typedef SHEETLINK *PSHEETLINK; UINT cEdits; // number of edit sessions in progress PLIBLINK pllHead; // pointer to first lib link HANDLE offHighestLibLink; // highest offset of a lib link thus far recorded PSHEETLINK pslHead; // pointer to first sheet link UINT cSheetLinks; // number of sheet links HANDLE offHighestSheetLink; // highest offset of a sheet link thus far recorded struct { // built-in property sheet info LPCTSTR lpTemplateName; DLGPROC lpfnDlgProc; int iType; } const aPSInfo[] = { { MAKEINTRESOURCE(IDD_PROGRAM), DlgPrgProc, SHEETTYPE_SIMPLE}, { MAKEINTRESOURCE(IDD_FONT), DlgFntProc, SHEETTYPE_SIMPLE}, { MAKEINTRESOURCE(IDD_MEMORY), DlgMemProc, SHEETTYPE_SIMPLE}, { MAKEINTRESOURCE(IDD_SCREEN), DlgVidProc, SHEETTYPE_SIMPLE}, { MAKEINTRESOURCE(IDD_MISC), DlgMscProc, SHEETTYPE_SIMPLE}, }; /** EnumPropertyLibs - enumerate property libraries * * INPUT * iLib == 0 to begin enumeration, or result of previous call * lphDLL -> where to store handle (NULL if don't care) * lpszDLL -> where to store name of library (NULL if don't care) * cchszDLL == size of space (in chars) to store name * * OUTPUT * lphDLL and lpszDLL filled in as appropriate, 0 if no more libs (or error) */ HANDLE WINAPI EnumPropertyLibs(HANDLE iLib, LPHANDLE lphDLL, LPTSTR lpszDLL, int cchszDLL) { register PLIBLINK pll; FunctionName(EnumPropertyLibs); if (!iLib) pll = pllHead; else pll = ((PLIBLINK)iLib)->pllNext; // Validate the handle if (!pll) return 0; if ((HANDLE) pll > offHighestLibLink) return 0; if (pll->iSig != LIB_SIG) return 0; if (lphDLL) *lphDLL = pll->hDLL; if (lpszDLL) StringCchCopy(lpszDLL, min(cchszDLL, ARRAYSIZE(pll->achDLL)), pll->achDLL); return pll; } /** LoadPropertySheets - load property sheets * * INPUT * hProps = property handle * flags = 0 (reserved) * * OUTPUT * # of sheets loaded, 0 if error */ int WINAPI LoadPropertySheets(HANDLE hProps, int flags) { register PLIBLINK pll; FunctionName(LoadPropertySheets); // If this is the first edit session, do global init now if (cEdits++ == 0) if (!LoadGlobalEditData()) return 0; pll = NULL; while (NULL != (pll = (PLIBLINK)EnumPropertyLibs(pll, NULL, NULL, 0))) { if (!pll->hDLL && (pll->flLib & LIB_DEFER)) { pll->hDLL = LoadLibrary(pll->achDLL); // If the load failed, to us that simply means those sheets // will not be available; the particular error is not interesting, // so nullify the handle if (pll->hDLL < (HINSTANCE)HINSTANCE_ERROR) pll->hDLL = NULL; } } return cSheetLinks + ARRAYSIZE(aPSInfo); } /** EnumPropertySheets - enumerate property sheets * * INPUT * hProps == property handle * iType == sheet type (see SHEETTYPE_* constants) * iSheet == 0 to begin enumeration, or result of previous call * lppsi -> property sheet info structure to be filled in * * OUTPUT * lppsi filled in as appropriate, 0 if no more sheets (or error) */ INT_PTR WINAPI EnumPropertySheets(HANDLE hProps, int iType, INT_PTR iSheet, LPPROPSHEETPAGE lppsp) { register PSHEETLINK psl; FunctionName(EnumPropertySheets); while (iSheet < ARRAYSIZE(aPSInfo)) { if (aPSInfo[iSheet].iType <= iType) { if (lppsp) { lppsp->dwSize = SIZEOF(PROPSHEETPAGE); lppsp->dwFlags = PSP_DEFAULT; lppsp->hInstance = HINST_THISDLL; lppsp->pszTemplate = aPSInfo[iSheet].lpTemplateName; lppsp->pfnDlgProc = aPSInfo[iSheet].lpfnDlgProc; // lppsp->pszTitle = NULL; lppsp->lParam = (LONG_PTR)hProps; } return ++iSheet; } ++iSheet; } if (iSheet == ARRAYSIZE(aPSInfo)) psl = pslHead; else psl = ((PSHEETLINK)iSheet)->pslNext; // Validate the handle while (psl && (HANDLE) psl <= offHighestSheetLink && psl->iSig == SHEET_SIG) { if (psl->iType <= iType) { *lppsp = psl->psi; lppsp->lParam = (LONG_PTR)hProps; return (INT_PTR) psl; } psl = psl->pslNext; } return 0; // no more matching sheets } /** FreePropertySheets - free property sheets * * INPUT * hProps = property handle * flags = 0 (reserved) * * OUTPUT * Nothing */ HANDLE WINAPI FreePropertySheets(HANDLE hProps, int flags) { register PLIBLINK pll; FunctionName(FreePropertySheets); pll = NULL; while (NULL != (pll = (PLIBLINK)EnumPropertyLibs(pll, NULL, NULL, 0))) { if (pll->hDLL && (pll->flLib & LIB_DEFER)) { FreeLibrary(pll->hDLL); pll->hDLL = NULL; } } // If this is the last edit session, do global un-init now if (--cEdits == 0) FreeGlobalEditData(); return 0; } /** InitRealModeFlag - Initialize PROP_REALMODE * * INPUT * ppl = properties * * OUTPUT * ppl->flProp PROP_REALMODE bit set if sheet is for real-mode app, * else clear. */ void InitRealModeFlag(PPROPLINK ppl) { PROPPRG prg; if (!PifMgr_GetProperties(ppl, MAKELP(0,GROUP_PRG), &prg, SIZEOF(prg), GETPROPS_NONE)) { return; /* Weird */ } if (prg.flPrgInit & PRGINIT_REALMODE) { ppl->flProp |= PROP_REALMODE; } else { ppl->flProp &= ~PROP_REALMODE; } } BOOL LoadGlobalEditData() { FunctionName(LoadGlobalEditData); if (!LoadGlobalFontEditData()) return FALSE; return TRUE; } void FreeGlobalEditData() { FunctionName(FreeGlobalEditData); FreeGlobalFontEditData(); } UINT CALLBACK PifPropPageRelease(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE lppsp) { FunctionName(PifPropPageRelease); if (uMsg == PSPCB_RELEASE) { PPROPLINK ppl = (PPROPLINK)(INT_PTR)lppsp->lParam; if ((--ppl->iSheetUsage) == 0) { FreePropertySheets(ppl, 0); PifMgr_CloseProperties(ppl, CLOSEPROPS_NONE); } } return 1; } #define MZMAGIC ((WORD)'M'+((WORD)'Z'<<8)) // // call SHELL.DLL to get the EXE type. // BOOL IsWinExe(LPCTSTR lpszFile) { DWORD dw = (DWORD) SHGetFileInfo(lpszFile, 0, NULL, 0, SHGFI_EXETYPE); return dw && LOWORD(dw) != MZMAGIC; } BOOL WINAPI PifPropGetPages(LPVOID lpv, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam) { #define hDrop (HDROP)lpv PPROPLINK ppl; PROPSHEETPAGE psp; int iType, cSheets; INT_PTR iSheet; HPROPSHEETPAGE hpage; TCHAR szFileName[MAXPATHNAME]; FunctionName(PifPropGetPages); // only process things if hDrop contains only one file if (DragQueryFile(hDrop, (UINT)-1, NULL, 0) != 1) { return TRUE; } // get the name of the file DragQueryFile(hDrop, 0, szFileName, ARRAYSIZE(szFileName)); if (GetFileAttributes( szFileName) & FILE_ATTRIBUTE_OFFLINE) { return FALSE; } // if this is a windows app, don't do no properties if (IsWinExe(szFileName)) return TRUE; // if we can't get a property handle, don't do no properties either if (!(ppl = (PPROPLINK)PifMgr_OpenProperties(szFileName, NULL, 0, OPENPROPS_NONE))) return TRUE; InitRealModeFlag(ppl); if (!(cSheets = LoadPropertySheets(ppl, 0))) goto CloseProps; // Since the user wishes to *explicitly* change settings for this app // we make sure that the DONTWRITE flag isn't going to get in his way... ppl->flProp &= ~PROP_DONTWRITE; iSheet = cSheets = 0; iType = (GetKeyState(VK_CONTROL) >= 0? SHEETTYPE_SIMPLE : SHEETTYPE_ADVANCED); while (TRUE) { if (!(iSheet = EnumPropertySheets(ppl, iType, iSheet, &psp))) { // done with enumeration break; } psp.dwFlags |= PSP_USECALLBACK; psp.pfnCallback = PifPropPageRelease; psp.pcRefParent = 0; hpage = CreatePropertySheetPage(&psp); if (hpage) { // the PROPLINK is now being used by this property sheet as well if (lpfnAddPage(hpage, lParam)) { ppl->iSheetUsage++; cSheets++; } else { PifPropPageRelease(NULL, PSPCB_RELEASE, &psp); } } } if (!cSheets) { FreePropertySheets(ppl, 0); CloseProps: PifMgr_CloseProperties(ppl, CLOSEPROPS_NONE); } return TRUE; } #undef hDrop #endif