目的:快数定位全局对象的构造函数 类的虚函数表 MessageMap表
工具:IDA4.8 VC6SP6
1. Vc6迅速生成一个mfcdemo,基于dialog,整个程序由一个CWinApp子类和一个CDialog子类构成
2. 编译得到release\mfcdemo.exe
3. 给当前系统配置好symbol,用IDA4.80反汇编mfcdemo.exe
4. 通过IDA names页可以迅速找到下面这个表,显然,就是CWinApp子类的虚函数表。
没有名字的,就是没有找到符号的,为什么找不到?因为被我们重载了嘛。根据CWinApp的定义,
可以找到相关的被重载的虚汗数名字,注意:CWinApp<--CWinThread<--CCmdTarget<--CObject,虚汗数表需要从祖先分析起,然后累加
如CWinApp的虚函数表:
[this]
|
\|/
|--------
|foo11
|foo12 CObject的虚函数
|foo13
|--------
|foo21
|foo22 CCmdTarget的虚函数
|foo23
|--------
|foo31
|foo32 CWinThread的虚函数
|foo33
|--------
|foo41
|foo42 CWinApp的虚函数
|foo43
|--------
//CWinApp子类的虚函数表
.rdata:004021F8 off_4021F8 dd offset ?GetRuntimeClass@CWinApp@@UBEPAUCRuntimeClass@@XZ
.rdata:004021F8 ; DATA XREF: unknown_libname_1-56o
.rdata:004021F8 ; CWinApp::GetRuntimeClass(void)
.rdata:004021FC dd offset sub_401040 //析构函数
.rdata:00402200 dd offset nullsub_2 //Serialize
.rdata:00402204 dd offset nullsub_3 //AssertValid
.rdata:00402208 dd offset nullsub_2 //Dump
.rdata:0040220C dd offset ?OnCmdMsg@CCmdTarget@@UAEHIHPAXPAUAFX_CMDHANDLERINFO@@@Z ; CCmdTarget::OnCmdMsg(uint,int,void *,AFX_CMDHANDLERINFO *)
.rdata:00402210 dd offset ?OnFinalRelease@CCmdTarget@@UAEXXZ ; CCmdTarget::OnFinalRelease(void)
.rdata:00402214 dd offset ?IsInvokeAllowed@CCmdTarget@@UAEHJ@Z ; CCmdTarget::IsInvokeAllowed(long)
.rdata:00402218 dd offset ?GetDispatchIID@CCmdTarget@@UAEHPAU_GUID@@@Z ; CCmdTarget::GetDispatchIID(_GUID *)
.rdata:0040221C dd offset ?GetTypeInfoCount@CCmdTarget@@UAEIXZ ; CCmdTarget::GetTypeInfoCount(void)
.rdata:00402220 dd offset ?GetTypeLibCache@CCmdTarget@@UAEPAVCTypeLibCache@@XZ ; CCmdTarget::GetTypeLibCache(void)
.rdata:00402224 dd offset ?GetTypeLib@CCmdTarget@@UAEJKPAPAUITypeLib@@@Z ; CCmdTarget::GetTypeLib(ulong,ITypeLib * *)
.rdata:00402228 dd offset sub_401010 //GetMessageMap
.rdata:0040222C dd offset ?GetCommandMap@CCmdTarget@@MBEPBUAFX_OLECMDMAP@@XZ ; CCmdTarget::GetCommandMap(void)
.rdata:00402230 dd offset ?GetDispatchMap@CCmdTarget@@MBEPBUAFX_DISPMAP@@XZ ; CCmdTarget::GetDispatchMap(void)
.rdata:00402234 dd offset ?GetConnectionMap@CCmdTarget@@MBEPBUAFX_CONNECTIONMAP@@XZ ; CCmdTarget::GetConnectionMap(void)
.rdata:00402238 dd offset ?GetInterfaceMap@CCmdTarget@@MBEPBUAFX_INTERFACEMAP@@XZ ; CCmdTarget::GetInterfaceMap(void)
.rdata:0040223C dd offset ?GetEventSinkMap@CCmdTarget@@MBEPBUAFX_EVENTSINKMAP@@XZ ; CCmdTarget::GetEventSinkMap(void)
.rdata:00402240 dd offset ?OnCreateAggregates@CCmdTarget@@UAEHXZ ; CCmdTarget::OnCreateAggregates(void)
.rdata:00402244 dd offset ?GetInterfaceHook@CCmdTarget@@UAEPAUIUnknown@@PBX@Z ; CCmdTarget::GetInterfaceHook(void const *)
.rdata:00402248 dd offset ?GetExtraConnectionPoints@CCmdTarget@@MAEHPAVCPtrArray@@@Z ; CCmdTarget::GetExtraConnectionPoints(CPtrArray *)
.rdata:0040224C dd offset ?GetConnectionHook@CCmdTarget@@MAEPAUIConnectionPoint@@ABU_GUID@@@Z ; CCmdTarget::GetConnectionHook(_GUID const &)
.rdata:00402250 dd offset sub_4010B0 //InitInstance
.rdata:00402254 dd offset ?Run@CWinApp@@UAEHXZ ; CWinApp::Run(void)
.rdata:00402258 dd offset ?PreTranslateMessage@CWinThread@@UAEHPAUtagMSG@@@Z ; CWinThread::PreTranslateMessage(tagMSG *)
.rdata:0040225C dd offset ?PumpMessage@CWinThread@@UAEHXZ ; CWinThread::PumpMessage(void)
.rdata:00402260 dd offset ?OnIdle@CWinApp@@UAEHJ@Z ; CWinApp::OnIdle(long)
.rdata:00402264 dd offset ?IsIdleMessage@CWinThread@@UAEHPAUtagMSG@@@Z ; CWinThread::IsIdleMessage(tagMSG *)
.rdata:00402268 dd offset ?ExitInstance@CWinApp@@UAEHXZ ; CWinApp::ExitInstance(void)
.rdata:0040226C dd offset ?ProcessWndProcException@CWinApp@@UAEJPAVCException@@PBUtagMSG@@@Z ; CWinApp::ProcessWndProcException(CException *,tagMSG const *)
.rdata:00402270 dd offset ?ProcessMessageFilter@CWinThread@@UAEHHPAUtagMSG@@@Z ; CWinThread::ProcessMessageFilter(int,tagMSG *)
.rdata:00402274 dd offset ?GetMainWnd@CWinThread@@UAEPAVCWnd@@XZ ; CWinThread::GetMainWnd(void)
.rdata:00402278 dd offset ?Delete@CWinThread@@UAEXXZ ; CWinThread::Delete(void)
.rdata:0040227C dd offset ?OpenDocumentFile@CWinApp@@UAEPAVCDocument@@PBD@Z ; CWinApp::OpenDocumentFile(char const *)
.rdata:00402280 dd offset ?AddToRecentFileList@CWinApp@@UAEXPBD@Z ; CWinApp::AddToRecentFileList(char const *)
.rdata:00402284 dd offset ?InitApplication@CWinApp@@UAEHXZ ; CWinApp::InitApplication(void)
.rdata:00402288 dd offset ?SaveAllModified@CWinApp@@UAEHXZ ; CWinApp::SaveAllModified(void)
.rdata:0040228C dd offset ?DoMessageBox@CWinApp@@UAEHPBDII@Z ; CWinApp::DoMessageBox(char const *,uint,uint)
.rdata:00402290 dd offset ?DoWaitCursor@CWinApp@@UAEXH@Z ; CWinApp::DoWaitCursor(int)
.rdata:00402294 dd offset ?OnDDECommand@CWinApp@@UAEHPAD@Z ; CWinApp::OnDDECommand(char *)
.rdata:00402298 dd offset ?WinHelpA@CWinApp@@UAEXKI@Z ; CWinApp::WinHelpA(ulong,uint)
//CObject
#ifdef _AFXDLL
class CObject
#else
class AFX_NOVTABLE CObject
#endif
{
public:
// Object model (types, destruction, allocation)
virtual CRuntimeClass* GetRuntimeClass() const //虚函数,GetRuntimeClass
virtual ~CObject(); // virtual destructors are necessary //虚函数,~CObject
// Diagnostic allocations
void* PASCAL operator new(size_t nSize);
void* PASCAL operator new(size_t, void* p);
void PASCAL operator delete(void* p);
#if _MSC_VER >= 1200
void PASCAL operator delete(void* p, void* pPlace);
#endif
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
// for file name/line number tracking using DEBUG_NEW
void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#if _MSC_VER >= 1200
void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine);
#endif
#endif
// Disable the copy constructor and assignment by default so you will get
// compiler errors instead of unexpected behaviour if you pass objects
// by value or assign objects.
protected:
CObject();
private:
CObject(const CObject& objectSrc); // no implementation
void operator=(const CObject& objectSrc); // no implementation
// Attributes
public:
BOOL IsSerializable() const;
BOOL IsKindOf(const CRuntimeClass* pClass) const;
// Overridables
virtual void Serialize(CArchive& ar); //虚函数,Serialize
#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
virtual void AssertValid() const; //虚函数,AssertValid
virtual void Dump(CDumpContext& dc) const; //虚函数,Dump
#endif
// Implementation
public:
static const AFX_DATA CRuntimeClass classCObject;
#ifdef _AFXDLL
static CRuntimeClass* PASCAL _GetBaseClass();
#endif
};
//CCmdTarget
#ifdef _AFXDLL
class CCmdTarget : public CObject
#else
class AFX_NOVTABLE CCmdTarget : public CObject
#endif
{
DECLARE_DYNAMIC(CCmdTarget) //虚函数GetRuntimeClass,重载 [x]
protected:
public:
// Constructors
CCmdTarget();
// Attributes
LPDISPATCH GetIDispatch(BOOL bAddRef);
// retrieve IDispatch part of CCmdTarget
static CCmdTarget* PASCAL FromIDispatch(LPDISPATCH lpDispatch);
// map LPDISPATCH back to CCmdTarget* (inverse of GetIDispatch)
BOOL IsResultExpected();
// returns TRUE if automation function should return a value
// Operations
void EnableAutomation();
// call in constructor to wire up IDispatch
void EnableConnections();
// call in constructor to wire up IConnectionPointContainer
void BeginWaitCursor();
void EndWaitCursor();
void RestoreWaitCursor(); // call after messagebox
#ifndef _AFX_NO_OLE_SUPPORT
// dispatch OLE verbs through the message map
BOOL EnumOleVerbs(LPENUMOLEVERB* ppenumOleVerb);
BOOL DoOleVerb(LONG iVerb, LPMSG lpMsg, HWND hWndParent, LPCRECT lpRect);
#endif
// Overridables
// route and dispatch standard command message types
// (more sophisticated than OnCommand)
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, //虚函数,OnCmdMsg
AFX_CMDHANDLERINFO* pHandlerInfo);
#ifndef _AFX_NO_OLE_SUPPORT
// called when last OLE reference is released
virtual void OnFinalRelease(); //虚函数,OnFinalRelease
#endif
#ifndef _AFX_NO_OLE_SUPPORT
// called before dispatching to an automation handler function
virtual BOOL IsInvokeAllowed(DISPID dispid); //虚函数,IsInvokeAllowed
#endif
#ifndef _AFX_NO_OLE_SUPPORT
// support for OLE type libraries
void EnableTypeLib();
HRESULT GetTypeInfoOfGuid(LCID lcid, const GUID& guid,
LPTYPEINFO* ppTypeInfo);
virtual BOOL GetDispatchIID(IID* pIID);
virtual UINT GetTypeInfoCount();
virtual CTypeLibCache* GetTypeLibCache();
virtual HRESULT GetTypeLib(LCID lcid, LPTYPELIB* ppTypeLib); //虚函数,GetTypeLib
#endif
// Implementation
public:
virtual ~CCmdTarget(); //重载,[x]
#ifdef _DEBUG
virtual void Dump(CDumpContext& dc) const;
virtual void AssertValid() const;
#endif
#ifndef _AFX_NO_OLE_SUPPORT
void GetNotSupported();
void SetNotSupported();
#endif
protected:
friend class CView;
CView* GetRoutingView();
CFrameWnd* GetRoutingFrame();
static CView* PASCAL GetRoutingView_();
static CFrameWnd* PASCAL GetRoutingFrame_();
DECLARE_MESSAGE_MAP() // base class - no {{ }} macros //虚函数,GetMessageMap,会被子类重载的
#ifndef _AFX_NO_DOCOBJECT_SUPPORT
DECLARE_OLECMD_MAP()
friend class COleCmdUI;
#endif
#ifndef _AFX_NO_OLE_SUPPORT
DECLARE_DISPATCH_MAP()
DECLARE_CONNECTION_MAP()
DECLARE_INTERFACE_MAP()
#ifndef _AFX_NO_OCC_SUPPORT
DECLARE_EVENTSINK_MAP()
#endif // !_AFX_NO_OCC_SUPPORT
// OLE interface map implementation
public:
// data used when CCmdTarget is made OLE aware
long m_dwRef;
LPUNKNOWN m_pOuterUnknown; // external controlling unknown if != NULL
DWORD m_xInnerUnknown; // place-holder for inner controlling unknown
public:
// advanced operations
void EnableAggregation(); // call to enable aggregation
void ExternalDisconnect(); // forcibly disconnect
LPUNKNOWN GetControllingUnknown();
// get controlling IUnknown for aggregate creation
// these versions do not delegate to m_pOuterUnknown
DWORD InternalQueryInterface(const void*, LPVOID* ppvObj);
DWORD InternalAddRef();
DWORD InternalRelease();
// these versions delegate to m_pOuterUnknown
DWORD ExternalQueryInterface(const void*, LPVOID* ppvObj);
DWORD ExternalAddRef();
DWORD ExternalRelease();
// implementation helpers
LPUNKNOWN GetInterface(const void*);
LPUNKNOWN QueryAggregates(const void*);
// advanced overrideables for implementation
virtual BOOL OnCreateAggregates();
virtual LPUNKNOWN GetInterfaceHook(const void*);
// OLE automation implementation
protected:
struct XDispatch
{
DWORD m_vtbl; // place-holder for IDispatch vtable
#ifndef _AFX_NO_NESTED_DERIVATION
size_t m_nOffset;
#endif
} m_xDispatch;
BOOL m_bResultExpected;
// member variable-based properties
void GetStandardProp(const AFX_DISPMAP_ENTRY* pEntry,
VARIANT* pvarResult, UINT* puArgErr);
SCODE SetStandardProp(const AFX_DISPMAP_ENTRY* pEntry,
DISPPARAMS* pDispParams, UINT* puArgErr);
// DISPID to dispatch map lookup
static UINT PASCAL GetEntryCount(const AFX_DISPMAP* pDispMap);
const AFX_DISPMAP_ENTRY* PASCAL GetDispEntry(LONG memid);
static LONG PASCAL MemberIDFromName(const AFX_DISPMAP* pDispMap, LPCTSTR lpszName);
// helpers for member function calling implementation
static UINT PASCAL GetStackSize(const BYTE* pbParams, VARTYPE vtResult);
#ifdef _PPC_
SCODE PushStackArgs(BYTE* pStack, const BYTE* pbParams,
void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams,
UINT* puArgErr, VARIANT* rgTempVars, UINT nSizeArgs);
#else
SCODE PushStackArgs(BYTE* pStack, const BYTE* pbParams,
void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams,
UINT* puArgErr, VARIANT* rgTempVars);
#endif
SCODE CallMemberFunc(const AFX_DISPMAP_ENTRY* pEntry, WORD wFlags,
VARIANT* pvarResult, DISPPARAMS* pDispParams, UINT* puArgErr);
friend class COleDispatchImpl;
#ifndef _AFX_NO_OCC_SUPPORT
public:
// OLE event sink implementation
BOOL OnEvent(UINT idCtrl, AFX_EVENT* pEvent,
AFX_CMDHANDLERINFO* pHandlerInfo);
protected:
const AFX_EVENTSINKMAP_ENTRY* PASCAL GetEventSinkEntry(UINT idCtrl,
AFX_EVENT* pEvent);
#endif // !_AFX_NO_OCC_SUPPORT
// OLE connection implementation
struct XConnPtContainer
{
DWORD m_vtbl; // place-holder for IConnectionPointContainer vtable
#ifndef _AFX_NO_NESTED_DERIVATION
size_t m_nOffset;
#endif
} m_xConnPtContainer;
#ifdef _AFXDLL
AFX_MODULE_STATE* m_pModuleState;
friend class CInnerUnknown;
friend UINT APIENTRY _AfxThreadEntry(void* pParam);
#endif
virtual BOOL GetExtraConnectionPoints(CPtrArray* pConnPoints);
virtual LPCONNECTIONPOINT GetConnectionHook(const IID& iid);
friend class COleConnPtContainer;
#endif //!_AFX_NO_OLE_SUPPORT
};
//CWinThread
class CWinThread : public CCmdTarget
{
DECLARE_DYNAMIC(CWinThread)
public:
// Constructors
CWinThread();
BOOL CreateThread(DWORD dwCreateFlags = 0, UINT nStackSize = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
// Attributes
CWnd* m_pMainWnd; // main window (usually same AfxGetApp()->m_pMainWnd)
CWnd* m_pActiveWnd; // active main window (may not be m_pMainWnd)
BOOL m_bAutoDelete; // enables 'delete this' after thread termination
// only valid while running
HANDLE m_hThread; // this thread's HANDLE
operator HANDLE() const;
DWORD m_nThreadID; // this thread's ID
int GetThreadPriority();
BOOL SetThreadPriority(int nPriority);
// Operations
DWORD SuspendThread();
DWORD ResumeThread();
BOOL PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam);
// Overridables
// thread initialization
virtual BOOL InitInstance(); //虚函数,InitInstance
// running and idle processing
virtual int Run(); //虚函数,Run
virtual BOOL PreTranslateMessage(MSG* pMsg); //虚函数,PreTranslateMessage
virtual BOOL PumpMessage(); // low level message pump //虚函数,PumpMessage
virtual BOOL OnIdle(LONG lCount); // return TRUE if more idle processing //虚函数,OnIdle
virtual BOOL IsIdleMessage(MSG* pMsg); // checks for special messages //虚函数,IsIdleMessage
// thread termination
virtual int ExitInstance(); // default will 'delete this' //虚函数,ExitInstance
// Advanced: exception handling
virtual LRESULT ProcessWndProcException(CException* e, const MSG* pMsg);
// Advanced: handling messages sent to message filter hook
virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg);
// Advanced: virtual access to m_pMainWnd
virtual CWnd* GetMainWnd();
// Implementation
public:
virtual ~CWinThread();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
int m_nDisablePumpCount; // Diagnostic trap to detect illegal re-entrancy
#endif
void CommonConstruct();
virtual void Delete();
// 'delete this' only if m_bAutoDelete == TRUE
// message pump for Run
MSG m_msgCur; // current message
public:
// constructor used by implementation of AfxBeginThread
CWinThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam);
// valid after construction
LPVOID m_pThreadParams; // generic parameters passed to starting function
AFX_THREADPROC m_pfnThreadProc;
// set after OLE is initialized
void (AFXAPI* m_lpfnOleTermOrFreeLib)(BOOL, BOOL);
COleMessageFilter* m_pMessageFilter;
protected:
CPoint m_ptCursorLast; // last mouse position
UINT m_nMsgLast; // last mouse message
BOOL DispatchThreadMessageEx(MSG* msg); // helper
void DispatchThreadMessage(MSG* msg); // obsolete
};
//Macros
#define DECLARE_DYNAMIC(class_name) public: static const AFX_DATA CRuntimeClass class##class_name; virtual CRuntimeClass* GetRuntimeClass() const;
#define _DECLARE_DYNAMIC(class_name) public: static AFX_DATA CRuntimeClass class##class_name; virtual CRuntimeClass* GetRuntimeClass() const;
#define DECLARE_MESSAGE_MAP() private: static const AFX_MSGMAP_ENTRY _messageEntries[]; protected: static AFX_DATA const AFX_MSGMAP messageMap; virtual const AFX_MSGMAP* GetMessageMap() const; \ //返回的是MessageMap静态数组的地址,数组定义如下
struct AFX_MSGMAP
{
#ifdef _AFXDLL
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)(); //动态连接的话,MFC库的MessageMap被编译在Mfc42.dll里面
#else
const AFX_MSGMAP* pBaseMap; //你知道是什么?父类的GetMessageMap,每个类都有一个MessageMap
#endif
const AFX_MSGMAP_ENTRY* lpEntries; //Map数组入口,每个单元由6个dword
};
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message //Message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value) //Message处理函数
};
//GetMessageMap函数,返回的地址是MesssageMap
.text:00401010 GetMessageMap proc near ; DATA XREF: .rdata:00402228o
.text:00401010 mov eax, offset off_4021C0
.text:00401015 retn
.text:00401015 GetMessageMap endp
//MesssageMap
.rdata:004021C0 off_4021C0 dd offset sub_401000 ; DATA XREF: GetMessageMapo
.rdata:004021C4 dd offset unk_4021C8
//AFX_MSGMAP_ENTRY[]原始数据
.rdata:004021C8 unk_4021C8 db 11h ; DATA XREF: .rdata:004021C4o
.rdata:004021C9 db 1
.rdata:004021CA db 0
.rdata:004021CB db 0
.rdata:004021CC db 0
.rdata:004021CD db 0
.rdata:004021CE db 0
.rdata:004021CF db 0
.rdata:004021D0 db 46h ; F
.rdata:004021D1 db 0E1h ; ?
.rdata:004021D2 db 0
.rdata:004021D3 db 0
.rdata:004021D4 db 46h ; F
.rdata:004021D5 db 0E1h ; ?
.rdata:004021D6 db 0
.rdata:004021D7 db 0
.rdata:004021D8 db 0Ch
.rdata:004021D9 db 0
.rdata:004021DA db 0
.rdata:004021DB db 0
.rdata:004021DC db 40h ; @
.rdata:004021DD db 13h
.rdata:004021DE db 40h ; @
.rdata:004021DF db 0
.rdata:004021E0 db 0
.rdata:004021E1 db 0
.rdata:004021E2 db 0
.rdata:004021E3 db 0
.rdata:004021E4 db 0
.rdata:004021E5 db 0
.rdata:004021E6 db 0
.rdata:004021E7 db 0
.rdata:004021E8 db 0
.rdata:004021E9 db 0
.rdata:004021EA db 0
.rdata:004021EB db 0
.rdata:004021EC db 0
.rdata:004021ED db 0
.rdata:004021EE db 0
.rdata:004021EF db 0
.rdata:004021F0 db 0
.rdata:004021F1 db 0
.rdata:004021F2 db 0
.rdata:004021F3 db 0
.rdata:004021F4 db 0
.rdata:004021F5 db 0
.rdata:004021F6 db 0
.rdata:004021F7 db 0
5.整理AFX_MSGMAP_ENTRY[]
.rdata:004021C8 dword_4021C8 dd 111h ; DATA XREF: .rdata:004021C4o ;WM_COMMAND
.rdata:004021CC dd 0 ;Code=0
.rdata:004021D0 dd 0E146h ;ID_HELP
.rdata:004021D4 dd 0E146h ;LastID=ID_HELP
.rdata:004021D8 dd 0Ch
.rdata:004021DC dd offset ?OnHelp@CWinApp@@IAEXXZ ; CWinApp::OnHelp(void)
空的代表此类的MessageMap接触,请去找父类的MessageMap如果你喜欢
.rdata:004021E0 dd 0
.rdata:004021E4 dd 0
.rdata:004021E8 dd 0
.rdata:004021EC dd 0
.rdata:004021F0 dd 0
.rdata:004021F4 dd 0
.
6.原代码
// MfcDemo.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "MfcDemo.h"
#include "MfcDemoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMfcDemoApp
BEGIN_MESSAGE_MAP(CMfcDemoApp, CWinApp)
//{{AFX_MSG_MAP(CMfcDemoApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMfcDemoApp construction
CMfcDemoApp::CMfcDemoApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CMfcDemoApp object
CMfcDemoApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CMfcDemoApp initialization
BOOL CMfcDemoApp::InitInstance()
{
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
CMfcDemoDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
7.全局变量和构造函数
start-->initterm-->(pfn_Start,pfn_End)
pfn_Start就是第一个构造函数啦
pfn_End就是最后一个啦,可能是0结尾
最好看vc6sp6的源代码。