/* File: main.cpp Project: Universal Joystick Control Panel OLE Client Author: Brycej Date: 02/28/95 Comments: Copyright (c) 1995, Microsoft Corporation */ //#pragma pack (8) #include #include #include "cpanel.h" #include "resource.h" // Windows bug 578471 -- remove from server //#include "creditst.h" // for the Credit Dialog! #define JOYSTICK_CPL 0 #define MAX_CPL_PAGES 6 HINSTANCE ghInstance; extern WCHAR *pwszTypeArray[MAX_DEVICES]; extern WCHAR *pwszGameportDriverArray[MAX_GLOBAL_PORT_DRIVERS]; extern WCHAR *pwszGameportBus[MAX_BUSSES]; // List of enumerated gameport buses extern BYTE nGamingDevices; // Gaming Devices Enumeration Counter extern BYTE nGameportDriver; // Global Port Driver Enumeration Counter extern BYTE nGameportBus; // Gameport Bus Enumeration Counter extern short nFlags; // State Flags the CPL defined in CPANEL.H static void AddPage(LPPROPSHEETHEADER ppsh, short nTemplateID, int nTabID, DLGPROC pfn); static void DoProperties(HWND hWnd, UINT nStartPage); void WINAPI ShowJoyCPL(HWND); void ParseArgs(HWND hDlg, LPTSTR lpArgList); INT_PTR CALLBACK SplashDialogProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam); // From AppMan.cpp //extern HRESULT AppManInit(); // Windows bug 578471 -- remove from server // From Retrocfg.cpp //extern HRESULT DVoiceCPLInit(); //extern INT_PTR CALLBACK RetrofitProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); //extern INT_PTR RetrofitDestroyHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); BYTE nID, nStartPageDef, nStartPageCPL; BOOL WINAPI DllMain(HANDLE hModule, ULONG uReason, LPVOID pv) { switch( uReason ) { case DLL_PROCESS_ATTACH: ghInstance = (HINSTANCE)hModule; // needed because CEdit will Assert without this line!!! afxCurrentInstanceHandle = ghInstance; afxCurrentResourceHandle = ghInstance; break; // case DLL_PROCESS_DETACH: // ClearArrays(); case DLL_THREAD_ATTACH: DisableThreadLibraryCalls((HMODULE)hModule); case DLL_THREAD_DETACH: break; } return(TRUE); } /* function: CPlApplet() comments: Entry point for control panel applets. */ LONG WINAPI CPlApplet(HWND hWnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2) { switch( uMsg ) { case CPL_INIT: return(1); case CPL_GETCOUNT: return(1); case CPL_INQUIRE: ((LPCPLINFO)lParam2)->idIcon = IDI_CPANEL; ((LPCPLINFO)lParam2)->idName = IDS_GEN_CPANEL_TITLE; ((LPCPLINFO)lParam2)->idInfo = IDS_GEN_CPANEL_INFO; ((LPCPLINFO)lParam2)->lData = 0; return(1); case CPL_DBLCLK: nID = (NUMJOYDEVS<<1); // Applet icon double clicked -- invoke property sheet with // The first property sheet page on top. DoProperties(hWnd, 0); break; /* * This function requires Windows 2000. Not available on Win9x. */ case CPL_STARTWPARMS: // Same as CPL_DBLCLK, but lParam2 is a long pointer to // a string of extra directions that are to be supplied to // the property sheet that is to be initiated. // The arguments are as follows: // @nCPLDialog Index, nStartPageCPL, nStartPageDef // Don't do anything if there are no arguments! if( *(LPTSTR)lParam2 ) ParseArgs(hWnd, (LPTSTR)lParam2); return(TRUE); // return non-zero to indicate message handled case CPL_EXIT: case CPL_STOP: break; } return(0); } /* Function: DoProperties(HWND hWnd, UINT nStartPage) Arguements: hWnd - Handle to Main Window nStartPage - Page number to start */ static void DoProperties(HWND hWnd, UINT nStartPage) { static HWND hPrevHwnd; static HANDLE hMutex = CreateMutex(NULL, TRUE, MUTEX_NAME); if( GetLastError() == ERROR_ALREADY_EXISTS ) { SetForegroundWindow(hPrevHwnd); } else { hPrevHwnd = hWnd; nFlags = (GetVersion() < 0x80000000) ? ON_NT : 0; HPROPSHEETPAGE *pPages = new (HPROPSHEETPAGE[MAX_CPL_PAGES]); ASSERT (pPages); LPPROPSHEETHEADER ppsh = new (PROPSHEETHEADER); ASSERT(ppsh); ZeroMemory(ppsh, sizeof(PROPSHEETHEADER)); ppsh->dwSize = sizeof(PROPSHEETHEADER); ppsh->dwFlags = PSH_NOAPPLYNOW | PSH_USEICONID; ppsh->hwndParent = hWnd; ppsh->hInstance = ghInstance; ppsh->pszCaption = MAKEINTRESOURCE(IDS_GEN_CPANEL_TITLE); ppsh->pszIcon = MAKEINTRESOURCE(IDI_CPANEL); ppsh->nStartPage = nStartPage; ppsh->phpage = pPages; AddPage(ppsh, IDD_CPANEL, IDS_GENERAL_TAB, CPanelProc); AddPage(ppsh, IDD_ADVANCED, IDS_ADVANCED_TAB, AdvancedProc); // Windows bug 578471 -- remove from server // if( SUCCEEDED ( DVoiceCPLInit() )) { // AddPage(ppsh, IDD_PROP_RETROFIT, IDS_DVOICE_TAB, RetrofitProc); // } // if( SUCCEEDED ( AppManInit() ) ) { // AddPage(ppsh, IDD_APPMAN, IDS_APPMAN_TAB, AppManProc); // AddPage(ppsh, IDD_APPMAN_LOCKING, IDS_APPMANLOCK_TAB, AppManLockProc); // } #ifdef SYMANTIC_MAPPER AddPage(ppsh, IDD_SMAPPER, ID_SMAPPER_TAB, SMapperProc); #endif // SYMANTIC_MAPPER // trap for return... VERIFY(PropertySheet(ppsh) != -1); if( pPages ) delete[] (pPages); if( ppsh ) delete (ppsh); ReleaseMutex(hMutex); CloseHandle(hMutex); // Windows bug 578471 -- remove from server // Ensure voice is always cleaned up //RetrofitDestroyHandler( NULL, 0, 0, 0 ); ClearArrays(); } } static void AddPage(LPPROPSHEETHEADER ppsh, short nTemplateID, int nTabID, DLGPROC pfn) { if( ppsh->nPages < MAX_CPL_PAGES ) { LPPROPSHEETPAGE ppsp = new (PROPSHEETPAGE); ASSERT(ppsp); ZeroMemory(ppsp, sizeof(PROPSHEETPAGE)); ppsp->dwSize = sizeof(PROPSHEETPAGE); ppsp->pszTitle = MAKEINTRESOURCE(nTabID); ppsp->hInstance = ghInstance; ppsp->pfnDlgProc = pfn; ppsp->pszTemplate = MAKEINTRESOURCE(nTemplateID); ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(ppsp); if( ppsp ) delete (ppsp); if( ppsh->phpage[ppsh->nPages] ) ppsh->nPages++; } } // AddPage // DO NOT REMOVE THIS!!! // This is here because the games group loads the CPL from the exported function // If you remove this Hellbender, Monster Truck Maddness, CART, etc will fail to // load the Joystick CPL!!! // DO NOT REMOVE THIS!!! void WINAPI ShowJoyCPL(HWND hWnd) { nID = (NUMJOYDEVS<<1); DoProperties(hWnd, 0); } void LaunchExtention(HWND hWnd) { // These are defined in CPANEL.CPP extern LPDIRECTINPUT lpDIInterface; extern IDirectInputJoyConfig* pDIJoyConfig; HRESULT hr = DirectInputCreate(ghInstance, DIRECTINPUT_VERSION, &lpDIInterface, NULL); if( FAILED(hr) ) return; // Call CreateJoyConfigInterface! if( SUCCEEDED(lpDIInterface->QueryInterface(IID_IDirectInputJoyConfig, (LPVOID*)&pDIJoyConfig)) ) { // Create a pJoy and populate it's GUID from GetTypeInfo PJOY pJoy = new (JOY); ASSERT (pJoy); pJoy->ID = nID; DIJOYCONFIG_DX5 JoyConfig; JoyConfig.dwSize = sizeof (DIJOYCONFIG_DX5); if( SUCCEEDED(pDIJoyConfig->GetConfig(nID, (LPDIJOYCONFIG)&JoyConfig, DIJC_REGHWCONFIGTYPE)) ) { LPDIJOYTYPEINFO_DX5 pdiJoyTypeInfo = new (DIJOYTYPEINFO_DX5); ASSERT (pdiJoyTypeInfo); pdiJoyTypeInfo->dwSize = sizeof (DIJOYTYPEINFO_DX5); hr = pDIJoyConfig->GetTypeInfo(JoyConfig.wszType, (LPDIJOYTYPEINFO)pdiJoyTypeInfo, DITC_CLSIDCONFIG); if( !IsEqualIID(pdiJoyTypeInfo->clsidConfig, GUID_NULL) ) pJoy->clsidPropSheet = pdiJoyTypeInfo->clsidConfig; if( pdiJoyTypeInfo ) delete (pdiJoyTypeInfo); } if( SUCCEEDED(hr) ) Launch(hWnd, pJoy, nStartPageDef); if( pJoy ) delete (pJoy); // release the DI JoyConfig interface pointer if( pDIJoyConfig ) { pDIJoyConfig->Release(); pDIJoyConfig = 0; } } // release the DI Device interface pointer if( lpDIInterface ) { lpDIInterface->Release(); lpDIInterface = 0; } } void ParseArgs(HWND hDlg, LPTSTR lpArgList) { BOOL bShowCPL = TRUE; // Check for '-', as they may not want to show the CPL! if( *lpArgList == '-' ) { bShowCPL = FALSE; *lpArgList++; } nStartPageCPL = nStartPageCPL = nStartPageDef = 0; // parse command line for nStartPageCPL! while( *lpArgList && (*lpArgList != ',') ) { nStartPageCPL *= 10; nStartPageCPL += *lpArgList++ - '0'; } // check to make sure nStartPageCPL is within range! if( bShowCPL ) { if( nStartPageCPL > MAX_CPL_PAGES ) { #ifdef _DEBUG OutputDebugString(TEXT("JOY.CPL: Command line requested an invalid start page, reset to default!\n")); #endif // NUMJOYDEVS is used to send the user to the Add dialog on start-up! if( nStartPageCPL != NUMJOYDEVS ) nStartPageCPL = 0; } } // Only continue if you have something further to parse! if( *lpArgList == ',' ) { *lpArgList++; nID = 0; // Parse for ID's while( *lpArgList && (*lpArgList != ',') ) { nID *= 10; nID += *lpArgList++ - '0'; } // Check for error cases! if( (nID < 1) || (nID > NUMJOYDEVS) ) { #ifdef _DEBUG OutputDebugString(TEXT("JOY.CPL: Command line Device ID out of range!\n")); #endif nID = (NUMJOYDEVS<<1); return; } // Decrement to internal zero based ID nID--; // Don't parse what you don't have! if( *lpArgList == ',' ) { *lpArgList++; // Lastly, parse for nStartPageDef! while( *lpArgList && (*lpArgList != ',') ) { nStartPageDef *= 10; nStartPageDef += *lpArgList++ - '0'; } } } else { nID = (NUMJOYDEVS<<1); } // Done with the parsing... // Time to get to work! // if we're not showing the CPL... if( !bShowCPL ) { // check to make sure the next value is a 1 // we may want to have further negative arguments :) switch( nStartPageCPL ) { case 1: // Invalid ID... if( nID > NUMJOYDEVS ) return; LaunchExtention(hDlg); break; #ifdef WE_CAN_HAVE_CREDITS case 60: // If they ask for the splash, they don't get the CPL! DialogBox( ghInstance, (PTSTR)IDD_SPLASH, hDlg, SplashDialogProc ); break; #endif } } else { DoProperties(NULL, nStartPageCPL); } } #ifdef WE_CAN_HAVE_CREDITS INT_PTR CALLBACK SplashDialogProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam) { static CCreditStatic *pStatic; switch( uMsg ) { case WM_INITDIALOG: { pStatic = new (CCreditStatic); ASSERT (pStatic); CWnd *pCWnd = new (CWnd); ASSERT (pCWnd); pCWnd->Attach(hDlg); pStatic->SubclassDlgItem(IDC_MYSTATIC, pCWnd); if( pCWnd ) { pCWnd->Detach(); delete (pCWnd); pCWnd = 0; } LPTSTR lpStr = new (TCHAR[MAX_STR_LEN]); ASSERT (lpStr); // The Credits come in two lines! BYTE nStrLen = (BYTE)LoadString(ghInstance, IDS_SPLASH, lpStr, MAX_STR_LEN); LoadString(ghInstance, IDS_SPLASH1, &lpStr[nStrLen], MAX_STR_LEN-nStrLen); pStatic->SetCredits(lpStr); if( lpStr ) { delete[] (lpStr); lpStr = 0; } pStatic->StartScrolling(); } return(TRUE); // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE} case WM_COMMAND: switch( LOWORD(wParam) ) { case IDOK: EndDialog(hDlg, LOWORD(wParam)); break; } break; // case WM_TIMER: //SendDlgItemMessage(hDlg, IDC_STATIC, WM_TIMER, 0, 0); // pStatic->OnTimer(150); //DISPLAY_TIMER_ID // break; case WM_DESTROY: if( pStatic ) { delete (pStatic); pStatic = 0; } break; } return(0); } #endif