You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
394 lines
10 KiB
394 lines
10 KiB
/*
|
|
* 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
|