home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / MFC / SRC / APPCORE.CP_ / APPCORE.CP
Encoding:
Text File  |  1993-02-08  |  21.3 KB  |  787 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and Microsoft
  7. // QuickHelp and/or WinHelp documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11.  
  12. #include "stdafx.h"
  13. #include <malloc.h>
  14.  
  15. #include "penwin.h"     // MFC Apps are PenAware by default
  16.  
  17. #ifdef AFX_CORE1_SEG
  18. #pragma code_seg(AFX_CORE1_SEG)
  19. #endif
  20.  
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // Define global state in ordinary "C" globals
  28.  
  29. #ifndef _AFXDLL
  30. extern "C"
  31. {
  32. CWinApp* NEAR afxCurrentWinApp = NULL;
  33. HINSTANCE NEAR afxCurrentInstanceHandle = NULL;
  34. HINSTANCE NEAR afxCurrentResourceHandle = NULL;
  35. const char* NEAR afxCurrentAppName = NULL;
  36. }
  37. HBRUSH NEAR afxDlgBkBrush = NULL;
  38. COLORREF NEAR afxDlgTextClr = (COLORREF)-1; // not set
  39. #else //_AFXDLL
  40.  
  41. // use macros for inline access to stack globals
  42. #define afxCurrentWinApp (_AfxGetAppData()->appCurrentWinApp)
  43. #define afxCurrentInstanceHandle (_AfxGetAppData()->appCurrentInstanceHandle)
  44. #define afxCurrentResourceHandle (_AfxGetAppData()->appCurrentResourceHandle)
  45. #define afxCurrentAppName (_AfxGetAppData()->appCurrentAppName)
  46. extern BOOL WINAPI _AfxAppDataInit();       // from 'dllinit.cpp'
  47. extern void WINAPI _AfxAppDataTerm();       // from 'dllinit.cpp'
  48.  
  49. #endif //_AFXDLL
  50.  
  51. /////////////////////////////////////////////////////////////////////////////
  52. // other globals (internal library use)
  53.  
  54. IMPLEMENT_DYNAMIC(CWinApp, CCmdTarget)
  55.  
  56. #ifndef _USRDLL
  57. static void (CALLBACK* _afxRegisterPenAppProc)(UINT, BOOL);
  58. #endif //!_USRDLL
  59.  
  60. ///////////////////////////////////////////////////////////////////////////
  61.  
  62. #ifdef _DEBUG
  63. void CWinApp::AssertValid() const
  64. {
  65.     CObject::AssertValid();
  66.     ASSERT(afxCurrentWinApp == this);
  67.     ASSERT(afxCurrentInstanceHandle == m_hInstance);
  68.  
  69.     POSITION pos = m_templateList.GetHeadPosition();
  70.     while (pos)
  71.     {
  72.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  73.         ASSERT_VALID(pTemplate);
  74.     }
  75. }
  76.  
  77. void CWinApp::Dump(CDumpContext& dc) const
  78. {
  79.     CCmdTarget::Dump(dc);
  80.  
  81.     AFX_DUMP1(dc, "\nm_hInstance = ", (UINT)m_hInstance);
  82.     AFX_DUMP1(dc, "\nm_hPrevInstance = ", (UINT)m_hPrevInstance);
  83.     AFX_DUMP1(dc, "\nm_lpCmdLine = ", m_lpCmdLine);
  84.     AFX_DUMP1(dc, "\nm_nCmdShow = ", m_nCmdShow);
  85.     AFX_DUMP1(dc, "\nm_pMainWnd = ", m_pMainWnd);
  86.     AFX_DUMP1(dc, "\nm_pszAppName = ", m_pszAppName);
  87.     AFX_DUMP1(dc, "\nm_bHelpMode = ", m_bHelpMode);
  88.     AFX_DUMP1(dc, "\nm_pszExeName = ", m_pszExeName);
  89.     AFX_DUMP1(dc, "\nm_pszHelpFilePath = ", m_pszHelpFilePath);
  90.     AFX_DUMP1(dc, "\nm_pszProfileName = ", m_pszProfileName);
  91.     AFX_DUMP1(dc, "\nm_hDevMode = ", (UINT)m_hDevMode);
  92.     AFX_DUMP1(dc, "\nm_hDevNames = ", (UINT)m_hDevNames);
  93.     AFX_DUMP1(dc, "\nm_dwPromptContext = ", m_dwPromptContext);
  94.  
  95.     AFX_DUMP0(dc, "\nm_strRecentFiles[] = ");
  96.     for (int i = 0; i < _AFX_MRU_COUNT; i++)
  97.     {
  98.         if (m_strRecentFiles[i].GetLength() != 0)
  99.             AFX_DUMP1(dc, "\n\tFile: ", m_strRecentFiles[i]);
  100.     }
  101.  
  102.     AFX_DUMP1(dc, "\nm_nWaitCursorCount = ", m_nWaitCursorCount);
  103.     AFX_DUMP1(dc, "\nm_hcurWaitCursorRestore = ", (UINT)m_hcurWaitCursorRestore);
  104.     AFX_DUMP1(dc, "\nm_hcurHelp = ", (UINT)m_hcurHelp);
  105.     AFX_DUMP1(dc, "\nm_nNumPreviewPages = ", m_nNumPreviewPages);
  106.     AFX_DUMP0(dc, "\nm_templateList[] = {");
  107.  
  108.     AFX_DUMP0(dc, "\nm_msgCur = {");
  109.     AFX_DUMP1(dc, "\n\thwnd = ", (UINT)m_msgCur.hwnd);
  110.     AFX_DUMP1(dc, "\n\tmessage = ", (UINT)m_msgCur.message);
  111.     AFX_DUMP1(dc, "\n\twParam = ", (UINT)m_msgCur.wParam);
  112.     AFX_DUMP1(dc, "\n\tlParam = ", (void FAR*)m_msgCur.lParam);
  113.     AFX_DUMP1(dc, "\n\ttime = ", m_msgCur.time);
  114.     AFX_DUMP1(dc, "\n\tpt = ", CPoint(m_msgCur.pt));
  115.     AFX_DUMP0(dc, "}");
  116.  
  117.     if (dc.GetDepth() == 0)
  118.         return;
  119.  
  120.     POSITION pos = m_templateList.GetHeadPosition();
  121.     while (pos)
  122.     {
  123.         CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  124.         AFX_DUMP1(dc, "\n", pTemplate);
  125.     }
  126.     AFX_DUMP0(dc, "}");
  127. }
  128. #endif
  129.  
  130. ///////////////////////////////////////////////////////////////////////////
  131. // Initialization
  132.  
  133. #ifdef AFX_INIT_SEG
  134. #pragma code_seg(AFX_INIT_SEG)
  135. #endif
  136.  
  137. void CWinApp::SetCurrentHandles()
  138. {
  139.     ASSERT(this == afxCurrentWinApp);
  140.     ASSERT(afxCurrentInstanceHandle == NULL);
  141.     ASSERT(afxCurrentResourceHandle == NULL);
  142.     ASSERT(afxCurrentAppName == NULL);
  143.  
  144.     afxCurrentInstanceHandle = m_hInstance; // for instance tagging
  145.     afxCurrentResourceHandle = m_hInstance; // for resource loading
  146.  
  147.     // get path of executable
  148.     char szBuff[_MAX_PATH+1];
  149.     VERIFY(::GetModuleFileName(m_hInstance, szBuff, _MAX_PATH));
  150.  
  151.     int nLen = strlen(szBuff);
  152.     ASSERT(nLen > 4 && szBuff[nLen-4] == '.');  // must end in .EXE
  153.     nLen -= 4;
  154.     szBuff[nLen] = '\0';        // no suffix
  155.  
  156.     // get path of .HLP file
  157.     if (m_pszHelpFilePath == NULL)
  158.     {
  159.         static char BASED_CODE szHlp[] = ".HLP";
  160.         lstrcat(szBuff, szHlp);
  161.         m_pszHelpFilePath = _strdup(szBuff);
  162.         szBuff[nLen] = '\0';        // back to no suffix
  163.     }
  164.  
  165.     // get the exe title from the full path name [no extension]
  166.     char szExeName[_MAX_PATH];
  167.     VERIFY(::GetFileTitle(szBuff, szExeName, _MAX_PATH) == 0);
  168.     if (m_pszExeName == NULL)
  169.         m_pszExeName = _strdup(szExeName); // save non-localized name
  170.  
  171.     if (m_pszProfileName == NULL)
  172.     {
  173.         static char BASED_CODE szIni[] = ".INI";
  174.         lstrcat(szExeName, szIni);     // will be enough room in buffer
  175.         m_pszProfileName = _strdup(szExeName);
  176.     }
  177.  
  178.     // m_pszAppName is the name used to present to the user
  179.     if (m_pszAppName == NULL)
  180.     {
  181.         char szTitle[256];
  182.         if (_AfxLoadString(AFX_IDS_APP_TITLE, szTitle))
  183.             m_pszAppName = _strdup(szTitle);             // human readable title
  184.         else
  185.             m_pszAppName = _strdup(m_pszExeName);       // same as EXE
  186.     }
  187.  
  188.     afxCurrentAppName = m_pszAppName;
  189.     ASSERT(afxCurrentAppName != NULL);
  190. }
  191.  
  192.  
  193. CWinApp::CWinApp(const char* pszAppName)
  194. {
  195.     m_pszAppName = pszAppName;
  196.     // in non-running state until WinMain
  197.     m_hInstance = NULL;
  198.     m_pMainWnd = NULL;
  199.     m_pszHelpFilePath = NULL;
  200.     m_pszProfileName = NULL;
  201.     m_pszExeName = NULL;
  202.     m_atomApp = m_atomSystemTopic = NULL;
  203.     m_nSafetyPoolSize = 512;        // default size
  204.     m_pSafetyPoolBuffer = NULL;     // get's allocated in idle
  205.  
  206.     ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
  207.     afxCurrentWinApp = this; // hook for WinMain
  208.  
  209. #ifdef _DEBUG
  210.     m_nDisablePumpCount = 0;
  211. #endif
  212.  
  213.     m_nWaitCursorCount = 0;
  214.     m_hcurWaitCursorRestore = NULL;
  215.  
  216.     m_hDevMode = NULL;
  217.     m_hDevNames = NULL;
  218.  
  219.     m_nNumPreviewPages = 0;     // not specified (defaults to 1)
  220.     m_lpfnCleanupVBXFiles = NULL;   // Will be set by LoadVBXFile if VBX linked
  221.  
  222.     m_hcurHelp = NULL;
  223.     m_bHelpMode = FALSE;
  224. }
  225.  
  226.  
  227. BOOL CWinApp::InitApplication()
  228. {
  229.     return TRUE;
  230. }
  231.  
  232. BOOL CWinApp::InitInstance()
  233. {
  234.     return TRUE;
  235. }
  236.  
  237. /////////////////////////////////////////////////////////////////////////////
  238. // App termination
  239.  
  240. #ifdef AFX_INIT_SEG     // init as well as termination code in 1 segment
  241. #pragma code_seg(AFX_INIT_SEG)
  242. #endif
  243.  
  244. CWinApp::~CWinApp()
  245. {
  246.     // for cleanup - delete all document templates
  247.     while (!m_templateList.IsEmpty())
  248.         delete (CDocTemplate*)m_templateList.RemoveHead();
  249.     m_templateList.RemoveAll(); // clean up list overhead
  250.     for (int iMRU = 0; iMRU < _AFX_MRU_COUNT; iMRU++)
  251.         m_strRecentFiles[iMRU].Empty();
  252.  
  253.     // free printer info
  254.     if (m_hDevMode != NULL)
  255.         ::GlobalFree(m_hDevMode);
  256.     if (m_hDevNames != NULL)
  257.         ::GlobalFree(m_hDevNames);
  258.  
  259.     // free atoms if used
  260.     if (m_atomApp != NULL)
  261.         ::GlobalDeleteAtom(m_atomApp);
  262.     if (m_atomSystemTopic != NULL)
  263.         ::GlobalDeleteAtom(m_atomSystemTopic);
  264. }
  265.  
  266. int CWinApp::ExitInstance()
  267. {
  268.     SaveStdProfileSettings();
  269.     return m_msgCur.wParam; // Returns the value from PostQuitMessage
  270. }
  271.  
  272. /////////////////////////////////////////////////////////////////////////////
  273.  
  274. #ifdef AFX_CORE1_SEG
  275. #pragma code_seg(AFX_CORE1_SEG)
  276. #endif
  277.  
  278. BOOL CWinApp::PumpMessage()
  279. {
  280. #ifdef _DEBUG
  281.     if (m_nDisablePumpCount != 0)
  282.     {
  283.         TRACE0("Error: CWinApp::PumpMessage() called when not permitted\n");
  284.         ASSERT(FALSE);
  285.     }
  286. #endif
  287.  
  288.     if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
  289.     {
  290. #ifdef _DEBUG
  291.         if (afxTraceFlags & 2)
  292.             TRACE0("PumpMessage - Received WM_QUIT\n");
  293.         m_nDisablePumpCount++; // application must die
  294.             // NOTE: prevents calling message loop things in 'ExitInstance'
  295.             // will never be decremented
  296. #endif
  297.         return FALSE;
  298.     }
  299.  
  300. #ifdef _DEBUG
  301.     if (afxTraceFlags & 2)
  302.         _AfxTraceMsg("PumpMessage", &m_msgCur);
  303. #endif
  304.  
  305.     // process this message
  306.     if (!PreTranslateMessage(&m_msgCur))
  307.     {
  308.         ::TranslateMessage(&m_msgCur);
  309.         ::DispatchMessage(&m_msgCur);
  310.     }
  311.     return TRUE;
  312. }
  313.  
  314. // Main running routine until application exits
  315. int CWinApp::Run()
  316. {
  317.     if (m_pMainWnd == NULL)
  318.     {
  319.         TRACE0("Warning: 'm_pMainWnd' is NULL in CWinApp::Run"
  320.                 " - quitting application\n");
  321.         ::PostQuitMessage(0);
  322.     }
  323.  
  324. #ifdef _DEBUG
  325.     if (!afxData.bWin31 && !afxData.bWin30Compat)
  326.     {
  327.         TRACE0("Warning: running program under Win3.0 but without the\n"
  328.             "  'AfxEnableWin30Compatibility()' API being called\n"
  329.             "  Program may not behave correctly under Win3.1\n"
  330.             "  Please refer to MFC Technical Note TN034\n");
  331.     }
  332. #endif //_DEBUG
  333.  
  334.     // Acquire and dispatch messages until a WM_QUIT message is received.
  335.     for (; ;)
  336.     {
  337.         LONG lIdleCount = 0;
  338.         // check to see if we can do idle work
  339.         while (!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE) &&
  340.             OnIdle(lIdleCount++))
  341.         {
  342.             // more work to do
  343.         }
  344.  
  345.         // either we have a message, or OnIdle returned false
  346.  
  347.         if (!PumpMessage())
  348.             break;
  349.     }
  350.  
  351.     return ExitInstance();
  352. }
  353.  
  354. /////////////////////////////////////////////////////////////////////////////
  355. // Stubs for standard implementation
  356.  
  357. static BOOL PASCAL IsHelpKey(LPMSG lpMsg)
  358.     // return TRUE only for non-repeat F1 keydowns.
  359. {
  360.     return lpMsg->message == WM_KEYDOWN &&
  361.            lpMsg->wParam == VK_F1 &&
  362.            !(HIWORD(lpMsg->lParam) & KF_REPEAT) &&
  363.            GetKeyState(VK_SHIFT) >= 0 &&
  364.            GetKeyState(VK_CONTROL) >= 0 &&
  365.            GetKeyState(VK_MENU) >= 0;
  366. }
  367.  
  368. BOOL CWinApp::PreTranslateMessage(MSG* pMsg)
  369. {
  370.     HWND hWnd;
  371.     CWnd* pWnd;
  372.  
  373.     // walk from the target window up to the desktop window checking
  374.     //  if any window wants to translate this message
  375.     for (hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
  376.     {
  377.         if ((pWnd = CWnd::FromHandlePermanent(hWnd)) != NULL)
  378.         {
  379.             // target window is a C++ window
  380.             if (pWnd->PreTranslateMessage(pMsg))
  381.                 return TRUE; // trapped by target window (eg: accelerators)
  382.  
  383.             if (pWnd == m_pMainWnd)
  384.                 return FALSE;       // got to our main window without interest
  385.         }
  386.     }
  387.  
  388.     // in case of modeless dialogs, last chance route through main window's
  389.     //   accelerator table
  390.     if (m_pMainWnd != NULL && m_pMainWnd->PreTranslateMessage(pMsg))
  391.         return TRUE; // trapped by main window (eg: accelerators)
  392.  
  393.     return FALSE;       // no special processing
  394. }
  395.  
  396.  
  397. /////////////////////////////////////////////////////////////////////////////
  398. // Message Filter processing
  399.  
  400. #ifndef _AFXDLL
  401. static HHOOK NEAR _afxHHookOldMsgFilter = NULL;
  402. #else
  403. #define _afxHHookOldMsgFilter _AfxGetAppData()->appHHookOldMsgFilter
  404. #endif
  405.  
  406. #ifndef _USRDLL
  407. LRESULT CALLBACK AFX_EXPORT
  408. _AfxMsgFilterHook(int code, WPARAM wParam, LPARAM lParam)
  409.     // filter for WH_MSGFILTER
  410. {
  411.     if (code < 0)
  412.     {
  413.         if (!afxData.bWin31)
  414.         {
  415. #ifdef STRICT
  416.             return ::DefHookProc(code, wParam, lParam, &_afxHHookOldMsgFilter);
  417. #else
  418.             return ::DefHookProc(code, wParam, lParam,
  419.                 (HOOKPROC FAR*)&_afxHHookOldMsgFilter);
  420. #endif
  421.         }
  422.         else
  423.         {
  424.             return ::CallNextHookEx(_afxHHookOldMsgFilter, code, wParam, lParam);
  425.         }
  426.     }
  427.  
  428.     ASSERT(wParam == 0);
  429.     return (LRESULT)AfxGetApp()->ProcessMessageFilter(code, (LPMSG)lParam);
  430. }
  431. #endif //!_USRDLL
  432.  
  433. static inline BOOL IsEnterKey(LPMSG lpMsg)
  434. {
  435.     return lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_RETURN;
  436. }
  437.  
  438. static inline BOOL IsButtonUp(LPMSG lpMsg)
  439. {
  440.     return lpMsg->message == WM_LBUTTONUP;
  441. }
  442.  
  443. BOOL CWinApp::ProcessMessageFilter(int code, LPMSG lpMsg)
  444. {
  445.     switch (code)
  446.     {
  447.     case MSGF_MENU:
  448.         if (m_bHelpMode && m_pMainWnd != NULL &&
  449.             lpMsg != NULL && lpMsg->hwnd != NULL)
  450.         {
  451.             CFrameWnd* pFrame =
  452.                 (CFrameWnd*)CWnd::FromHandlePermanent(lpMsg->hwnd);
  453.             if (pFrame != NULL && IsEnterKey(lpMsg) || IsButtonUp(lpMsg))
  454.             {
  455.                 if (!pFrame->IsKindOf(RUNTIME_CLASS(CFrameWnd)) ||
  456.                     !pFrame->IsTracking())
  457.                 {
  458.                     // only frame windows that are tracking have Shift+F1
  459.                     // help support.
  460.                     break;
  461.                 }
  462.                 m_pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
  463.                 return TRUE;
  464.             }
  465.         }
  466.         // fall through...
  467.  
  468.     case MSGF_DIALOGBOX:    // handles message boxes as well.
  469.         if (m_pMainWnd != NULL &&
  470.             lpMsg != NULL && IsHelpKey(lpMsg))
  471.         {
  472.             m_pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
  473.             return TRUE;
  474.         }
  475.         break;
  476.     }
  477.  
  478.     return FALSE;   // default to not handled
  479. }
  480.  
  481. // called when exception not caught in a WndProc
  482. LRESULT CWinApp::ProcessWndProcException(CException* e, const MSG* pMsg)
  483. {
  484.     if (pMsg->message == WM_CREATE)
  485.     {
  486.         return -1;  // just fail
  487.     }
  488.     else if (pMsg->message == WM_PAINT)
  489.     {
  490.         // force validation of window to prevent getting WM_PAINT again
  491.         ValidateRect(pMsg->hwnd, NULL);
  492.         return 0;
  493.     }
  494.  
  495.     UINT nIDP = AFX_IDP_INTERNAL_FAILURE;   // generic message string
  496.     LRESULT lResult = 0;        // sensible default
  497.     if (pMsg->message == WM_COMMAND && (HWND)LOWORD(pMsg->lParam) == NULL)
  498.     {
  499.         nIDP = AFX_IDP_COMMAND_FAILURE; // command (not from a control)
  500.         lResult = (LRESULT)TRUE;        // pretend the command was handled
  501.     }
  502.  
  503.     if (!e->IsKindOf(RUNTIME_CLASS(CUserException)))
  504.     {
  505.         // user has not been alerted yet of this somewhat catastrophic problem
  506.         AfxMessageBox(nIDP, MB_ICONSTOP);
  507.     }
  508.  
  509.     return lResult; // sensible default return from most WndProc functions
  510. }
  511.  
  512. /////////////////////////////////////////////////////////////////////////////
  513. // CWinApp idle processing
  514.  
  515. BOOL CWinApp::OnIdle(LONG lCount)
  516. {
  517.     if (lCount == 0)
  518.     {
  519.         // update command buttons etc from the top down
  520.         if (m_pMainWnd != NULL)
  521.             m_pMainWnd->SendMessageToDescendants(WM_IDLEUPDATECMDUI,
  522.                 (WPARAM)TRUE);
  523.         return TRUE;        // more to do
  524.     }
  525.     else if (lCount == 1)
  526.     {
  527.         // clean up temp objects etc
  528.         if (m_lpfnCleanupVBXFiles != NULL)
  529.             (*m_lpfnCleanupVBXFiles)();
  530.  
  531.         CGdiObject::DeleteTempMap();
  532.         CDC::DeleteTempMap();
  533.         CMenu::DeleteTempMap();
  534.         CWnd::DeleteTempMap();
  535.  
  536. #ifndef _PORTABLE
  537.         // Safety Pool memory allocation for critical low memory
  538.  
  539.         // restore safety pool after temp objects destroyed
  540.         while ((m_pSafetyPoolBuffer == NULL ||
  541.            _msize(m_pSafetyPoolBuffer) < m_nSafetyPoolSize) &&
  542.           m_nSafetyPoolSize != 0)
  543.         {
  544.             // attempt to restore the safety pool to it's max size
  545.             size_t nOldSize = 0;
  546.             if (m_pSafetyPoolBuffer != NULL)
  547.             {
  548.                 nOldSize = _msize(m_pSafetyPoolBuffer);
  549.                 free(m_pSafetyPoolBuffer);
  550.             }
  551.  
  552.             // undo handler trap for the following allocation
  553.             _PNH pnhOldHandler = _AfxSetNewHandler(NULL);
  554.             if ((m_pSafetyPoolBuffer = malloc(m_nSafetyPoolSize)) == NULL)
  555.             {
  556.                 TRACE1("Warning: failed to reclaim %d bytes"
  557.                     " for memory safety pool\n", m_nSafetyPoolSize);
  558.                 // at least get the old buffer back
  559.                 if (nOldSize != 0)
  560.                 {
  561.                     m_pSafetyPoolBuffer = malloc(nOldSize);
  562.                     ASSERT(m_pSafetyPoolBuffer != NULL);    //get it back
  563.                 }
  564.             }
  565.             _AfxSetNewHandler(pnhOldHandler);
  566.         }
  567. #endif // !_PORTABLE
  568.  
  569.         return TRUE;        // more to do
  570.     }
  571.  
  572.     return FALSE;   // no more processing (sleep please)
  573. }
  574.  
  575. /////////////////////////////////////////////////////////////////////////////
  576. // Standard init called by WinMain
  577.  
  578. #ifdef AFX_INIT_SEG
  579. #pragma code_seg(AFX_INIT_SEG)
  580. #endif
  581.  
  582. static BOOL NEAR PASCAL RegisterWithIcon(WNDCLASS* pWndCls,
  583.     const char* pszClassName, UINT nIDIcon)
  584. {
  585.     pWndCls->lpszClassName = pszClassName;
  586.     if ((pWndCls->hIcon = ::LoadIcon(pWndCls->hInstance,
  587.       MAKEINTRESOURCE(nIDIcon))) == NULL)
  588.     {
  589.         // use default icon
  590.         pWndCls->hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
  591.     }
  592.     return RegisterClass(pWndCls);
  593. }
  594.  
  595. /////////////////////////////////////////////////////////////////////////////
  596.  
  597. extern "C"
  598. BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  599.     LPSTR lpCmdLine, int nCmdShow)
  600. {
  601.     CWinApp* pApp = AfxGetApp();
  602.     ASSERT(pApp != NULL);   // must have one CWinApp derived object defined
  603.  
  604. #ifdef _AFXDLL
  605.     if (!_AfxAppDataInit())
  606.         return FALSE;
  607. #endif
  608.  
  609.     // shared initialization
  610. #ifndef _USRDLL
  611.     HINSTANCE hPenWin;
  612.     if ((hPenWin = (HINSTANCE)GetSystemMetrics(SM_PENWINDOWS)) != NULL)
  613.     {
  614.         static char BASED_CODE szRegisterPenApp[] = "RegisterPenApp";
  615.         _afxRegisterPenAppProc = (void (CALLBACK*)(UINT, BOOL))
  616.             ::GetProcAddress(hPenWin, szRegisterPenApp);
  617.     }
  618. #endif //!_USRDLL
  619.  
  620.     // fill in the initial state for the application
  621.     pApp->m_hInstance = hInstance;
  622.     pApp->m_hPrevInstance = hPrevInstance;
  623.     pApp->m_lpCmdLine = lpCmdLine;
  624.     pApp->m_nCmdShow = nCmdShow;
  625.     pApp->SetCurrentHandles();
  626.  
  627.     // Windows version specific initialization
  628. #ifndef _USRDLL
  629.     if (!afxData.bWin31)
  630.     {
  631.         // set message filter proc
  632.         _afxHHookOldMsgFilter = (HHOOK)::SetWindowsHook(WH_MSGFILTER,
  633.             (HOOKPROC)_AfxMsgFilterHook);
  634.     }
  635.     else
  636.     {
  637.         // set message filter proc
  638.         _afxHHookOldMsgFilter = ::SetWindowsHookEx(WH_MSGFILTER,
  639.             (HOOKPROC)_AfxMsgFilterHook,
  640.             _AfxGetHookHandle(), ::GetCurrentTask());
  641.     }
  642. #endif //!_USRDLL
  643.  
  644.     if (hPrevInstance == NULL)  // one instance initialization
  645.     {
  646.         // register basic WndClasses
  647.         WNDCLASS wndcls;
  648.         memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults
  649.  
  650.         // common initialization
  651.         wndcls.lpfnWndProc = AfxWndProc;
  652.         wndcls.hInstance = hInstance;
  653.         wndcls.hCursor = afxData.hcurArrow;
  654.  
  655.         // Child windows - no brush, no icon, safest default class styles
  656.         wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  657.         wndcls.lpszClassName = _afxWnd;
  658.         if (!::RegisterClass(&wndcls))
  659.             return FALSE;
  660.  
  661.         // Control bar windows
  662.         wndcls.style = 0;   // control bars don't handle double click
  663.         wndcls.lpszClassName = _afxWndControlBar;
  664.         wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  665.         if (!::RegisterClass(&wndcls))
  666.             return FALSE;
  667.  
  668.         // MDI Frame window (also used for splitter window)
  669.         wndcls.style = CS_DBLCLKS;
  670.         wndcls.hbrBackground = NULL;
  671.         if (!RegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
  672.             return FALSE;
  673.  
  674.         // SDI Frame or MDI Child windows or views - normal colors
  675.         wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  676.         wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  677.         if (!RegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
  678.             return FALSE;
  679.     }
  680.  
  681. #ifndef _USRDLL
  682.     // Register as a Pen aware app if penwindows installed
  683.     if (_afxRegisterPenAppProc != NULL)
  684.         (*_afxRegisterPenAppProc)(RPA_DEFAULT, TRUE);
  685. #endif //!_USRDLL
  686.  
  687.     // Handle critical errors ourself
  688.     ::SetErrorMode(SEM_FAILCRITICALERRORS);
  689.  
  690.     return TRUE;
  691. }
  692.  
  693.  
  694. extern "C"
  695. void AFXAPI AfxWinTerm(void)
  696. {
  697. #ifndef _AFXDLL
  698.     // These static CWnd objects refer to HWNDs that don't exist
  699.     // so let's not call ::DestroyWindow when CWnd::~CWnd() is invoked.
  700.     ((CWnd&)CWnd::wndTop).m_hWnd = NULL;
  701.     ((CWnd&)CWnd::wndBottom).m_hWnd = NULL;
  702.     ((CWnd&)CWnd::wndTopMost).m_hWnd = NULL;
  703.     ((CWnd&)CWnd::wndNoTopMost).m_hWnd = NULL;
  704. #else
  705.     _AfxAppDataTerm();
  706. #endif //_AFXDLL
  707.  
  708. #ifndef _USRDLL
  709.     // if we registered ourself with PenWin, deregister now
  710.     if (_afxRegisterPenAppProc != NULL)
  711.     {
  712.         (*_afxRegisterPenAppProc)(RPA_DEFAULT, FALSE);
  713.         _afxRegisterPenAppProc = NULL;
  714.     }
  715.  
  716.     if (afxDlgBkBrush != NULL)
  717.     {
  718.         ::DeleteObject(afxDlgBkBrush);
  719.         afxDlgBkBrush = NULL;
  720.     }
  721.  
  722.     if (_afxHHookOldMsgFilter != NULL)
  723.     {
  724.         if (!afxData.bWin31)
  725.             ::UnhookWindowsHook(WH_MSGFILTER, (HOOKPROC)_AfxMsgFilterHook);
  726.         else
  727.             ::UnhookWindowsHookEx(_afxHHookOldMsgFilter);
  728.         _afxHHookOldMsgFilter = NULL;
  729.     }
  730.  
  731.     if (_afxHHookOldCbtFilter != NULL)
  732.     {
  733.         ASSERT(afxData.bWin31);
  734.         ::UnhookWindowsHookEx(_afxHHookOldCbtFilter);
  735.         _afxHHookOldCbtFilter = NULL;
  736.     }
  737. #endif //!_USRDLL
  738. }
  739.  
  740. /////////////////////////////////////////////////////////////////////////////
  741. // force WinMain or LibMain inclusion
  742.  
  743. #ifdef _WINDLL      // any DLL
  744. extern "C" int PASCAL LibMain(HINSTANCE, WORD, WORD, LPSTR);
  745. static FARPROC linkAddr = (FARPROC) LibMain;
  746. #else
  747. extern "C" int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
  748. static FARPROC linkAddr = (FARPROC) WinMain;
  749. #endif //!_WINDLL
  750.  
  751. /////////////////////////////////////////////////////////////////////////////
  752.  
  753. #ifdef _USRDLL
  754.  
  755. #ifdef AFX_CORE1_SEG
  756. #pragma code_seg()
  757. #endif
  758.  
  759. extern "C" int CALLBACK _WEP(int);
  760. #pragma alloc_text(WEP_TEXT, _WEP)
  761.  
  762. extern "C" int CALLBACK _WEP(int)
  763. {
  764. #ifdef _DEBUG
  765.     if (!afxData.bWin31)
  766.     {
  767.         // AfxTrace() may cause Windows to fault under 3.0 when called from
  768.         // inside the WEP, so it is disabled while executing WEP code.
  769.         afxTraceEnabled = FALSE;
  770.     }
  771. #endif
  772.  
  773.     TRACE0("Inside of MFC-supplied _WEP, calling (virtual) CWinApp::ExitInstance\n");
  774.  
  775.     // NOTE: An application should be careful not to use too much stack space
  776.     //  in the ExitInstance function.  Under Windows 3.0, the WEP is called
  777.     //  on a very small stack owned by the kernel.
  778.     //  Calling Windows USER functions, in particular, is not advised.
  779.     AfxGetApp()->ExitInstance();
  780.  
  781.     // Now it is safe to cleanup the library.
  782.     AfxWinTerm();
  783.  
  784.     return TRUE;
  785. }
  786. #endif //_USRDLL
  787.