windows-nt/Source/XPSP1/NT/multimedia/directx/gamectrl/gcdef/server.cpp

542 lines
18 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/******************************************************************
*
* The Plug In Server.
*
* HISTORY:
* Created : 02/11/97
* a-kirkh 4/2/97 Added call to SetInstance, RegisterPOVClass
*
*
* SUMMARY:
*
******************************************************************
(c) Microsoft 1997 - All right reserved.
******************************************************************/
#define INC_OLE2
#pragma pack (8)
#include "stdafx.h"
#include <objbase.h>
#include <initguid.h>
#include <shlobj.h>
#include "slang.h"
#ifndef PPVOID
typedef LPVOID* PPVOID;
#endif
#include <joycpl.h>
#include "resource.h"
#include "dicpl.h"
#include "hsvrguid.h"
#include "pov.h"
#include <malloc.h>
#include <afxconv.h>
#define STR_LEN_128 128
#define NUMPROPAGES 2
DIGCPAGEINFO page_info[NUMPROPAGES];
DIGCSHEETINFO sheet_info;
/// These strings are also defined in RESRC1.H
#define IDS_SHEET_CAPTION 9000
#define IDS_PAGE_TITLE1 9001
#define IDS_PAGE_TITLE2 9002
LRESULT SetJoyInfo(UINT nID, LPCSTR szOEMKey);
BOOL SetDialogItemText( HWND hdlg, UINT nctrl, UINT nstr );
CString *pszCommonString=NULL;
// %%% debug %%%
LPJOYDATA pjd;
JOYDATAPTR jdp;
extern LPGLOBALVARS gpgv;
extern BOOL fIsSideWinder;
static HINSTANCE ghInstance;
static LONG gcRefServerDll = 0; // Reference count for this DLL
//const LPSTR device_name="Gaming Input Device (Generic)";
USHORT gnID; // ID as sent from Client via SetID
static HINSTANCE ghModLang;
/*------------------------------------------------------------
** DllMain
*
* PARAMETERS :
*
* DESCRIPTION : Entry point into the Inprocess handler.
* This implementation is a single thread,
in process server.
* RETURNS :
* AUTHOR : Guru Datta Venkatarama
* 02/12/97 12:21:17 (PST)
*
------------------------------------------------------------*/
int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
switch( dwReason ) {
case DLL_PROCESS_ATTACH:
{
ghModLang = hInstance;
// save the DLL instance
ghInstance = hInstance;
SetResourceInstance(ghModLang);
AfxSetResourceHandle(ghModLang);
pszCommonString = new CString;
USES_CONVERSION;
char lpStr[STR_LEN_64];
// Populate page info stuff!
BYTE nIndex = NUMPROPAGES;
do {
nIndex--;
page_info[nIndex].dwSize = sizeof(DIGCPAGEINFO);
page_info[nIndex].lpwszPageTitle = new WCHAR[STR_LEN_128];
ASSERT(page_info[nIndex].lpwszPageTitle);
VERIFY(LoadString(ghModLang, IDS_PAGE_TITLE2-(nIndex^1), lpStr, STR_LEN_64));
wcscpy(page_info[nIndex].lpwszPageTitle, A2W(lpStr));
page_info[nIndex].fpPageProc = (nIndex) ? (DLGPROC)TestProc : (DLGPROC)JoystickDlg;
page_info[nIndex].fProcFlag = FALSE;
page_info[nIndex].fpPrePostProc = NULL;
// if fIconFlag is TRUE, DON'T FORGET TO MALLOC YOUR MEMORY!!!
page_info[nIndex].fIconFlag = FALSE;
page_info[nIndex].lpwszPageIcon = NULL;
page_info[nIndex].lpwszTemplate = (nIndex) ? (PWSTR)IDD_TEST : (PWSTR)IDD_SETTINGS ;
page_info[nIndex].lParam = 0;
page_info[nIndex].hInstance = ghModLang;
}
while( nIndex );
// Populate Sheet Info stuff!
sheet_info.dwSize = sizeof(DIGCSHEETINFO);
sheet_info.nNumPages = NUMPROPAGES;
VERIFY(LoadString(ghModLang, IDS_SHEET_CAPTION, lpStr, STR_LEN_64));
sheet_info.lpwszSheetCaption = new WCHAR[STR_LEN_64];
ASSERT(sheet_info.lpwszSheetCaption);
wcscpy(sheet_info.lpwszSheetCaption, A2W(lpStr));
// Don't forget to malloc your memory here if you ever need to have an Icon!
sheet_info.fSheetIconFlag = FALSE;
sheet_info.lpwszSheetIcon = NULL;
RegisterPOVClass(ghModLang); //Added by JKH 3/31/97
}
break;
case DLL_PROCESS_DETACH:
// clean-up Page info
for( BYTE nIndex = 0; nIndex < NUMPROPAGES; nIndex++ ) {
if( page_info[nIndex].lpwszPageTitle ) {
delete[] (page_info[nIndex].lpwszPageTitle);
}
// if fIconFlag is TRUE, DON'T FORGET TO FREE YOUR MEMORY!!!
}
// clean-up Sheet info
if( sheet_info.lpwszSheetCaption )
delete[] (sheet_info.lpwszSheetCaption);
// dll about to be released from process
// time to clean up all local work ( if any )
if( pszCommonString )
delete(pszCommonString);
break;
}
return(TRUE);
}
/*------------------------------------------------------------ DllGetClassObject
** DllGetClassObject
*
* PARAMETERS : rclsid = Reference to class ID specifier
riid = Reference to interface ID specifier
ppv = Pointer to location to receive interface pointer
*
* DESCRIPTION : Here be the entry point of COM.
DllGetClassObject is called by the Client socket to
create a class factory object.
This Class factory will support the generation of three different class
Objects.
*
* RETURNS : HRESULT code signifying success or failure
*
* AUTHOR : Guru Datta Venkatarama
* 01/29/97 14:22:02 (PST)
*
------------------------------------------------------------*/
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PPVOID ppv)
{
// %%% debug %%% figure out this optimisation later.
USHORT l_clsidtype=0;
*ppv = NULL;
// Make sure the class ID valid for the class factory. Otherwise, the class
// factory of the object type specified by rclsid cannot be generated.
// %%% debug %%% - seems like we cannot implement this check because
// each server will have its own CLSID. so we need to hard code this for
// every server
if( !IsEqualCLSID (rclsid, CLSID_LegacyServer) ) {
return(ResultFromScode (CLASS_E_CLASSNOTAVAILABLE));
}
// Make sure that the interface id that is being requested is a valid one i.e. IID_IClassFactory
if( !IsEqualIID (riid, IID_IClassFactory) ) {
return(ResultFromScode (E_NOINTERFACE));
}
// create a new class factory ... ( here we associate the CLSID to object of a type )
CServerClassFactory *pClassFactory = new CServerClassFactory ();
// Verify .. was the class factory created ?
if( pClassFactory == NULL ) {
// Nope ! Return an ERROR !
return(ResultFromScode (E_OUTOFMEMORY));
}
// Get the interface pointer from QueryInterface and copy it to *ppv.
// The required type of riid is automatically being passed in ....
HRESULT hr = pClassFactory->QueryInterface (riid, ppv);
pClassFactory->Release ();
return(hr);
}
/*------------------------------------------------------------ DllCanUnloadNow
** DllCanUnloadNow
*
* PARAMETERS : None
*
* DESCRIPTION : DllCanUnloadNow is called by the shell to find out if the DLL can be
* unloaded. The answer is yes if (and only if) the module reference count
* stored in gcRefServerDll is 0.
This Dll can be unloaded if and only if :
a) All the in process servers that it "spawns" can be unloaded and
b) Its own reference count is down to zero
* RETURNS : HRESULT code equal to S_OK if the DLL can be unloaded, S_FALSE if not
* AUTHOR : Guru Datta Venkatarama
* 01/30/97 08:24:21 (PST)
*
------------------------------------------------------------*/
STDAPI DllCanUnloadNow(void)
{
// %%% debug %%% implement / verify complex condition for return value ( lock servers actually )
return((gcRefServerDll == 0) ? S_OK : S_FALSE);
}
/*------------------------------------------------------------ CServerClassFactory::CServerClassFactory
** CServerClassFactory Member Functions
*
* DESCRIPTION : This is the implementation of the standard member functions of the
Server's class factory.
*
* AUTHOR : Guru Datta Venkatarama
* 01/30/97 08:30:18 (PST)
*
------------------------------------------------------------*/
// constructor ..
CServerClassFactory::CServerClassFactory(void)
{
m_ServerCFactory_refcount = 0; // was 1;
AddRef();
// increment the dll refcount
InterlockedIncrement(&gcRefServerDll);
}
// ----------------------------------------------------------- CServerClassFactory::~CServerClassFactory
// destructor ..
CServerClassFactory::~CServerClassFactory(void)
{
// decrement the dll refcount
InterlockedDecrement(&gcRefServerDll);
}
// ----------------------------------------------------------- CServerClassFactory::QueryInterface
STDMETHODIMP CServerClassFactory::QueryInterface(
REFIID riid,
PPVOID ppv)
{
// Reflexive Response - return our own base Interface class pointer cast appropriately
if( IsEqualIID(riid, IID_IUnknown) ) {
*ppv = (LPUNKNOWN) (LPCLASSFACTORY) this;
} else {
// Reflexive Response - return our own class pointer
if( IsEqualIID(riid, IID_IClassFactory) ) {
*ppv = (LPCLASSFACTORY) this;
} else {
// unsupported interface requested for
*ppv = NULL;
return(ResultFromScode (E_NOINTERFACE));
}
}
// add reference count every time a pointer is provided
AddRef();
return(NOERROR);
}
// ----------------------------------------------------------- CServerClassFactory::AddRef
STDMETHODIMP_(ULONG)CServerClassFactory::AddRef(void)
{
InterlockedIncrement((LPLONG)&m_ServerCFactory_refcount);
return(m_ServerCFactory_refcount);
}
// ----------------------------------------------------------- CServerClassFactory::Release
STDMETHODIMP_(ULONG)CServerClassFactory::Release(void)
{
InterlockedDecrement((LPLONG)&m_ServerCFactory_refcount);
if( m_ServerCFactory_refcount == 0 ) {
delete this;
return(0);
} else {
return(m_ServerCFactory_refcount);
}
}
// -----------------------------------------------------------
/*------------------------------------------------------------ CServerClassFactory::CreateInstance
** CServerClassFactory::CreateInstance
*
* PARAMETERS : pUnkOuter = Pointer to controlling unknown
* riid = Reference to interface ID specifier
* ppvObj = Pointer to location to receive interface pointer
* DESCRIPTION : CreateInstance is the class factory implementation.
* It is called by the client to create the IServerCharacterstics interface
* It is called by the members of the IServerCharacteristics interface
* viz CreatePropertySheet and CreateDiagnostics to create the
* appropriate interfaces for each.
*
* RETURNS : HRESULT code signifying success or failure
*
* AUTHOR : Guru Datta Venkatarama
* 01/31/97 09:29:36 (PST)
*
------------------------------------------------------------*/
STDMETHODIMP CServerClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, PPVOID ppvObj)
{
*ppvObj = NULL;
HRESULT hr=S_OK;
// We don't support aggregation at this time!
if( pUnkOuter != NULL )
return(ResultFromScode(CLASS_E_NOAGGREGATION));
// Instantiate a class factory object of the appropriate type and retrieve its pointer.
if( IsEqualIID(riid, IID_IDIGameCntrlPropSheet) ) {
LPCDIGAMECNTRLPROPSHEET pCServerProperty = new CDIGameCntrlPropSheet();
if( pCServerProperty == NULL ) {
return(ResultFromScode(E_OUTOFMEMORY));
} else {
// Get the interface pointer from QueryInterface and copy it to *ppvObj.
hr = pCServerProperty->QueryInterface(riid, ppvObj);
// add the reference and count to the parent in order to support "containment"
// pCServerProperty->AddRef();
// drop a refcount created by the constructor on the server property object
pCServerProperty->Release ();
}
} else return(ResultFromScode (E_NOINTERFACE));
return(hr);
}
/*------------------------------------------------------------ CServerClassFactory::LockServer
** CServerClassFactory::LockServer
*
* PARAMETERS :
*
* DESCRIPTION : LockServer increments or decrements the DLL's lock count.
*
* RETURNS :
*
* AUTHOR : Guru Datta Venkatarama
* 01/31/97 18:40:17 (PST)
* IMPLIMENTOR : Brycej 08/04/97
*
------------------------------------------------------------*/
STDMETHODIMP CServerClassFactory::LockServer(BOOL fLock)
{
HRESULT hRes = E_NOTIMPL;
// increment/decrement based on fLock
if( fLock ) {
// increment the dll refcount
InterlockedIncrement(&gcRefServerDll);
} else {
// decrement the dll refcount
InterlockedDecrement(&gcRefServerDll);
}
// all done
return(hRes);
}
// -----------------------------------------------------------
//****************************************************************************************************
//********************************* **********************************
//****************************************************************************************************
// ----------------------------------------------------------- CImpIServerProperty::CImpIServerProperty
// constructor ..
CDIGameCntrlPropSheet::CDIGameCntrlPropSheet(void)
{
m_cProperty_refcount = 0;
AddRef();
m_nID = -1;
// increment the dll refcount
InterlockedIncrement(&gcRefServerDll);
}
// ----------------------------------------------------------- CImpIServerProperty::~CImpIServerProperty
// destructor ..
CDIGameCntrlPropSheet::~CDIGameCntrlPropSheet(void)
{
// decrement the dll refcount
InterlockedDecrement(&gcRefServerDll);
}
// ----------------------------------------------------------- CImpIServerProperty::QueryInterface
STDMETHODIMP CDIGameCntrlPropSheet::QueryInterface(
REFIID riid,
PPVOID ppv)
{
// Reflexive Response - return our own base Interface class pointer cast appropriately
if( IsEqualIID(riid, IID_IUnknown) ) {
*ppv = (LPUNKNOWN) (LPCLASSFACTORY) this;
} else {
// Reflexive Response - return our own class pointer
if( IsEqualIID(riid, IID_IDIGameCntrlPropSheet) ) {
*ppv = (LPCLASSFACTORY) this;
} else {
// unsupported interface requested for
*ppv = NULL;
return(ResultFromScode (E_NOINTERFACE));
}
}
// add reference count every time a pointer is provided
AddRef();
return(NOERROR);
}
// ----------------------------------------------------------- CImpIServerProperty::AddRef
STDMETHODIMP_(ULONG)CDIGameCntrlPropSheet::AddRef(void)
{
// update and return our object's reference count
InterlockedIncrement((LPLONG)&m_cProperty_refcount);
return(m_cProperty_refcount);
}
// ----------------------------------------------------------- CImpIServerProperty::Release
STDMETHODIMP_(ULONG)CDIGameCntrlPropSheet::Release(void)
{
// update and return our object's reference count
InterlockedDecrement((LPLONG)&m_cProperty_refcount);
if( m_cProperty_refcount == 0 ) {
delete this;
return(0);
} else {
return(m_cProperty_refcount);
}
}
// ----------------------------------------------------------- CImpIServerProperty::ReportSheetStats
STDMETHODIMP CDIGameCntrlPropSheet::GetSheetInfo(LPDIGCSHEETINFO *svrshtptr)
{
// pass the pointer back to the caller
*svrshtptr =(LPDIGCSHEETINFO) &sheet_info;
// return
return(S_OK);
}
// ----------------------------------------------------------- CImpIServerProperty::ReportPageStats
STDMETHODIMP CDIGameCntrlPropSheet::GetPageInfo(LPDIGCPAGEINFO * svrpagptr)
{
pjd = JoystickDataInit();
if( pjd == NULL ) {
*svrpagptr = NULL;
return(E_FAIL);
}
jdp.pjd = pjd;
page_info[0].lParam = (LPARAM) &jdp;
// pass pages information report structure pointer back to the caller
*svrpagptr = (LPDIGCPAGEINFO)page_info;
// return
return(S_OK);
}
STDMETHODIMP CDIGameCntrlPropSheet::SetID(USHORT nID)
{
gnID = m_nID = nID;
return(S_OK);
}
/*
// ----------------------------------------------------------
BOOL SetDialogItemText( HWND hdlg, UINT nctrl, UINT nstr )
{
CString * pszDialogString= new CString;
ASSERT(pszDialogString);
if(pszDialogString)
{
pszDialogString->LoadString(nstr);
SetDlgItemText( hdlg, nctrl, (LPCTSTR)*pszDialogString);
if (pszDialogString)
delete(pszDialogString);
return(TRUE);
}
if (pszDialogString)
delete (pszDialogString);
return(FALSE);
}
*/
// ----------------------------------------------------------
LRESULT SetJoyInfo(UINT nID, LPCSTR szOEMKey)
{
if( !strcmp(szOEMKey, "Microsoft SideWinder 3D Pro") )
fIsSideWinder = 1;
jdp.iJoyId = gnID;
gpgv = &pjd->pgvlist[gnID];
return(NOERROR);
}
// -------------------------------------------------------------------------------EOF