virtual int Run() { if (bRun) { #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); _ASSERTE(SUCCEEDED(hRes)); hRes = CoResumeClassObjects(); #else hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE); #endif _ASSERTE(SUCCEEDED(hRes)); INITCOMMONCONTROLSEX iccex; iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); iccex.dwICC = ICC_COOL_CLASSES; InitCommonControlsEx(&iccex); { EditableRegistry::RegisterEditable<Bumper>(); EditableRegistry::RegisterEditable<Decal>(); EditableRegistry::RegisterEditable<DispReel>(); EditableRegistry::RegisterEditable<Flasher>(); EditableRegistry::RegisterEditable<Flipper>(); EditableRegistry::RegisterEditable<Gate>(); EditableRegistry::RegisterEditable<Kicker>(); EditableRegistry::RegisterEditable<Light>(); EditableRegistry::RegisterEditable<LightSeq>(); EditableRegistry::RegisterEditable<Plunger>(); EditableRegistry::RegisterEditable<Primitive>(); EditableRegistry::RegisterEditable<Ramp>(); EditableRegistry::RegisterEditable<Rubber>(); EditableRegistry::RegisterEditable<Spinner>(); EditableRegistry::RegisterEditable<Surface>(); EditableRegistry::RegisterEditable<Textbox>(); EditableRegistry::RegisterEditable<Timer>(); EditableRegistry::RegisterEditable<Trigger>(); EditableRegistry::RegisterEditable<HitTarget>(); } g_pvp = new VPinball(); g_pvp->AddRef(); g_pvp->Init(); g_haccel = LoadAccelerators(g_hinst, MAKEINTRESOURCE(IDR_VPACCEL)); if (fFile) { bool lf = true; if (szTableFileName[0] != '\0') g_pvp->LoadFileName(szTableFileName); else lf = g_pvp->LoadFile(); if (fPlay && lf) g_pvp->DoPlay(); if (fPov && lf) g_pvp->Quit(); } // VBA APC handles message loop (bastards) g_pvp->MainMsgLoop(); g_pvp->Release(); DestroyAcceleratorTable(g_haccel); _Module.RevokeClassObjects(); Sleep(THREADS_PAUSE); //wait for any threads to finish } return 0; }
extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int /*nShowCmd*/) { #ifdef CRASH_HANDLER rde::CrashHandler::Init(); #endif // disable auto-rotate on tablets #if (WINVER <= 0x0601) SetDisplayAutoRotationPreferences = (pSDARP) GetProcAddress(GetModuleHandle(TEXT("user32.dll")), "SetDisplayAutoRotationPreferences"); if(SetDisplayAutoRotationPreferences) SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_LANDSCAPE); #else SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_LANDSCAPE); #endif g_hinst = hInstance; #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED); #else HRESULT hRes = CoInitialize(NULL); #endif _ASSERTE(SUCCEEDED(hRes)); _Module.Init(ObjectMap, hInstance, &LIBID_VPinballLib); bool fFile = false; bool fPlay = false; bool bRun = true; TCHAR szTableFileName[_MAX_PATH] = {0}; int nRet = 0; int nArgs; LPSTR *szArglist = CommandLineToArgvA(GetCommandLine(), &nArgs); for(int i=0; i < nArgs; ++i) { if (lstrcmpi(szArglist[i], _T("-UnregServer"))==0 || lstrcmpi(szArglist[i], _T("/UnregServer"))==0) { _Module.UpdateRegistryFromResource(IDR_VPINBALL, FALSE); nRet = _Module.UnregisterServer(TRUE); bRun = false; break; } if (lstrcmpi(szArglist[i], _T("-RegServer"))==0 || lstrcmpi(szArglist[i], _T("/RegServer"))==0) { _Module.UpdateRegistryFromResource(IDR_VPINBALL, TRUE); nRet = _Module.RegisterServer(TRUE); bRun = false; break; } const bool editfile = (lstrcmpi(szArglist[i], _T("-Edit"))==0 || lstrcmpi(szArglist[i], _T("/Edit"))==0); const bool playfile = (lstrcmpi(szArglist[i], _T("-Play"))==0 || lstrcmpi(szArglist[i], _T("/Play"))==0); if ((editfile || playfile) && (i+1 < nArgs)) { fFile = true; fPlay = playfile; // Remove leading - or / char* filename; if((szArglist[i+1][0] == '-') || (szArglist[i+1][0] == '/')) filename = szArglist[i+1]+1; else filename = szArglist[i+1]; // Remove " " if(filename[0] == '"') { strcpy_s(szTableFileName,filename+1); szTableFileName[lstrlen(szTableFileName)] = '\0'; } else strcpy_s(szTableFileName,filename); // Add current path char szLoadDir[MAX_PATH]; if(szTableFileName[1] != ':') { GetCurrentDirectory(MAX_PATH,szLoadDir); strcat_s(szLoadDir,"\\"); strcat_s(szLoadDir,szTableFileName); strcpy_s(szTableFileName,szLoadDir); } else // Or set from table path if(playfile) { PathFromFilename(szTableFileName, szLoadDir); SetCurrentDirectory(szLoadDir); } if(playfile) VPinball::SetOpenMinimized(); break; } } free(szArglist); // load and register VP type library for COM integration char szFileName[_MAX_PATH]; if (GetModuleFileName(hInstance, szFileName, _MAX_PATH)) { ITypeLib *ptl = NULL; MAKE_WIDEPTR_FROMANSI(wszFileName, szFileName); if (SUCCEEDED(LoadTypeLib(wszFileName, &ptl))) { // first try to register system-wide (if running as admin) HRESULT hr = RegisterTypeLib(ptl, wszFileName, NULL); if (!SUCCEEDED(hr)) { // if failed, register only for current user hr = RegisterTypeLibForUser(ptl, wszFileName, NULL); if (!SUCCEEDED(hr)) MessageBox(0, "Could not register type library. Try running Visual Pinball as administrator.", "Error", MB_ICONWARNING); } ptl->Release(); } else MessageBox(0, "Could not load type library.", "Error", MB_ICONSTOP); } if (bRun) { #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); _ASSERTE(SUCCEEDED(hRes)); hRes = CoResumeClassObjects(); #else hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE); #endif _ASSERTE(SUCCEEDED(hRes)); INITCOMMONCONTROLSEX iccex; iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); iccex.dwICC = ICC_COOL_CLASSES; InitCommonControlsEx(&iccex); { EditableRegistry::RegisterEditable<Bumper>(); EditableRegistry::RegisterEditable<Decal>(); EditableRegistry::RegisterEditable<DispReel>(); EditableRegistry::RegisterEditable<Flasher>(); EditableRegistry::RegisterEditable<Flipper>(); EditableRegistry::RegisterEditable<Gate>(); EditableRegistry::RegisterEditable<Kicker>(); EditableRegistry::RegisterEditable<Light>(); EditableRegistry::RegisterEditable<LightSeq>(); EditableRegistry::RegisterEditable<Plunger>(); EditableRegistry::RegisterEditable<Primitive>(); EditableRegistry::RegisterEditable<Ramp>(); EditableRegistry::RegisterEditable<Rubber>(); EditableRegistry::RegisterEditable<Spinner>(); EditableRegistry::RegisterEditable<Surface>(); EditableRegistry::RegisterEditable<Textbox>(); EditableRegistry::RegisterEditable<Timer>(); EditableRegistry::RegisterEditable<Trigger>(); } g_pvp = new VPinball(); g_pvp->AddRef(); g_pvp->Init(); g_haccel = LoadAccelerators(g_hinst,MAKEINTRESOURCE(IDR_VPACCEL)); if (fFile) { g_pvp->LoadFileName(szTableFileName); if (fPlay) g_pvp->DoPlay(); } // VBA APC handles message loop (bastards) g_pvp->MainMsgLoop(); g_pvp->Release(); DestroyAcceleratorTable(g_haccel); _Module.RevokeClassObjects(); Sleep(dwPause); //wait for any threads to finish } _Module.Term(); CoUninitialize(); #ifdef _CRTDBG_MAP_ALLOC #ifdef DEBUG_XXX //disable this in perference to DevPartner _CrtSetDumpClient(MemLeakAlert); #endif _CrtDumpMemoryLeaks(); #endif //SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF ); return nRet; }
DWORD OPCEngine::mainOPCThread(void) { DWORD ret; BOOL end = FALSE; try { _TRACE(TL_INF, TG_ENG, (_T("started engine thread"))); //-- initialize engine thread -- _TRACE(TL_DEB, TG_ENG, (_T("COM initialize (multithreaded)"))); HRESULT res = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); if( FAILED(res)) { _ERROR(TG_ENG, OPCENGINE_ERR_COM,(_T("Can't initialize COM: 0x%X"), res)); return res; } if (m_type == OutProc) { _TRACE(TL_DEB, TG_ENG, (_T("register class objects"))); _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE); } //-- wait till engine termiantion -- while (!end) { ret = ::WaitForMultipleObjects(2, m_events, FALSE, m_clientCheckInterval); switch (ret - WAIT_OBJECT_0) { case END_EVENT: { // end event end = TRUE; _TRACE(TL_DEB, TG_ENG, (_T("received end event"))); } break; case SHUTDOWN_EVENT: { // shutdown event OPCShutdownRequest *sreq; _TRACE(TL_DEB, TG_ENG, (_T("received shutdown event"))); while(!m_shutdownList.IsEmpty()) { sreq = m_shutdownList.RemoveHead(); if (sreq->server) { sreq->server->sendShutdownRequest(sreq->reason); if (sreq->event != INVALID_HANDLE_VALUE) ::SetEvent(sreq->event); sreq->server->release(); } delete sreq; } } break; default: { // timeout //-- check client connections -- GenericList<GenericBranch> serverListCopy; POSITION posSrv; GenericServer *server; BOOL conOK; serverListCopy.create(); { GenericList<GenericBranch> serverList(m_opcRoot->getBranchList()); posSrv = serverList.getStartPosition(); while(posSrv) { server = (GenericServer *)serverList.getNext(posSrv); server->addRef(); serverListCopy.add(server); } } posSrv = serverListCopy.getStartPosition(); while(posSrv) { server = (GenericServer *)serverListCopy.getNext(posSrv); conOK = server->checkClientConnection(); if (!conOK) { server->disconnectClient(); } server->release(); } serverListCopy.free(); } break; } } //-- terminated engine -- if (m_type == OutProc) { _TRACE(TL_DEB, TG_ENG, (_T("revoke class objects"))); _Module.RevokeClassObjects(); } //-- disconnect all clients -- GenericList<GenericBranch> serverList(m_opcRoot->getBranchList()); POSITION posSrv; GenericServer *server; posSrv = serverList.getStartPosition(); while(posSrv) { server = (GenericServer *)serverList.getNext(posSrv); server->disconnectClient(); } serverList.unlock(); _TRACE(TL_DEB, TG_ENG, (_T("COM uninitialize"))); ::CoUninitialize(); _TRACE(TL_INF, TG_ENG, (_T("terminated engine thread"))); } catch(CException* e) { TCHAR excText[100]; CRuntimeClass* rt = e->GetRuntimeClass(); e->GetErrorMessage(excText, 100); _ERROR(TG_ENG, OPCENGINE_ERR_EXCEPTION,(_T("MFC EXCEPTION in OPC Engine Main Thread: %s (%s)"), rt->m_lpszClassName, excText)); return 1; } catch(...) { _ERROR(TG_ENG, OPCENGINE_ERR_EXCEPTION,(_T("EXCEPTION in OPC Engine Main Thread"))); return 1; } return S_OK; }