Inside COM 笔记三(Chapter5, Chapter6)

来源:互联网 发布:汽车坐垫推荐 知乎 编辑:程序博客网 时间:2024/05/17 04:06
Chapter5 动态链接
Dll 动态链接库,他与组件有什么关系呢?
答:Dll只是发布组件的形式,不是组件。组件是Dll中实现的接口集合。
如何创建组件?
这里涉及到Dll的输出函数,Dll存在的意义也就是它了。试想没有输出函数的Dll会有什么用啊?
输出函数的定义注意加extern “C”防止编译器加上类型信息。方便调用者使用。
光有extern“C”,还是不能使用Dll,还要有DEF文件来说明有哪些导出函数。
追加:FunctionName @1 PRIVATE
            函数名             序号  属性
Dll的装载
装载Dll记住两个函数就够了,LoadLibrary 和 GetProcAddress。具体参数详见MSDN。
使用Dll实现组件的原因是:它可以链入程序的地址空间。方便调用。
Chapter6 关于HRESULT,GUID,注册表及其他的细节
What is HRESULT?
A value returned from a function call to an interface, consisting of a severity code, context information, a facility code, and a status code that describes the result. It is 32 bits data, and low 16 bits represent return code, other 15 bits represent device code (OS) information, highest bit represent how critical result is.
Here is the RESULT NOT Handle to RESULT!
If set to 0, SEVERITY_SUCCESS, the value indicates success. If set to 1, SEVERITY_ERROR, it indicates failure.
The R, C, N, and r bits are reserved.
How to use HRESULT?
Many successes and fails, so S_OK or S_FAIL is not enough.
Fail code may change.
  use SUCCEEDED() or FAILED(),  Example:
    HRESULT hr = CoCreateInstance(…);
    if (FAILED(hr))
   {…       
    }
    hr = QueryInterface(…);
    if (SUCCEEDED(hr))
   {…
   }
User define HRESULT?
Rules:
Do NOT use 0x0000—0x01FF as return value.
Do NOT transmit FACILITY_ITF error code.
More use general successful or failure symbols which are defined in COM.
Avoid defining own HRESULT, use a output parameter.
Can use MAKE_HRESULT function to define a HRESULT.
What is GUID?
Globally Unique Identifier
A GUID is a 128-bit integer (16 bytes) that can be used across all computers and networks wherever a unique identifier is required. Such an identifier has a very low probability of being duplicated.
Tone likes goo-id.
Example:
// {B8EF95EC-BCD6-11D1-AB17-00C04FC2AA49}
static const IID IID_IDownload500 =
{ 0xb8ef95ec, 0xbcd6, 0x11d1, { 0xab, 0x17, 0x0, 0xc0, 0x4f, 0xc2, 0xaa, 0x49 } };
Make sure GUID is unique.
How to make sure.
One solution is UUIDGEN.exe
Another is using CoCreateGuid() function defined in Microsoft COM library.
GUID background knowledge
48 bits physical address.
60 bits timestamp.
From 1852.10.15 00:00:00 to 3400.
Interval is 100 ns.
GUID similar to UUID
Its structure is more bigger.
Declare: extern “C” const  IID IID_IX;
Define: IID_IX = {32bb8320,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,
0xd6,0x82}};
Simple Define & Declare
DEFINE_GUID(<name>, 0x32bb8320,0xb41b,0x11cf,0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82);
Compare GUID
1.    use “==”, such as
 if (guid1 == guid2)
2. Use function :
IsEqualGUID, ISEqualIID, IsEqualCLSID
Simple Define & Declare
DEFINE_GUID(<name>, 0x32bb8320,0xb41b,0x11cf,
0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82);
Represent not only Interface but also Com.
Use reference not value.
COM Lib Functions
Initialize
Basic initial function:
HRESULT CoInitialize(void *pReserved); (OleInitialize apply to OLE)
Only function could call before initialize:
DWORD CoBuildVersion();
Another function to initialize:
CoInitializeEx  (apply to DCOM)
Closes the COM library:
void CoUninitialize(void); (OleUninitialize apply to OLE)
Memory Management of COM Lib( A )
HRESULT CoGetMalloc(DWORD dwMemContext, IMalloc **ppMalloc);
class IMalloc : public IUnknown
{
    void *    Alloc(ULONG cb) = 0;
    void *    Realloc( void * pv,  ULONG cb) = 0;
    void      Free(void* pv) = 0;
    ULONG      GetSize( void * pv) = 0;
    int         DidAlloc(void * pv) = 0;
    void        HeapMinimize()= 0;
};
Example:
DWORD     length = MAX_LENGTH;
IMalloc * pIMalloc;
HRESULT   hr;

hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc);
if (hr != S_OK)
    // return failure

psz=pIMalloc->Alloc(length);
pIMalloc->Release();

if (NULL==psz)
    // return failure......
pszText = psz;
Memory Management of COM Lib( B )
Three functions:
void * CoTaskMemAlloc(ULONG cb);
void CoTaskMemFree(void *pv);
void CoTaskMemRealloc(void *pv, ULONG cb);
DWORD     length = MAX_LENGTH;
IMalloc * pIMalloc;
HRESULT   hr;
void * psz;
psz=CoTaskMemAlloc (length);

if (NULL==psz)
    // return failure
......
pszText = psz;
WCHAR *pwProgID;
char pszProgID[128];
hResult = ::ProgIDFromCLSID(CLSID_Dictionary,  &pwProgID);
if  (hResult != S_OK) {
        ……
}
wcstombs(pszProgID, pwProgID, 128) ;
CoTaskMemFree(pwProgID);

原创粉丝点击