static void __clrcall _CrtDumpClient_managed_cleanup(void) { _CRT_DUMP_CLIENT pfnDumpClient=_CrtGetDumpClient(); _CRT_DUMP_CLIENT_M enull = (_CRT_DUMP_CLIENT_M) EncodePointer(NULL)(); if(pfnDumpClient==_CrtDumpClient_managed_thunk && __pfnDumpClientManaged!=enull) { _CrtSetDumpClient((_CRT_DUMP_CLIENT)NULL); } __pfnDumpClientManaged=enull; }
virtual ~VPApp() { _Module.Term(); CoUninitialize(); #ifdef _CRTDBG_MAP_ALLOC #ifdef DEBUG_XXX //disable this in perference to DevPartner _CrtSetDumpClient(MemLeakAlert); #endif _CrtDumpMemoryLeaks(); #endif }
_AFX_DEBUG_STATE::~_AFX_DEBUG_STATE() { #ifndef _AFX_NO_DEBUG_CRT _CrtDumpMemoryLeaks(); int nOldState = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); _CrtSetDbgFlag(nOldState & ~_CRTDBG_LEAK_CHECK_DF); _CrtSetReportHook(pfnOldCrtReportHook); _CrtSetDumpClient(pfnOldCrtDumpClient); #endif // _AFX_NO_DEBUG_CRT }
/*** *_CRT_DUMP_CLIENT_M _CrtSetDumpClient() - set client dump hook * *Purpose: * set client dump hook * *Entry: * _CRT_DUMP_CLIENT_M pfnNewHook - new dump hook * *Exit: * return previous hook * *Exceptions: * *******************************************************************************/ _MRTIMP _CRT_DUMP_CLIENT_M __cdecl _CrtSetDumpClient ( _CRT_DUMP_CLIENT_M pfnNewHook ) { if(_atexit_m_appdomain(_CrtDumpClient_managed_cleanup)!=0) { return NULL; } _CRT_DUMP_CLIENT_M pfnOldHook = (_CRT_DUMP_CLIENT_M) DecodePointer(__pfnDumpClientManaged); if (pfnNewHook) { __pfnDumpClientManaged = (_CRT_DUMP_CLIENT_M) EncodePointer(pfnNewHook); _CrtSetDumpClient((_CRT_DUMP_CLIENT)_CrtDumpClient_managed_thunk); } else { _CRT_DUMP_CLIENT_M enull = (_CRT_DUMP_CLIENT_M) EncodePointer(NULL)(); __pfnDumpClientManaged = enull; _CrtSetDumpClient((_CRT_DUMP_CLIENT)NULL); } return pfnOldHook; }
_AFX_DEBUG_STATE::_AFX_DEBUG_STATE() { afxTraceEnabled = ::GetPrivateProfileInt(szDiagSection, szTraceEnabled, TRUE, szIniFile); afxTraceFlags = ::GetPrivateProfileInt(szDiagSection, szTraceFlags, 0, szIniFile); #ifndef _AFX_NO_DEBUG_CRT ASSERT(pfnOldCrtDumpClient == NULL); pfnOldCrtDumpClient = _CrtSetDumpClient(_AfxCrtDumpClient); ASSERT(pfnOldCrtReportHook == NULL); pfnOldCrtReportHook = _CrtSetReportHook(_AfxCrtReportHook); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW); #endif // _AFX_NO_DEBUG_CRT }
BOOL __cdecl __CRTDLL_INIT( HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved ) { BOOL term_all = FALSE; if ( dwReason == DLL_PROCESS_ATTACH ) { if ( !_heap_init() ) /* initialize heap */ /* * The heap cannot be initialized, return failure to the * loader. */ return FALSE; if(!_mtinit()) /* initialize multi-thread */ { /* * If the DLL load is going to fail, we must clean up * all resources that have already been allocated. */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } if (_ioinit() < 0) { _mtterm(); /* free TLS index, call _mtdeletelocks() */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } _wcmdln = GetCommandLineW(); #if !defined(_CRT_APP) || defined(_KERNELX) _aenvptr = (char *)__crtGetEnvironmentStringsA(); _acmdln = GetCommandLineA(); #else /* !defined(_CRT_APP) || defined(_KERNELX) */ // We cannot call GetCommandLineA in the App CRT: if (!__copy_to_char(_wcmdln, &_acmdln)) { _acmdln = NULL; } #endif /* !defined(_CRT_APP) || defined(_KERNELX) */ #if !defined(_CRT_APP) || defined(_KERNELX) #ifdef _MBCS /* * Initialize multibyte ctype table. Always done since it is * needed for processing the environment strings. */ __initmbctable(); #endif /* _MBCS */ if (_setenvp() < 0 || /* get environ info */ _cinit(FALSE) != 0) /* do C data initialize */ { term_all = TRUE; } #else /* !defined(_CRT_APP) || defined(_KERNELX) */ if (_cinit(FALSE) != 0) /* do C data initialize */ { term_all = TRUE; } #endif /* !defined(_CRT_APP) || defined(_KERNELX) */ if (term_all) { #if defined(_CRT_APP) && !defined(_KERNELX) _free_crt(_acmdln); _acmdln = NULL; #endif _ioterm(); /* shut down lowio */ _mtterm(); /* free TLS index, call _mtdeletelocks() */ _heap_term(); /* heap is now invalid! */ return FALSE; /* fail DLL load on failure */ } /* * Increment flag indicating process attach notification * has been received. */ proc_attached++; } else if ( dwReason == DLL_PROCESS_DETACH ) { /* * if a client process is detaching, make sure minimal * runtime termination is performed and clean up our * 'locks' (i.e., delete critical sections). */ if ( proc_attached > 0 ) { proc_attached--; __try { /* * Any basic clean-up done here may also need * to be done below if Process Attach is partly * processed and then a failure is encountered. */ if ( _C_Termination_Done == FALSE ) _cexit(); __crtdll_callstaticterminators(); /* Free all allocated CRT memory */ __freeCrtMemory(); #ifdef _DEBUG /* Dump all memory leaks */ if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF) { _CrtSetDumpClient(NULL); _CrtDumpMemoryLeaks(); } #endif /* _DEBUG */ /* * What remains is to clean up the system resources we have * used (handles, critical sections, memory,...,etc.). This * needs to be done if the whole process is NOT terminating. */ /* If dwReason is DLL_PROCESS_DETACH, lpreserved is NULL * if FreeLibrary has been called or the DLL load failed * and non-NULL if the process is terminating. */ if ( lpreserved == NULL ) { #if defined(_CRT_APP) && !defined(_KERNELX) _free_crt(_acmdln); _acmdln = NULL; #endif /* * The process is NOT terminating so we must clean up... */ _ioterm(); /* free TLS index, call _mtdeletelocks() */ _mtterm(); /* This should be the last thing the C run-time does */ _heap_term(); /* heap is now invalid! */ } } __finally { /* we shouldn't really have to care about this, because letting an exception escape from DllMain(DLL_PROCESS_DETACH) should result in process termination. Unfortunately, Windows up to Win7 as of now just silently swallows the exception. I have considered all kinds of tricks, but decided to leave it up to OS folks to fix this. For the time being just remove our FLS callback during phase 2 unwind that would otherwise be left pointing to unmapped address space. */ if ( lpreserved == NULL && __flsindex != FLS_OUT_OF_INDEXES ) _mtterm(); } } else /* no prior process attach, just return */ return FALSE;
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; }