|
|
//---------------------------------------------------------------------------
//
// 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; }
|