`
mengdejun
  • 浏览: 408828 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

atl thunk源码

阅读更多
atlstdthunk.h
// This is a part of the Active Template Library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the	
// Active Template Library product.

#ifndef __ATLSTDTHUNK_H__
#define __ATLSTDTHUNK_H__

#pragma once

#pragma push_macro("malloc")
#undef malloc
#pragma push_macro("realloc")
#undef realloc
#pragma push_macro("free")
#undef free
#pragma push_macro("new")
#undef new
#pragma push_macro("HeapAlloc")
#undef HeapAlloc
#pragma push_macro("HeapFree")
#undef HeapFree
#pragma push_macro("GetProcessHeap")
#undef GetProcessHeap



 

 
namespace ATL
{

/////////////////////////////////////////////////////////////////////////////
// Thunks for __stdcall member functions

#if defined(_M_IX86)
PVOID __stdcall __AllocStdCallThunk(VOID);
VOID  __stdcall __FreeStdCallThunk(PVOID);

#pragma pack(push,1)
struct _stdcallthunk
{
	DWORD   m_mov;          // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
	DWORD   m_this;         //
	BYTE    m_jmp;          // jmp WndProc
	DWORD   m_relproc;      // relative jmp
	BOOL Init(DWORD_PTR proc, void* pThis)
	{
		m_mov = 0x042444C7;  //C7 44 24 0C
		m_this = PtrToUlong(pThis);
		m_jmp = 0xe9;
		m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(_stdcallthunk)));
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	//some thunks will dynamically allocate the memory for the code
	void* GetCodeAddress()
	{
		return this;
	}
	void* operator new(size_t)
	{
        return __AllocStdCallThunk();
    }
    void operator delete(void* pThunk)
    {
        __FreeStdCallThunk(pThunk);
    }
};
#pragma pack(pop)

#elif defined(_M_AMD64)
PVOID __AllocStdCallThunk(VOID);
VOID  __FreeStdCallThunk(PVOID);
#pragma pack(push,2)
struct _stdcallthunk
{
    USHORT  RcxMov;         // mov rcx, pThis
    ULONG64 RcxImm;         // 
    USHORT  RaxMov;         // mov rax, target
    ULONG64 RaxImm;         //
    USHORT  RaxJmp;         // jmp target
    BOOL Init(DWORD_PTR proc, void *pThis)
    {
        RcxMov = 0xb948;          // mov rcx, pThis
        RcxImm = (ULONG64)pThis;  // 
        RaxMov = 0xb848;          // mov rax, target
        RaxImm = (ULONG64)proc;   //
        RaxJmp = 0xe0ff;          // jmp rax
        FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
    }
	//some thunks will dynamically allocate the memory for the code
	void* GetCodeAddress()
	{
		return this;
	}
	void* operator new(size_t)
	{
        return __AllocStdCallThunk();
    }
    void operator delete(void* pThunk)
    {
        __FreeStdCallThunk(pThunk);
    }
};
#pragma pack(pop)
#elif defined (_M_ALPHA)
// For ALPHA we will stick the this pointer into a0, which is where
// the HWND is.  However, we don't actually need the HWND so this is OK.
#pragma pack(push,4)
struct _stdcallthunk //this should come out to 20 bytes
{
	DWORD ldah_at;      //  ldah    at, HIWORD(func)
	DWORD ldah_a0;      //  ldah    a0, HIWORD(this)
	DWORD lda_at;       //  lda     at, LOWORD(func)(at)
	DWORD lda_a0;       //  lda     a0, LOWORD(this)(a0)
	DWORD jmp;          //  jmp     zero,(at),0
	BOOL Init(DWORD_PTR proc, void* pThis)
	{
		ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15);
		ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15);
		lda_at = 0x239c0000 | LOWORD(proc);
		lda_a0 = 0x22100000 | LOWORD(pThis);
		jmp = 0x6bfc0000;
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	void* GetCodeAddress()
	{
		return this;
	}
};
#pragma pack(pop)
#elif defined(_SH3_)
#pragma pack(push,4)
struct _stdcallthunk // this should come out to 16 bytes
{
	WORD	m_mov_r0;		// mov.l	pFunc,r0
	WORD	m_mov_r1;		// mov.l	pThis,r1
	WORD	m_jmp;			// jmp		@r0
	WORD	m_nop;			// nop
	DWORD	m_pFunc;
	DWORD	m_pThis;
	BOOL Init(DWORD_PTR proc, void* pThis)
	{
		m_mov_r0 = 0xd001;
		m_mov_r1 = 0xd402;
		m_jmp = 0x402b;
		m_nop = 0x0009;
		m_pFunc = (DWORD)proc;
		m_pThis = (DWORD)pThis;
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	void* GetCodeAddress()
	{
		return this;
	}
};
#pragma pack(pop)
#elif defined(_MIPS_)
#pragma pack(push,4)
struct _stdcallthunk
{
	WORD	m_pFuncHi;
	WORD	m_lui_t0;		// lui		t0,PFUNC_HIGH
	WORD	m_pFuncLo;
	WORD	m_ori_t0;		// ori		t0,t0,PFUNC_LOW
	WORD	m_pThisHi;
	WORD	m_lui_a0;		// lui		a0,PTHIS_HIGH
	DWORD	m_jr_t0;		// jr		t0
	WORD	m_pThisLo;
	WORD	m_ori_a0;		// ori		a0,PTHIS_LOW
	BOOL Init(DWORD_PTR proc, void* pThis)
	{
		m_pFuncHi = HIWORD(proc);
		m_lui_t0  = 0x3c08;
		m_pFuncLo = LOWORD(proc);
		m_ori_t0  = 0x3508;
		m_pThisHi = HIWORD(pThis);
		m_lui_a0  = 0x3c04;
		m_jr_t0   = 0x01000008;
		m_pThisLo = LOWORD(pThis);
		m_ori_a0  = 0x3484;
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	void* GetCodeAddress()
	{
		return this;
	}
};
#pragma pack(pop)
#elif defined(_ARM_)
#pragma pack(push,4)
struct _stdcallthunk // this should come out to 16 bytes
{
	DWORD	m_mov_r0;		// mov	r0, pThis
	DWORD	m_mov_pc;		// mov	pc, pFunc
	DWORD	m_pThis;
	DWORD	m_pFunc;
	BOOL Init(DWORD_PTR proc, void* pThis)
	{
		m_mov_r0 = 0xE59F0000;
		m_mov_pc = 0xE59FF000;
		m_pThis = (DWORD)pThis;
		m_pFunc = (DWORD)proc;
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	void* GetCodeAddress()
	{
		return this;
	}
};
#pragma pack(pop)
#elif defined(_M_IA64)
#pragma pack(push,8)
extern "C" void _StdCallThunkProcProc(void);
struct _FuncDesc
{
    void* pfn;
    void* gp;
};
struct _stdcallthunk
{
    _FuncDesc m_funcdesc;
    void* m_pFunc;
    void* m_pThis;
    BOOL Init(DWORD_PTR proc, void* pThis)
    {
        m_funcdesc.pfn = ((_FuncDesc*)(&_StdCallThunkProcProc))->pfn;  // Pointer to actual beginning of StdCallThunkProc
        m_funcdesc.gp = &m_pFunc;
        m_pFunc = reinterpret_cast< void* >( proc );
        m_pThis = pThis;
        ::FlushInstructionCache( GetCurrentProcess(), this, sizeof( _stdcallthunk ) );
		return TRUE;
    }
    void* GetCodeAddress()
    {
        return( &m_funcdesc );
    }
};
#pragma pack(pop)
//IA64 thunks do not currently use the atlhunk.cpp allocator.
#else
#error Only ARM, ALPHA, SH3, MIPS, IA64, AMD64 and X86 supported
#endif


#if defined(_M_IX86) || defined (_M_AMD64)
 
#pragma pack(push,8)
class CDynamicStdCallThunk
{
public:
	_stdcallthunk *pThunk;

	CDynamicStdCallThunk()
	{
		pThunk = NULL;
	}

	~CDynamicStdCallThunk()
	{
		if (pThunk)
		{
			delete pThunk;
		}
	}

	BOOL Init(DWORD_PTR proc, void *pThis)
	{
		if (pThunk == NULL) 
		{
			pThunk = new _stdcallthunk;
			if (pThunk == NULL)
			{
				return FALSE;
			}
		}
		return pThunk->Init(proc, pThis);
	}
	

	void* GetCodeAddress()
	{
		return pThunk->GetCodeAddress();
	}
};

#pragma pack(pop)
typedef CDynamicStdCallThunk CStdCallThunk;
#else
typedef _stdcallthunk CStdCallThunk;
#endif  // _M_IX86 || _M_AMD64

}   // namespace ATL
 

#pragma pop_macro("GetProcessHeap")
#pragma pop_macro("HeapAlloc")
#pragma pop_macro("HeapFree")
#pragma pop_macro("new")
#pragma pop_macro("free")
#pragma pop_macro("realloc")
#pragma pop_macro("malloc")

#endif // __ATLSTDTHUNK_H__

 

 

atlthunk.cpp
/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    thunkpool.cpp

Abstract:

    This module contains the support routines for managing a pool of ATL thunk
    structures.

    An ATL thunk contains object code that is built on the fly.  Normally
    ATL allocates these structures from standard usermode heap.  On platforms
    supporting "no-execute" operation, however, heap is protected no-execute so
    this isn't an option.

    The code here manages a separate "heap" of thunk structures that are
    allocated from execute-enabled page allocations.

Author:

    Forrest Foltz (forrestf) 16-May-2002

Environment:

    User mode only.

Revision History:

--*/
#include <windows.h>
#include "atlstdthunk.h"
 
extern "C"
{
typedef struct _CLIENT_ID {
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID *PCLIENT_ID;

struct _PEB;
typedef struct _PEB * PPEB;

typedef struct _TEB {
    NT_TIB NtTib;
    PVOID EnvironmentPointer;
    CLIENT_ID ClientId;
    PVOID ActiveRpcHandle;
    PVOID ThreadLocalStoragePointer;
    PPEB ProcessEnvironmentBlock;
    /* .... Don't need any thing below this*/
} TEB, *PTEB;
 
_inline struct _TEB * Atl_NtCurrentTeb( void ) { __asm mov eax, fs:[0x18] }
 
}

#if !defined(_X86_)
#error Unsupported platform
#endif

#if !defined(PAGE_SIZE)
#define PAGE_SIZE 4096
#endif

#if !defined(DECLSPEC_NOINLINE)
#define DECLSPEC_NOINLINE __declspec(noinline)
#endif

#define ATL_THUNKS_PER_PAGE (PAGE_SIZE / sizeof(ATL_THUNK_ENTRY))

//
// Local function prototypes and typedefs
//

BOOL
static
__InitializeThunkPool (
    VOID
    );

typedef
PSINGLE_LIST_ENTRY
(__stdcall *PINTERLOCKED_PUSH_ENTRY_SLIST) (
     PSLIST_HEADER ListHead,
     PSINGLE_LIST_ENTRY ListEntry
    );

typedef
PSINGLE_LIST_ENTRY
(__stdcall *PINTERLOCKED_POP_ENTRY_SLIST) (
     PSLIST_HEADER ListHead
    );

//
// An ATL thunk structure, used to manage free thunks in the pool
//

typedef union _ATL_THUNK_ENTRY {
    SLIST_ENTRY SListEntry;
	struct ATL::_stdcallthunk Thunk;
} ATL_THUNK_ENTRY, *PATL_THUNK_ENTRY;

//
// Pointer to the process-wide ATL thunk slist.
//

PSLIST_HEADER __AtlThunkPool = NULL;

//
// Special value for __AtlThunkPool indicating that the standard
// heap should be used for thunk allocation.
//

#define ATLTHUNK_USE_HEAP_VALUE (PSLIST_HEADER)UlongToPtr(1)
#define ATLTHUNK_USE_HEAP()     (__AtlThunkPool == ATLTHUNK_USE_HEAP_VALUE)

PINTERLOCKED_PUSH_ENTRY_SLIST __AtlInterlockedPushEntrySList = NULL;
PINTERLOCKED_POP_ENTRY_SLIST  __AtlInterlockedPopEntrySList = NULL;


PVOID
__AllocStdCallThunk_cmn (
    VOID
    )

/*++

Routine Description:

    This function is called by ATL to allocate a thunk structure from
    executable memory.

Arguments:

    None.

Return Value:

    Returns a pointer to a thunk structure on success.  Raises an exception
    on failure.

--*/

{
    PATL_THUNK_ENTRY lastThunkEntry;
    PATL_THUNK_ENTRY thunkEntry;
    PVOID thunkPage;

    //
    // Perform initialization if this is the first time through.
    //

    if (__AtlThunkPool == NULL) {
        if (__InitializeThunkPool() == FALSE) {
            goto outOfMemory;
        }
    }

    if (ATLTHUNK_USE_HEAP()) {

        //
        // On a non-NX capable platform, use the standard heap.
        //

        thunkEntry = (PATL_THUNK_ENTRY)HeapAlloc(GetProcessHeap(),
                                                 0,
												 sizeof(ATL::_stdcallthunk));
        if (thunkEntry == NULL) {
            goto outOfMemory;
        }

        return thunkEntry;
    }

    //
    // Attempt to pop a thunk structure from the list and return it
    // 

    thunkEntry = (PATL_THUNK_ENTRY)__AtlInterlockedPopEntrySList(__AtlThunkPool);
    if (thunkEntry != NULL) {
        return &thunkEntry->Thunk;
    }

    //
    // The thunk list was empty.  Allocate a new page of executable
    // memory.
    //

    thunkPage = (PATL_THUNK_ENTRY)VirtualAlloc(NULL,
                                               PAGE_SIZE,
                                               MEM_COMMIT,
                                               PAGE_EXECUTE_READWRITE);
    if (thunkPage == NULL) {
        goto outOfMemory;
    }

    //
    // See if another thread has replenished the pool while we were off
    // allocating memory.  This does not close the window but makes it much
    // smaller.
    //
    // The volatile reference moves the overhead of making the page present
    // outside of the window.
    //

    *(DWORD volatile *)thunkPage;
    thunkEntry = (PATL_THUNK_ENTRY)__AtlInterlockedPopEntrySList(__AtlThunkPool);
    if (thunkEntry != NULL) {

        //
        // The pool has been replenished.  Free the page and use the thunk
        // entry that we just received.
        //

        VirtualFree(thunkPage,0,MEM_RELEASE);
        return thunkEntry;
    }

    //
    // Create an array of thunk structures on the page and insert all but
    // the last into the free thunk list.
    //
    // The last is kept out of the list and represents the thunk allocation.
    //

    thunkEntry = (PATL_THUNK_ENTRY)thunkPage;
    lastThunkEntry = thunkEntry + ATL_THUNKS_PER_PAGE - 1;
    do {
        __AtlInterlockedPushEntrySList(__AtlThunkPool,&thunkEntry->SListEntry);
        thunkEntry += 1;
    } while (thunkEntry < lastThunkEntry);

    return thunkEntry;

outOfMemory:

    return NULL;
}


VOID
__FreeStdCallThunk_cmn (
    IN PVOID Thunk
    )

/*++

Routine Description:

    This function is called by ATL to release a thunk structure back to the
    process-wide free thunk pool.

Arguments:

    Thunk - supplies a pointer to a thunk structure that was allocated with
            __AllocStdCallThunk().

Return Value:

    None.

--*/

{
    PATL_THUNK_ENTRY thunkEntry;

    if (ATLTHUNK_USE_HEAP()) {

        //
        // On a non-NX capable platform, use the standard heap.
        //                              

        HeapFree(GetProcessHeap(),0,Thunk);

    } else {

        //
        // Simply push the free thunk structure back onto the pool
        //
    
        thunkEntry = (PATL_THUNK_ENTRY)Thunk;
        __AtlInterlockedPushEntrySList(__AtlThunkPool,&thunkEntry->SListEntry);
    }
}


BOOL
static
DECLSPEC_NOINLINE
__InitializeThunkPool (
    VOID
    )

/*++

Routine Description:

    This function is called on the first invocation of __AllocStdCallThunk().
    It retrieves a pointer to the process-wide thunk pool SLIST_HEADER, if
    one already exists, otherwise this routine supplies an initialized
    SLIST_HEADER.

Arguments:

    None.

Return Value:

    Returns TRUE if initialization succeeded, FALSE otherwise.

--*/

{
    #define PEB_POINTER_OFFSET 0x34

    PSLIST_HEADER *atlThunkPoolPtr;
    PSLIST_HEADER atlThunkPool;

    //
    // On Win64, a per-process ATL thunk "heap" (anchored in the PEB) is always
    // mantained as an SLIST.
    //
    // On X86, such a heap is conditional.  If the OS is < 5.1 (Windows XP) then
    // thunks are allocated/freed from/to the heap, otherwise they are mantained
    // as they would be on Win64.
    //
    // Two reasons for this:
    //
    // - We can't guarantee that the SLIST slot in the PEB is available downlevel
    // - Downlevel OSs may not offer the SLIST functionality
    // 

    HMODULE kernel32Module;
    BOOL result;

    result = IsProcessorFeaturePresent( 12 /*PF_NX_ENABLED*/ );
    if (result == FALSE) {

        //
        // NX execution is not happening on this machine.
        //
        // Indicate that the regular heap should be used by setting
        // __AtlThunkPool to a special value.
        //

        __AtlThunkPool = ATLTHUNK_USE_HEAP_VALUE;
        return TRUE;
    }

    //
    // We are running on Windows NT5.1 or later.  Get the kernel32 pointers to
    // InterlockedPushEntrySList and InterlockedPopEntrySList.  They can't be
    // simply imported as this library may run in environments without those
    // routines.
    // 

    kernel32Module = LoadLibrary( "kernel32.dll" );
    if (kernel32Module != NULL) {

        __AtlInterlockedPushEntrySList = (PINTERLOCKED_PUSH_ENTRY_SLIST)
            GetProcAddress( kernel32Module, "InterlockedPushEntrySList" );

        __AtlInterlockedPopEntrySList = (PINTERLOCKED_POP_ENTRY_SLIST)
            GetProcAddress( kernel32Module, "InterlockedPopEntrySList" );
    }

    if (__AtlInterlockedPushEntrySList == NULL ||
        __AtlInterlockedPopEntrySList == NULL) {

        //
        // If either address could not be retrieved then fail the
        // initialization.
        //

        return FALSE;
    }

    atlThunkPoolPtr =
        (PSLIST_HEADER *)((PCHAR)(Atl_NtCurrentTeb()->ProcessEnvironmentBlock) + PEB_POINTER_OFFSET);

    atlThunkPool = *atlThunkPoolPtr;
    if (atlThunkPool == NULL) {

        //
        // The pool list has not yet been initialized.  Try to use ours.
        //
        // Normally we would simply call InitializeSListHead() to initialize
        // the SLIST_HEADER.  However, this creates linkage that conflicts with
        // modules (such as duser) which also link to ntslist.lib.
        //
        // So to avoid that, the SLIST_HEADER is initialized manually.  This
        // code is platform-specific.
        // 
    
        atlThunkPool = (PSLIST_HEADER)HeapAlloc( GetProcessHeap(),
                                                 0,
                                                 sizeof(SLIST_HEADER) );
        if (atlThunkPool == NULL) {
            return FALSE;
        }

        //InitializeSListHead(atlThunkPool);
        atlThunkPool->Alignment = 0;

        if (InterlockedCompareExchangePointer( (PVOID *)atlThunkPoolPtr,
                                               atlThunkPool,
                                               NULL ) != NULL) {

            //
            // Another thread was initializing as well, and won the race.
            // Free our slist header and use the one that is now there.
            //

            HeapFree( GetProcessHeap(),
                      0,
                      atlThunkPool );
        }

        atlThunkPool = *atlThunkPoolPtr;
    }

    __AtlThunkPool = atlThunkPool;
    return TRUE;
}

//
// Now create the actual routines, one pair within an ATL namespace and one
// without.
// 

PVOID
__stdcall __AllocStdCallThunk (
    VOID
    )
{
    return __AllocStdCallThunk_cmn();
}

VOID
__stdcall __FreeStdCallThunk (
    IN PVOID Thunk
    )
{
    __FreeStdCallThunk_cmn(Thunk);
}

namespace ATL {

PVOID
__stdcall __AllocStdCallThunk (
    VOID
    )
{
    return __AllocStdCallThunk_cmn();
}

VOID
__stdcall __FreeStdCallThunk (
    IN PVOID Thunk
    )
{
    __FreeStdCallThunk_cmn(Thunk);
}

}   // namespace ATL


 

KC网络电话,中国最优秀的网络电话

分享到:
评论

相关推荐

    atl thunk

    在ATL中,thunk主要分为两种类型:STDMETHODCALLTYPE thunk和C++虚函数调用thunk。STDMETHODCALLTYPE是一种常见的COM调用约定,它与stdcall类似,参数由被调用者清理。而C++虚函数调用thunk则用于处理C++对象的多态...

    ATL开发指南源码

    这个“ATL开发指南源码”显然是一份详细的教程或示例集合,帮助开发者深入理解和实践ATL编程。下面我们将深入探讨ATL的核心概念、主要功能以及如何利用它来创建高效且小巧的COM组件。 ATL起源于1997年,主要是为了...

    ATL编程的例子源码

    全面使用VC ATL编程的例子源码(适合使用COM的中高级程序员) 压缩包中包含的文件如下: collection.zip:包含VC Atl开发的集合的源代码(组件程序和测试程序) enum.zip:包含VC Atl开发的枚举器的源代码(组件...

    atl开发指南源码

    这个“atl开发指南源码”是基于ATL开发指南的第二版,提供了一系列示例代码,帮助开发者深入理解并实践ATL技术。 ATL的主要目标是为COM编程提供轻量级的解决方案,它通过模板技术和元编程技术,减少了编写COM对象所...

    atl编程基础源码分享

    ATL(Active Template Library)是Microsoft开发的...通过这个ATL编程基础源码,你可以深入理解ATL如何与COM结合,以及如何利用它来构建Windows GUI应用程序。这是一个很好的起点,可以帮助你进一步掌握ATL和COM编程。

    文件系统监控ATL组件源码

    文件系统监控ATL组件源码是一份非常有价值的资源,它为开发者提供了标准的ATL(Active Template Library)实现,用于监视和控制文件系统的活动。ATL是微软开发的一个C++库,它简化了COM(Component Object Model)...

    ATL源码学习-聚合的支持

    ATL源码学习中关于聚合的支持主要涉及以下几个方面: 1. **IUnknown接口**:所有COM对象都必须实现IUnknown接口,它包含了三个基本方法:QueryInterface、AddRef和Release。在聚合中,聚合对象负责处理IUnknown的...

    全套c#atl技术 源码

    在本套源码中,我们看到的是使用C#语言与ATL技术结合的例子,运行环境为Visual Studio 2008。 1. ATLShellExtDragAndDropHandler:这是一个实现拖放操作的外壳扩展。在Windows操作系统中,外壳是用户界面的一部分,...

    ATL开发指南源码.rar 与书本配套的

    本压缩包"ATL开发指南源码.rar"包含了与某本书配套的源代码示例,旨在帮助读者通过实践来理解和掌握ATL编程技术。 在学习ATL开发时,有几个关键知识点是必不可少的: 1. **COM基础**:理解COM的基本概念,如接口、...

    ATL Internals练习源码1-11章

    这个压缩包包含了该书前11章的练习源码,对于学习和掌握ATL编程技巧具有很高的价值。 1. ATL基础知识:ATL是一种轻量级的库,主要设计用于快速、高效地创建COM对象。它通过模板技术减少了大量的样板代码,使得...

    取MAC地址的网页控件OCX(MFC/ATL)源码

    【标题】"取MAC地址的网页控件OCX(MFC/ATL)源码"涉及到的核心技术是创建一个能够获取计算机硬件物理地址(MAC地址)的ActiveX控件,该控件可以在网页环境中使用。这通常是通过MFC(Microsoft Foundation Classes)...

    深入解析ATL(第2版)ATL Internals: Working with ATL 8 (2nd Edition)

    中文版 清晰 pdf,经典ATL又一升级力作,不容错过。 这是第一部分。因为不能大于60M,所以只能分开为2部分了。 原书名: ATL Internals: Working with ATL 8 (2nd Edition) 作者: (美)Chris Tavares Kirk Fertitta...

    ATL开发指南和源码

    这个压缩包包含的"ATL开发指南"和"ATL开发指南源码"是学习和理解ATL编程的重要资源。 一、ATL基础 ATL是一个轻量级的库,它的设计目标是尽可能高效地实现COM接口和对象。ATL通过模板类和宏来简化COM编程,减少了...

    ATL ActiveX Opengl JavaScript

    ATL ActiveX OpenGL JavaScript 是一个技术组合,用于在网页中集成3D图形渲染,通过JavaScript调用由ATL(Active Template Library)创建的ActiveX控件来实现OpenGL的功能。ATL是微软提供的一种C++库,它简化了COM...

    ATL开发指南(附源码)

    总的来说,“ATL开发指南”是一份全面的参考资料,不仅提供了ATL的理论知识,还配以源码实例,是初学者和有经验的开发者深入研究ATL技术的理想选择。通过研读这份指南,你可以掌握创建高效、小巧COM组件的技能,为你...

    《使用ATL编写一个简单的COM服务器》配套源代码

    在ATL中,我们通常会遇到以下关键概念: 1. **CComObjectRootEx**: 这个模板类是所有ATL COM对象的基础,它负责对象的引用计数和接口管理。通过继承CComObjectRootEx,我们可以得到基本的COM对象行为。 2. **...

    ATL开发指南(随书源码)

    这个"ATL开发指南(随书源码)"很可能是一本关于ATL编程技术的书籍配套源代码,帮助读者深入理解并实践ATL编程。 ATL是一个轻量级的库,它提供了一组模板类,用于简化COM对象的创建和实现。在Windows平台上,COM是一...

Global site tag (gtag.js) - Google Analytics