Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

798 lines
21 KiB

//---------------------------------------------------------------------------
//
// File: PROPSEXT.CPP
//
// Implementation of the CPropSheetExt object.
//
//---------------------------------------------------------------------------
#include <windows.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include "propsext.h"
#include "rc.h"
#include "string.h"
#include "addon.h"
#include <shlobj.h>
//
// Defines for getting registry settings
//
#define STR_MCDKEY (PCSTR)"Software\\Microsoft\\Windows\\CurrentVersion\\MCD"
#define STR_ENABLE (LPSTR)"Enable"
#define STR_SWAPSYNC (LPSTR)"SwapSync"
#define STR_8BPP (LPSTR)"Palettized Formats"
#define STR_IOPRIORITY (LPSTR)"IO Priority"
#define STR_STENCIL (LPSTR)"Use Generic Stencil"
#define STR_DEBUG (LPSTR)"Debug"
#define STR_DCIKEY (PCSTR)"System\\CurrentControlSet\\Control\\GraphicsDrivers\\DCI"
#define STR_TIMEOUT (LPSTR)"TimeOut"
//
// Structure describing current MCD settings.
//
typedef struct tagMcdRegistry
{
HKEY hkMcd; // Handle to MCD key in registry.
BOOL bEnable;
BOOL bSwapSync;
BOOL bPalFormats;
BOOL bIoPriority;
BOOL bUseGenSten;
#ifdef SUPPORT_MCDBG_FLAGS
long lDebug;
#endif
HKEY hkDci; // Handle to DCI key in registry.
long lTimeout;
} MCDREGISTRY;
MCDREGISTRY McdRegistry;
//
// Functions to get registry settings, setup dialog based on settings, and
// save registry settings.
//
extern "C" {
void McdInitRegistry(MCDREGISTRY *pMcdReg);
BOOL McdOpenRegistry(MCDREGISTRY *pMcdReg);
void McdUpdateDialogSettings(MCDREGISTRY *pMcdReg, HWND hDlg);
void McdCloseRegistry(MCDREGISTRY *pMcdReg);
void McdUpdateRegistry(MCDREGISTRY *pMcdReg);
void McdSetRegValue(HKEY hkey, LPSTR lpstrValueName, long lData);
long McdGetRegValue(HKEY hkey, LPSTR lpstrValueName, long lDefaultData);
BOOL McdDetection(void);
};
//
// Function prototype
//
BOOL CALLBACK McdDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam,
LPARAM lParam);
//
// Handle to the DLL
//
extern HINSTANCE g_hInst;
//
// Track state of OLE CoInitialize()
//
BOOL gfCoInitDone = FALSE;
#if DBG
ULONG
DbgPrint(
PCH DebugMessage,
...
)
{
va_list ap;
char buffer[256];
va_start(ap, DebugMessage);
vsprintf(buffer, DebugMessage, ap);
OutputDebugStringA(buffer);
va_end(ap);
return(0);
}
VOID NTAPI
DbgBreakPoint(VOID)
{
DebugBreak();
}
#endif
///////////////////////////// BEGIN CUT-AND-PASTE /////////////////////////////
// //
// This section of code is cut-and-paste from the Plus! Pack prop sheet //
// code. The coding style is entirely the responsibility of someone //
// over in building 27. :-) //
// //
// -- Gilman //
// //
//---------------------------------------------------------------------------
// Class Member functions
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------
CPropSheetExt::CPropSheetExt( LPUNKNOWN pUnkOuter, LPFNDESTROYED pfnDestroy )
{
m_cRef = 0;
m_pUnkOuter = pUnkOuter;
m_pfnDestroy = pfnDestroy;
return;
}
//---------------------------------------------------------------------------
// Destructor
//---------------------------------------------------------------------------
CPropSheetExt::~CPropSheetExt( void )
{
return;
}
//---------------------------------------------------------------------------
// QueryInterface()
//---------------------------------------------------------------------------
STDMETHODIMP CPropSheetExt::QueryInterface( REFIID riid, LPVOID* ppv )
{
*ppv = NULL;
if( IsEqualIID( riid, IID_IShellPropSheetExt ) )
{
*ppv = (LPVOID)this;
++m_cRef;
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
//---------------------------------------------------------------------------
// AddRef()
//---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CPropSheetExt::AddRef( void )
{
return ++m_cRef;
}
//---------------------------------------------------------------------------
// Release()
//---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CPropSheetExt::Release( void )
{
ULONG cRefT;
cRefT = --m_cRef;
if( m_cRef == 0 )
{
// Tell the housing that an object is going away so that it
// can shut down if appropriate.
if( NULL != m_pfnDestroy )
(*m_pfnDestroy)();
delete this;
}
return cRefT;
}
//---------------------------------------------------------------------------
// AddPages()
//---------------------------------------------------------------------------
STDMETHODIMP CPropSheetExt::AddPages( LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam )
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpage;
// Fail the call if not an MCD-enabled display
// driver.
if (!McdDetection())
return ( E_FAIL );
psp.dwSize = sizeof(PROPSHEETPAGE);
// psp.dwFlags = PSP_USETITLE | PSP_HASHELP;
psp.dwFlags = PSP_USETITLE;
psp.hIcon = NULL;
psp.hInstance = g_hInst;
psp.pszTemplate = MAKEINTRESOURCE( MCD_DLG );
psp.pfnDlgProc = (DLGPROC)McdDlgProc;
psp.pszTitle = "3D";
psp.lParam = 0;
if( ( hpage = CreatePropertySheetPage( &psp ) ) == NULL )
{
return ( E_OUTOFMEMORY );
}
if( !lpfnAddPage( hpage, lParam ) )
{
DestroyPropertySheetPage( hpage );
return ( E_FAIL );
}
return NOERROR;
}
//---------------------------------------------------------------------------
// ReplacePage()
//---------------------------------------------------------------------------
STDMETHODIMP CPropSheetExt::ReplacePage( UINT uPageID, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam )
{
return NOERROR;
}
// //
// Guess its time to go back to my code. //
// //
// -- Gilman //
// //
////////////////////////////// END CUT-AND-PASTE //////////////////////////////
/******************************Public*Routine******************************\
* McdDlgProc
*
* The dialog procedure for the "OpenGL MCD" property sheet page.
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL CALLBACK
McdDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE) GetWindowLong(hDlg, DWL_USER);
static char szHelpFile[32];
switch( uMessage )
{
case WM_INITDIALOG:
//!!! This is left over from the Plus!Pack propsheet. Is it needed?
SetWindowLong( hDlg, DWL_USER, lParam );
psp = (LPPROPSHEETPAGE)lParam;
//
// Get the name of the help file.
//
LoadString( g_hInst, IDS_HELPFILE, szHelpFile, 32 );
//
// Get the values for the settings from the registry and
// set the checkboxes.
//
McdInitRegistry(&McdRegistry);
McdOpenRegistry(&McdRegistry);
McdUpdateDialogSettings(&McdRegistry, hDlg);
break;
case WM_DESTROY:
if ( gfCoInitDone )
CoUninitialize();
McdCloseRegistry(&McdRegistry);
break;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDC_MCD_ENABLE:
McdRegistry.bEnable = IsDlgButtonChecked(hDlg, IDC_MCD_ENABLE);
break;
case IDC_MCD_SYNCSWAP:
McdRegistry.bSwapSync = IsDlgButtonChecked(hDlg, IDC_MCD_SYNCSWAP);
break;
case IDC_MCD_PALFMTS:
McdRegistry.bPalFormats = IsDlgButtonChecked(hDlg, IDC_MCD_PALFMTS);
break;
case IDC_MCD_IOPRIORITY:
McdRegistry.bIoPriority = IsDlgButtonChecked(hDlg, IDC_MCD_IOPRIORITY);
break;
case IDC_MCD_STENCIL:
McdRegistry.bUseGenSten = IsDlgButtonChecked(hDlg, IDC_MCD_STENCIL);
break;
case IDC_DCI_TIMEOUT:
if (IsDlgButtonChecked(hDlg, IDC_DCI_TIMEOUT))
McdRegistry.lTimeout = 7;
else
McdRegistry.lTimeout = 0;
break;
#ifdef SUPPORT_MCDBG_FLAGS
case IDC_MCDBG_ALLOCBUF:
if (!IsDlgButtonChecked(hDlg, IDC_MCDBG_ALLOCBUF))
McdRegistry.lDebug |= MCDDEBUG_DISABLE_ALLOCBUF;
else
McdRegistry.lDebug &= ~MCDDEBUG_DISABLE_ALLOCBUF;
break;
case IDC_MCDBG_GETBUF:
if (!IsDlgButtonChecked(hDlg, IDC_MCDBG_GETBUF))
McdRegistry.lDebug |= MCDDEBUG_DISABLE_GETBUF;
else
McdRegistry.lDebug &= ~MCDDEBUG_DISABLE_GETBUF;
break;
case IDC_MCDBG_DRAW:
if (!IsDlgButtonChecked(hDlg, IDC_MCDBG_DRAW))
McdRegistry.lDebug |= MCDDEBUG_DISABLE_PROCBATCH;
else
McdRegistry.lDebug &= ~MCDDEBUG_DISABLE_PROCBATCH;
break;
case IDC_MCDBG_CLEAR:
if (!IsDlgButtonChecked(hDlg, IDC_MCDBG_CLEAR))
McdRegistry.lDebug |= MCDDEBUG_DISABLE_CLEAR;
else
McdRegistry.lDebug &= ~MCDDEBUG_DISABLE_CLEAR;
break;
#endif
default:
return FALSE;
}
//
// If the user changed a setting, tell the property manager we
// have outstanding changes. This will enable the "Apply Now" button...
//
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM) hDlg, 0L);
break;
case WM_NOTIFY:
switch( ((NMHDR *)lParam)->code )
{
case PSN_APPLY: // OK or Apply clicked
McdUpdateRegistry(&McdRegistry);
break;
case PSN_QUERYCANCEL: // Cancel clicked
break;
default:
break;
}
break;
#if 0
case WM_HELP:
{
LPHELPINFO lphi = (LPHELPINFO)lParam;
if( lphi->iContextType == HELPINFO_WINDOW )
{
WinHelp( (HWND)lphi->hItemHandle, (LPSTR)szHelpFile, HELP_WM_HELP,(DWORD)((POPUP_HELP_ARRAY FAR *)phaMainWin) );
}
}
break;
#endif
//!!! This is also left over from Plus!Pack propsheet. Is it needed?
case WM_CONTEXTMENU:
// first check for dlg window
if( (HWND)wParam == hDlg )
{
// let the def dlg proc decide whether to respond or ignore;
// necessary for title bar sys menu on right click
return FALSE;
}
#if 0
else
{
// else go for the controls
WinHelp( (HWND)wParam, (LPSTR)szHelpFile, HELP_CONTEXTMENU,(DWORD)((POPUP_HELP_ARRAY FAR *)phaMainWin) );
}
#endif
break;
default:
return FALSE;
}
return TRUE;
}
/******************************Public*Routine******************************\
* McdInitResistry
*
* Initializes the MCDREGISTRY structure.
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void McdInitRegistry(MCDREGISTRY *pMcdReg)
{
//
// The registry keys must be set to zero. The data is valid
// only if the corresponding keys are valid.
//
memset(pMcdReg, 0, sizeof(*pMcdReg));
}
/******************************Public*Routine******************************\
* McdOpenRegistry
*
* Opens the MCD registry and initializes the settings to the values found
* in the registry.
*
* Note:
* The function will leave the registry keys open, so the caller should
* make sure to call McdCloseRegistry when done.
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL McdOpenRegistry(MCDREGISTRY *pMcdReg)
{
//
// Open the MCD key and get the data.
//
if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE,
STR_MCDKEY,
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&pMcdReg->hkMcd) == ERROR_SUCCESS )
{
pMcdReg->bEnable =
McdGetRegValue(pMcdReg->hkMcd, STR_ENABLE, 0) != 0;
pMcdReg->bSwapSync =
McdGetRegValue(pMcdReg->hkMcd, STR_SWAPSYNC, 0) != 0;
pMcdReg->bPalFormats =
McdGetRegValue(pMcdReg->hkMcd, STR_8BPP, 0) != 0;
pMcdReg->bIoPriority =
McdGetRegValue(pMcdReg->hkMcd, STR_IOPRIORITY, 0) != 0;
pMcdReg->bUseGenSten =
McdGetRegValue(pMcdReg->hkMcd, STR_STENCIL, 0) != 0;
#ifdef SUPPORT_MCDBG_FLAGS
pMcdReg->lDebug = McdGetRegValue(pMcdReg->hkMcd, STR_DEBUG, 0);
#endif
}
else
{
pMcdReg->hkMcd = (HKEY) NULL;
}
//
// Open the DCI key and get the data.
//
if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE,
STR_DCIKEY,
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&pMcdReg->hkDci) == ERROR_SUCCESS )
{
pMcdReg->lTimeout = McdGetRegValue(pMcdReg->hkDci, STR_TIMEOUT, 0);
}
else
{
pMcdReg->hkDci = (HKEY) NULL;
}
return TRUE;
}
/******************************Public*Routine******************************\
* McdUpdateDialogSettings
*
* Sets the controls in the dialog to match the MCD registry settings.
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void McdUpdateDialogSettings(MCDREGISTRY *pMcdReg, HWND hDlg)
{
//
// If the mcd key is valid, the data is valid. Use the
// data to set the MCD controls in the dialog.
//
if (pMcdReg->hkMcd)
{
CheckDlgButton(hDlg, IDC_MCD_ENABLE, pMcdReg->bEnable);
CheckDlgButton(hDlg, IDC_MCD_SYNCSWAP, pMcdReg->bSwapSync);
CheckDlgButton(hDlg, IDC_MCD_PALFMTS, pMcdReg->bPalFormats);
CheckDlgButton(hDlg, IDC_MCD_IOPRIORITY, pMcdReg->bIoPriority);
CheckDlgButton(hDlg, IDC_MCD_STENCIL, pMcdReg->bUseGenSten);
#ifdef SUPPORT_MCDBG_FLAGS
CheckDlgButton(hDlg, IDC_MCDBG_ALLOCBUF, !(pMcdReg->lDebug & MCDDEBUG_DISABLE_ALLOCBUF ));
CheckDlgButton(hDlg, IDC_MCDBG_GETBUF, !(pMcdReg->lDebug & MCDDEBUG_DISABLE_GETBUF ));
CheckDlgButton(hDlg, IDC_MCDBG_DRAW, !(pMcdReg->lDebug & MCDDEBUG_DISABLE_PROCBATCH));
CheckDlgButton(hDlg, IDC_MCDBG_CLEAR, !(pMcdReg->lDebug & MCDDEBUG_DISABLE_CLEAR ));
#endif
}
//
// If the dci key is valid, the data is valid. Use the
// data to set the DCI controls in the dialog.
//
if (pMcdReg->hkDci)
{
CheckDlgButton(hDlg, IDC_DCI_TIMEOUT, pMcdReg->lTimeout != 0);
}
}
/******************************Public*Routine******************************\
* McdCloseRegistry
*
* Close any resources used in the MCDREGISTRY (i.e., close the open registry
* keys).
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void McdCloseRegistry(MCDREGISTRY *pMcdReg)
{
//
// Close open registry keys.
//
if (pMcdReg->hkMcd)
{
RegCloseKey(pMcdReg->hkMcd);
pMcdReg->hkMcd = (HKEY) NULL;
}
if (pMcdReg->hkDci)
{
RegCloseKey(pMcdReg->hkDci);
pMcdReg->hkDci = (HKEY) NULL;
}
}
/******************************Public*Routine******************************\
* McdUpdateRegistry
*
* Save the current values in MCDREGISTRY to the system
* Effects:
*
* Warnings:
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void McdUpdateRegistry(MCDREGISTRY *pMcdReg)
{
//
// If the mcd key is open, save the MCD data to the registry.
//
if (pMcdReg->hkMcd)
{
McdSetRegValue(pMcdReg->hkMcd, STR_ENABLE,
(long) pMcdReg->bEnable);
McdSetRegValue(pMcdReg->hkMcd, STR_SWAPSYNC,
(long) pMcdReg->bSwapSync);
McdSetRegValue(pMcdReg->hkMcd, STR_8BPP,
(long) pMcdReg->bPalFormats);
McdSetRegValue(pMcdReg->hkMcd, STR_IOPRIORITY,
(long) pMcdReg->bIoPriority);
McdSetRegValue(pMcdReg->hkMcd, STR_STENCIL,
(long) pMcdReg->bUseGenSten);
#ifdef SUPPORT_MCDBG_FLAGS
McdSetRegValue(pMcdReg->hkMcd, STR_DEBUG,
pMcdReg->lDebug);
#endif
}
//
// If the dci key is open, save the DCI data to the registry.
//
if (pMcdReg->hkDci)
{
McdSetRegValue(pMcdReg->hkDci, STR_TIMEOUT,
pMcdReg->lTimeout);
}
}
/******************************Public*Routine******************************\
* McdGetRegValue
*
* Get the data value for the specified value name out of the specified
* registry key.
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
long McdGetRegValue(HKEY hkey, LPSTR lpstrValueName, long lDefaultData)
{
DWORD dwDataType;
DWORD cjSize;
long lData;
//
// For specified value, attempt to fetch the data.
//
cjSize = sizeof(long);
if ( (RegQueryValueExA(hkey,
lpstrValueName,
(LPDWORD) NULL,
&dwDataType,
(LPBYTE) &lData,
&cjSize) != ERROR_SUCCESS)
|| (dwDataType != REG_DWORD) )
{
lData = lDefaultData;
}
return lData;
}
/******************************Public*Routine******************************\
* McdSetRegValue
*
* Set the specified value name of the registry key with the specified data.
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void McdSetRegValue(HKEY hkey, LPSTR lpstrValueName, long lData)
{
//
// Set the specified value.
//
RegSetValueExA(hkey, lpstrValueName, 0, REG_DWORD, (BYTE *) &lData,
sizeof(lData));
}
/******************************Public*Routine******************************\
* McdDetection
*
* Detect MCD support in the driver by calling the MCDGetDriverInfo function.
*
* History:
* 05-Apr-1996 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
typedef struct _MCDRIVERINFO {
ULONG verMajor;
ULONG verMinor;
ULONG verDriver;
CHAR idStr[200];
ULONG drvMemFlags;
ULONG drvBatchMemSizeMax;
} MCDDRIVERINFO;
typedef BOOL (APIENTRY *MCDGETDRIVERINFOFUNC)(HDC hdc, MCDDRIVERINFO *pMCDDriverInfo);
BOOL McdDetection(void)
{
static BOOL bFirstTime = TRUE;
static BOOL bRet = FALSE;
//ATTENTION -- Need a good way to detect MCD support independent of the
//ATTENTION setting of the MCD Enable flag. MCDGetDriverInfo fails
//ATTENTION if MCD is disabled (whether or not the driver has MCD
//ATTENTION support).
return TRUE;
if (bFirstTime)
{
HMODULE hmodMcd;
//
// Only do this once.
//
bFirstTime = FALSE;
//
// Load the MCD32.DLL library.
//
hmodMcd = LoadLibraryA("mcd32.dll");
if (hmodMcd)
{
MCDGETDRIVERINFOFUNC pMCDGetDriverInfo;
//
// Get the MCDGetDriverInfo entry point and call it.
//
pMCDGetDriverInfo = (MCDGETDRIVERINFOFUNC)
GetProcAddress(hmodMcd, "MCDGetDriverInfo");
if (pMCDGetDriverInfo)
{
HDC hdc;
//
// An hdc is required for the function call.
//
hdc = CreateDCA("display", NULL, NULL, NULL);
if (hdc)
{
MCDDRIVERINFO McdInfo;
//
// Gee, the display driver really does support MCD.
//
bRet = (*pMCDGetDriverInfo)(hdc, &McdInfo);
DeleteDC(hdc);
}
}
FreeLibrary(hmodMcd);
}
}
return bRet;
}