Posts Tagged ‘COM’

  1. Hello, COM(MASM) World!

    Posted on 5月 12th, 2012 by cx20

    COM(MASM)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は MASM による COM クライアントの例となっている。

    ソースコード

    ; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.40219.01 
     
    	TITLE	hello.c
    	.686P
    	.XMM
    	include listing.inc
    	.model	flat
     
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
     
    _DATA	SEGMENT
    $SG113507 DB	'H', 00H, 'e', 00H, 'l', 00H, 'l', 00H, 'o', 00H, ',', 00H
    	DB	' ', 00H, 'C', 00H, 'O', 00H, 'M', 00H, '(', 00H, 'M', 00H, 'A'
    	DB	00H, 'S', 00H, 'M', 00H, ')', 00H, ' ', 00H, 'W', 00H, 'o', 00H
    	DB	'r', 00H, 'l', 00H, 'd', 00H, '!', 00H, 00H, 00H
    _DATA	ENDS
    PUBLIC	_main
    EXTRN	__imp__CoUninitialize@0:PROC
    EXTRN	__imp__CoCreateInstance@20:PROC
    EXTRN	_CLSID_Shell:BYTE
    EXTRN	_IID_IShellDispatch:BYTE
    EXTRN	__imp__CoInitialize@4:PROC
    ; Function compile flags: /Odtp
    _TEXT	SEGMENT
    _pFolder$ = -36						; size = 4
    _vRootFolder$ = -32					; size = 16
    _folder$ = -12						; size = 4
    _pShell$ = -4						; size = 4
    _argc$ = 8						; size = 4
    _argv$ = 12						; size = 4
    _main	PROC
    ; File hello.c
    ; Line 4
            push    ebp
            mov     ebp, esp
            sub     esp, 36                                 ; 00000024H
    ; Line 11
            push    0
            call    DWORD PTR __imp__CoInitialize@4
    ; Line 13
            lea     eax, DWORD PTR _pShell$[ebp]
            push    eax
            push    OFFSET _IID_IShellDispatch
            push    1
            push    0
            push    OFFSET _CLSID_Shell
            call    DWORD PTR __imp__CoCreateInstance@20
    ; Line 15
            mov     ecx, 3
            mov     WORD PTR _vRootFolder$[ebp], cx
    ; Line 16
            mov     DWORD PTR _vRootFolder$[ebp+8], 36      ; 00000024H
    ; Line 17
            lea     edx, DWORD PTR _folder$[ebp]
            mov     DWORD PTR _pFolder$[ebp], edx
    ; Line 19
            lea     eax, DWORD PTR _pFolder$[ebp]
            push    eax
            sub     esp, 16                                 ; 00000010H
            mov     ecx, esp
            mov     edx, DWORD PTR _vRootFolder$[ebp]
            mov     DWORD PTR [ecx], edx
            mov     eax, DWORD PTR _vRootFolder$[ebp+4]
            mov     DWORD PTR [ecx+4], eax
            mov     edx, DWORD PTR _vRootFolder$[ebp+8]
            mov     DWORD PTR [ecx+8], edx
            mov     eax, DWORD PTR _vRootFolder$[ebp+12]
            mov     DWORD PTR [ecx+12], eax
            push    0
            push    OFFSET $SG113507
            push    0
            mov     ecx, DWORD PTR _pShell$[ebp]
            push    ecx
            mov     edx, DWORD PTR _pShell$[ebp]
            mov     eax, DWORD PTR [edx]
            mov     ecx, DWORD PTR [eax+40]
            call    ecx
    ; Line 20
            cmp     DWORD PTR _pFolder$[ebp], 0
            je      SHORT $LN1@main
    ; Line 22
            mov     edx, DWORD PTR _pFolder$[ebp]
            push    edx
            mov     eax, DWORD PTR _pFolder$[ebp]
            mov     ecx, DWORD PTR [eax]
            mov     edx, DWORD PTR [ecx+8]
            call    edx
    $LN1@main:
    ; Line 24
            mov     eax, DWORD PTR _pShell$[ebp]
            push    eax
            mov     ecx, DWORD PTR _pShell$[ebp]
            mov     edx, DWORD PTR [ecx]
            mov     eax, DWORD PTR [edx+8]
            call    eax
    ; Line 26
            call    DWORD PTR __imp__CoUninitialize@0
    ; Line 28
            xor     eax, eax
    ; Line 29
            mov     esp, ebp
            pop     ebp
            ret     0
    _main   ENDP
    _TEXT   ENDS
    END

    上記コードは以下のC言語のソースを VC++ でアセンブリコード出力(cl /FA hello.c)したものに相当する。

    #include <shlobj.h>
     
    int main( int argc, char* argv[] )
    {
        HRESULT hResult;
        IShellDispatch* pShell;
        VARIANT vRootFolder;
        Folder* pFolder;
     
        CoInitialize( NULL );
     
        CoCreateInstance( &CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, &IID_IShellDispatch, (void**)&pShell );
     
        VariantInit( &vRootFolder );
        vRootFolder.vt = VT_I4;
        vRootFolder.lVal = ssfWINDOWS;
     
        pShell->lpVtbl->BrowseForFolder( (void*)pShell, 0, L"Hello, COM(MASM) World!", 0, vRootFolder, &pFolder );
        VariantClear( &vRootFolder );
        if ( pFolder != NULL )
        {
            pFolder->lpVtbl->Release( (void*)pFolder );
        }
        pShell->lpVtbl->Release( (void*)pShell );
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル&リンク方法

    C:¥> ml -c hello.asm
    C:¥> midl shldisp.idl
    C:¥> cl shldisp_i.c
    C:¥> link hello.obj shldisp_i.obj ole32.lib oleaut32.lib

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(MASM) Wolrd!                |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  2. Hello, COM(MFC) World!

    Posted on 5月 11th, 2012 by cx20

    COM(MFC)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は Visual C++ / MFC による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。

    ソースコード(事前バインディング)

    #include <afxdisp.h>
     
    // [Typelib クラス追加ウィザード] で作成された IDispatch ラッパー クラスより一部抜粋
    class CFolder : public COleDispatchDriver
    {
    public:
        CFolder(){}
        CFolder(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
        CFolder(const CFolder& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}
    public:
        CString get_Title()
        {
            CString result;
            InvokeHelper(0x0, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
            return result;
        }
    };
     
    // [Typelib クラス追加ウィザード] で作成された IDispatch ラッパー クラスより一部抜粋
    class CShellDispatch : public COleDispatchDriver
    {
    public:
        CShellDispatch(){}
        CShellDispatch(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
        CShellDispatch(const CShellDispatch& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}
    public:
        LPDISPATCH BrowseForFolder(long Hwnd, LPCTSTR Title, long Options, VARIANT& RootFolder)
        {
            LPDISPATCH result;
            static BYTE parms[] = VTS_I4 VTS_BSTR VTS_I4 VTS_VARIANT ;
            InvokeHelper(0x60020003, DISPATCH_METHOD, VT_DISPATCH, (void*)&result, parms, Hwnd, Title, Options, &RootFolder);
            return result;
        }
    };
     
    int _tmain(int argc, TCHAR* argv[] )
    {
        CoInitialize( NULL );
     
        CFolder folder;
        CShellDispatch shell;
        shell.CreateDispatch( _T("Shell.Application") );
     
        COleVariant vRootFolder( (long)ssfWINDOWS );
        folder = shell.BrowseForFolder( 0, _T("Hello, COM(MFC) World!"), 0, vRootFolder );
        if ( folder != NULL )
        {
            folder.DetachDispatch();
            folder.ReleaseDispatch();
        }
        shell.DetachDispatch();
        shell.ReleaseDispatch();
     
        CoUninitialize();
        return 0;
    }

    ソースコード(実行時バインディング)

    #include <afxdisp.h>
     
    int _tmain(int argc, TCHAR* argv[] )
    {
        CoInitialize( NULL );
     
        COleDispatchDriver shell;
        shell.CreateDispatch( _T("Shell.Application") );
     
        DISPID  dispid;
        OLECHAR* ptName = L"BrowseForFolder";
        ((LPDISPATCH)shell)->GetIDsOfNames( IID_NULL, &ptName, 1, GetUserDefaultLCID(), &dispid );
     
        LPDISPATCH pResult;
        COleVariant vRootFolder( 36L );    // ssfWINDOWS
        BYTE parms[] = VTS_I4 VTS_BSTR VTS_I4 VTS_VARIANT;
        shell.InvokeHelper( dispid, DISPATCH_METHOD, VT_DISPATCH, &pResult, parms, 0, _T("Hello, COM(MFC) World!"), 0, &vRootFolder);
     
        COleDispatchDriver folder = pResult;
        if ( folder != NULL )
        {
            folder.DetachDispatch();
            folder.ReleaseDispatch();
        }
        shell.DetachDispatch();
        shell.ReleaseDispatch();
     
        CoUninitialize();
        return 0;
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.cpp

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(MFC) Wolrd!                 |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  3. Hello, COM(ATL) World!

    Posted on 5月 10th, 2012 by cx20

    COM(ATL)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は Visual C++ / ATL による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。

    ソースコード(事前バインディング)

    #include <atlbase.h>
    #include <shlobj.h>
     
    int _tmain(int argc, TCHAR* argv[] )
    {
        CoInitialize( NULL );
     
        CComPtr<Folder> pFolder;
        CComPtr<IShellDispatch> pShell;
        pShell.CoCreateInstance( CLSID_Shell );
     
        CComVariant vRootFolder( ssfWINDOWS );
        pShell->BrowseForFolder( 0, L"Hello, COM(ATL) World!", 0, vRootFolder, &pFolder );
        if ( pFolder != NULL )
        {
            pFolder = NULL;
        }
        pShell = NULL;
     
        CoUninitialize();
     
        return 0;
    }

    ソースコード(実行時バインディング)

    #include <atlbase.h>
     
    int _tmain(int argc, TCHAR* argv[] )
    {
        CoInitialize( NULL );
     
        CComPtr<IDispatch> pShell;
        pShell.CoCreateInstance( L"Shell.Application" );
     
        DISPPARAMS param = { NULL, NULL, 0, 0 };
        CComVariant varg[4];
        varg[0] = 36L;  // VT_I4 ssfWINDOWS 
        varg[1] = 0L;   // VT_I4
        varg[2] = L"Hello, COM(ATL) World!"; //  VT_BSTR
        varg[3] = 0L;   // VT_I4
     
        CComVariant vResult;
        pShell.InvokeN(L"BrowseForFolder", varg, 4, &vResult );
     
        CComPtr<IDispatch> pFolder = vResult.pdispVal;
        if ( pFolder != NULL )
        {
            pFolder = NULL;
        }
        pShell = NULL;
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.cpp

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(ATL) Wolrd!                 |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  4. Hello, COM(#import) World!

    Posted on 5月 9th, 2012 by cx20

    COM(#import)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は Visual C++ のコンパイラ機能である #import ディレクティブを使用した COM クライアントの例となっている。

    ソースコード(事前バインディング)

    #import "shell32.dll"
    using namespace Shell32;
     
    int main( int argc, char* argv[] )
    {
        CoInitialize( NULL );
     
        IShellDispatchPtr pShell("Shell.Application");
        FolderPtr pFolder = NULL;
     
        _variant_t vRootFolder( ssfWINDOWS );
        pFolder = pShell->BrowseForFolder( 0, L"Hello, COM(#import) World!", 0, vRootFolder );
        if ( pFolder != NULL )
        {
            pFolder = NULL;
        }
        pShell = NULL;
     
        CoUninitialize();
     
        return 0;
    }

    #import ディレクティブにより、以下の2ファイル(「*.tlh(タイプライブラリヘッダ)」「*.tli(タイプライブラリ実装ファイル)」)が自動生成されタイプライブラリの情報が C++ ヘッダとして取り込まれる。

    ソースコード(タイプライブラリヘッダ)

    // #import "shell32.dll" にて自動生成された shell32.tlh より一部抜粋
     
    #include <comdef.h>
    namespace Shell32 {
     
    enum ShellSpecialFolderConstants;
    struct __declspec(uuid("bbcbde60-c3ff-11ce-8350-444553540000"))
    /* dual interface */ Folder;
    struct __declspec(uuid("d8f015c0-c278-11ce-a49e-444553540000"))
    /* dual interface */ IShellDispatch;
     
    _COM_SMARTPTR_TYPEDEF(Folder, __uuidof(Folder));
    _COM_SMARTPTR_TYPEDEF(IShellDispatch, __uuidof(IShellDispatch));
     
    enum __declspec(uuid("ca31ea20-48d0-11cf-8350-444553540000"))
    ShellSpecialFolderConstants
    {
        ssfWINDOWS = 36,
    };
     
    struct __declspec(uuid("d8f015c0-c278-11ce-a49e-444553540000"))
    IShellDispatch : IDispatch
    {
        // Wrapper methods for error-handling
        FolderPtr BrowseForFolder (
            long Hwnd,
            _bstr_t Title,
            long Options,
            const _variant_t & RootFolder = vtMissing );
     
        // Raw methods provided by interface
          virtual HRESULT __stdcall get_Application (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall get_Parent (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall raw_NameSpace (
            /*[in]*/ VARIANT vDir,
            /*[out,retval]*/ struct Folder * * ppsdf ) = 0;
          virtual HRESULT __stdcall raw_BrowseForFolder (
            /*[in]*/ long Hwnd,
            /*[in]*/ BSTR Title,
            /*[in]*/ long Options,
            /*[in]*/ VARIANT RootFolder,
            /*[out,retval]*/ struct Folder * * ppsdf ) = 0;
          virtual HRESULT __stdcall raw_Windows (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall raw_Open (
            /*[in]*/ VARIANT vDir ) = 0;
          virtual HRESULT __stdcall raw_Explore (
            /*[in]*/ VARIANT vDir ) = 0;
          virtual HRESULT __stdcall raw_MinimizeAll ( ) = 0;
          virtual HRESULT __stdcall raw_UndoMinimizeALL ( ) = 0;
          virtual HRESULT __stdcall raw_FileRun ( ) = 0;
          virtual HRESULT __stdcall raw_CascadeWindows ( ) = 0;
          virtual HRESULT __stdcall raw_TileVertically ( ) = 0;
          virtual HRESULT __stdcall raw_TileHorizontally ( ) = 0;
          virtual HRESULT __stdcall raw_ShutdownWindows ( ) = 0;
          virtual HRESULT __stdcall raw_Suspend ( ) = 0;
          virtual HRESULT __stdcall raw_EjectPC ( ) = 0;
          virtual HRESULT __stdcall raw_SetTime ( ) = 0;
          virtual HRESULT __stdcall raw_TrayProperties ( ) = 0;
          virtual HRESULT __stdcall raw_Help ( ) = 0;
          virtual HRESULT __stdcall raw_FindFiles ( ) = 0;
          virtual HRESULT __stdcall raw_FindComputer ( ) = 0;
          virtual HRESULT __stdcall raw_RefreshMenu ( ) = 0;
          virtual HRESULT __stdcall raw_ControlPanelItem (
            /*[in]*/ BSTR bstrDir ) = 0;
    };
     
    struct __declspec(uuid("bbcbde60-c3ff-11ce-8350-444553540000"))
    Folder : IDispatch
    {
        // Property data
        __declspec(property(get=GetTitle))
        _bstr_t Title;
     
        // Wrapper methods for error-handling
        _bstr_t GetTitle ( );
     
        // Raw methods provided by interface
          virtual HRESULT __stdcall get_Title (
            /*[out,retval]*/ BSTR * pbs ) = 0;
          virtual HRESULT __stdcall get_Application (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall get_Parent (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall get_ParentFolder (
            /*[out,retval]*/ struct Folder * * ppsf ) = 0;
          virtual HRESULT __stdcall raw_Items (
            /*[out,retval]*/ struct FolderItems * * ppid ) = 0;
          virtual HRESULT __stdcall raw_ParseName (
            /*[in]*/ BSTR bName,
            /*[out,retval]*/ struct FolderItem * * ppid ) = 0;
          virtual HRESULT __stdcall raw_NewFolder (
            /*[in]*/ BSTR bName,
            /*[in]*/ VARIANT vOptions = vtMissing ) = 0;
          virtual HRESULT __stdcall raw_MoveHere (
            /*[in]*/ VARIANT vItem,
            /*[in]*/ VARIANT vOptions = vtMissing ) = 0;
          virtual HRESULT __stdcall raw_CopyHere (
            /*[in]*/ VARIANT vItem,
            /*[in]*/ VARIANT vOptions = vtMissing ) = 0;
          virtual HRESULT __stdcall raw_GetDetailsOf (
            /*[in]*/ VARIANT vItem,
            /*[in]*/ int iColumn,
            /*[out,retval]*/ BSTR * pbs ) = 0;
    };
     
    // Wrapper method implementations
    #include "shell32.tli"
     
    } // namespace Shell32

    ソースコード(タイプライブラリ実装ファイル)

    // #import "shell32.dll" にて自動生成された shell32.tli より一部抜粋
     
    // interface IShellDispatch wrapper method implementations
    inline FolderPtr IShellDispatch::BrowseForFolder ( long Hwnd, _bstr_t Title, long Options, const _variant_t & RootFolder ) {
        struct Folder * _result = 0;
        HRESULT _hr = raw_BrowseForFolder(Hwnd, Title, Options, RootFolder, &_result);
        if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
        return FolderPtr(_result, false);
    }
     
    // interface Folder wrapper method implementations
    inline _bstr_t Folder::GetTitle ( ) {
        BSTR _result = 0;
        HRESULT _hr = get_Title(&_result);
        if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
        return _bstr_t(_result, false);
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.cpp

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(#import) Wolrd!             |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  5. Hello, COM(C++) World!

    Posted on 5月 8th, 2012 by cx20

    COM(C++)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は C++ による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。

    ソースコード(事前バインディング)

    #include <shlobj.h>
     
    int main( int argc, char* argv[] )
    {
        CoInitialize( NULL );
     
        IShellDispatch* pShell;
        CoCreateInstance( CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pShell) );
     
        VARIANT vRootFolder;
        VariantInit( &vRootFolder );
        vRootFolder.vt = VT_I4;
        vRootFolder.lVal = ssfWINDOWS;
     
        Folder* pFolder;
        pShell->BrowseForFolder( 0, L"Hello, COM(C++) World!", 0, vRootFolder, &pFolder );
        VariantClear( &vRootFolder );
        if ( pFolder != NULL )
        {
            pFolder->Release();
        }
        pShell->Release();
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.cpp /link ole32.lib

    ソースコード(実行時バインディング)

    #include <ole2.h>
     
    int main( int argc, char* argv[] )
    {
        CoInitialize( NULL );
     
        CLSID clsid;
        CLSIDFromProgID( L"Shell.Application", &clsid );
        IDispatch* pShell;
        CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pShell) );
     
        DISPID dispid;
        OLECHAR* ptName = L"BrowseForFolder";
        pShell->GetIDsOfNames( IID_NULL, &ptName, 1, GetUserDefaultLCID(), &dispid );
     
        DISPPARAMS param = { NULL, NULL, 0, 0 };
        VARIANT varg[4];
        VariantInit( &varg[0] );
        varg[0].vt = VT_I4;
        varg[0].lVal = 36L;  // ssfWINDOWS 
     
        VariantInit( &varg[1] );
        varg[1].vt = VT_I4;
        varg[1].lVal = 0L;
     
        VariantInit( &varg[2] );
        varg[2].vt = VT_BSTR;
        varg[2].bstrVal = SysAllocString(L"Hello, COM(C++) World!"); 
     
        VariantInit( &varg[3] );
        varg[3].vt = VT_I4;
        varg[3].lVal = 0L;
     
        param.cArgs = 4;
        param.rgvarg = varg;
     
        VARIANT vResult;
        pShell->Invoke( dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &param, &vResult, NULL, NULL );
     
        VariantClear( &varg[0] );
        VariantClear( &varg[1] );
        VariantClear( &varg[2] );
        VariantClear( &varg[3] );
     
        IDispatch* pFolder = V_DISPATCH( &vResult );
        if ( pFolder != NULL )
        {
            pFolder->Release();
        }
        pShell->Release();
     
        CoUninitialize();
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.cpp /link ole32.lib oleaut32.lib

    以下は、コンパイラ COM サポートクラス(comdef.h で定義されている)を使用した例となっている。

    ソースコード(実行時バインディング)

    #include <comdef.h>
     
    int main( int argc, char* argv[] )
    {
        CoInitialize( NULL );
     
        IDispatchPtr pShell( L"Shell.Application" );
     
        DISPID dispid;
        OLECHAR* ptName = L"BrowseForFolder";
        pShell->GetIDsOfNames( IID_NULL, &ptName, 1, GetUserDefaultLCID(), &dispid );
     
        DISPPARAMS param = { NULL, NULL, 0, 0 };
        _variant_t varg[4];
        varg[0] = 36L;  // ssfWINDOWS 
        varg[1] = 0L;
        varg[2] = L"Hello, COM(C++) World!"; 
        varg[3] = 0L;
     
        param.cArgs = 4;
        param.rgvarg = varg;
     
        _variant_t vResult;
        pShell->Invoke( dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &param, &vResult, NULL, NULL );
     
        IDispatchPtr pFolder = V_DISPATCH(&vResult);
        if ( pFolder != NULL )
        {
            pFolder = NULL;
        }
        pShell = NULL;
     
        CoUninitialize();
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.cpp

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(C++) Wolrd!                 |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  6. Hello, COM(C言語) World!

    Posted on 5月 7th, 2012 by cx20

    COM(C言語)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は C言語による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。
    ここでは Windows 標準のプログラム部品である Shell.Application(Shell オブジェクト)の呼出しを例としてる。

    ソースコード(事前バインディング)

    #include <shlobj.h>
     
    int main( int argc, char* argv[] )
    {
        HRESULT hResult;
        IShellDispatch* pShell;
        VARIANT vRootFolder;
        Folder* pFolder;
     
        CoInitialize( NULL );
     
        CoCreateInstance( &CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, &IID_IShellDispatch, (void**)&pShell );
     
        VariantInit( &vRootFolder );
        vRootFolder.vt = VT_I4;
        vRootFolder.lVal = ssfWINDOWS;
     
        pShell->lpVtbl->BrowseForFolder( (void*)pShell, 0, L"Hello, COM World!", 0, vRootFolder, &pFolder );
        VariantClear( &vRootFolder );
        if ( pFolder != NULL )
        {
            pFolder->lpVtbl->Release( (void*)pFolder );
        }
        pShell->lpVtbl->Release( (void*)pShell );
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.c /link ole32.lib

    ソースコード(実行時バインディング)

    #include <ole2.h>
     
    int main( int argc, char* argv[] )
    {
        CLSID clsid;
        IDispatch* pShell;
        IDispatch* pFolder;
        DISPID dispid;
        OLECHAR* ptName = L"BrowseForFolder";
        DISPPARAMS param = { NULL, NULL, 0, 0 };
        VARIANT varg[4];
        VARIANT vResult;
     
        CoInitialize( NULL );
     
        CLSIDFromProgID(L"Shell.Application", &clsid );
        CoCreateInstance( &clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDispatch, (void**)&pShell);
        pShell->lpVtbl->GetIDsOfNames( (void*)pShell, &IID_NULL, &ptName, 1, GetUserDefaultLCID(), &dispid );
     
        VariantInit( &varg[0] );
        varg[0].vt = VT_I4;
        varg[0].lVal = 36L;  /* ssfWINDOWS */
     
        VariantInit( &varg[1] );
        varg[1].vt = VT_I4;
        varg[1].lVal = 0L;
     
        VariantInit( &varg[2] );
        varg[2].vt = VT_BSTR;
        varg[2].bstrVal = SysAllocString(L"Hello, COM World!"); 
     
        VariantInit( &varg[3] );
        varg[3].vt = VT_I4;
        varg[3].lVal = 0L;
     
        param.cArgs = 4;
        param.rgvarg = varg;
     
        pShell->lpVtbl->Invoke( (void*)pShell, dispid, &IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &param, &vResult, NULL, NULL );
     
        VariantInit( &varg[0] );
        VariantInit( &varg[1] );
        VariantInit( &varg[2] );
        VariantInit( &varg[3] );
     
        pFolder = V_DISPATCH( &vResult );
        if ( pFolder != NULL )
        {
            pFolder->lpVtbl->Release( (void*)pFolder );
        }
        pShell->lpVtbl->Release( (void*)pShell );
     
        CoUninitialize();
     
        return 0;
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.c /link ole32.lib oleaut32.lib

    コンパイル方法(MinGW 版 gcc)

    C:¥> gcc -o hello hello.c -l ole32 -l oleaut32 -l uuid

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM Wolrd!                      |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+