zoukankan      html  css  js  c++  java
  • PHP调用C++制作的非COM组件DLL

    下载DynaWrap.dll  http://download.csdn.net/source/3101053 放入SYSTEM32及EXT下

    $dw = new COM("DynamicWrapper") or die("创建COM失败");
    $sReturnedString=new VARIANT(sprintf("%1024s", " "));
    $dwBSTRAddr=$dw->GetBSTRAddr($sReturnedString);
    $dw->Register("DLL名称.dll", "方法名", "i=参数类型个数", "f=s", "r=返回类型");
    //如果返回string的话需要用BSTR和MemInBSTR方法
    $t = $dw->方法名($dwBSTRAddr);
    //dwBSTRAddr 根据内存指针转换为值
    $name=$dw->GetMemInBSTRAddr($dwBSTRAddr, $nOffset, 0); 
    
    
    http://download.csdn.net/source/3101057
    
    
    //-----------------------------------------------------------------
    // Dynamic Procedure Call COM object.  Jeff Stong 1998
    //-----------------------------------------------------------------
    #define  WIN32_LEAN_AND_MEAN
    #define INC_OLE2
    #include <windows.h>
    #include <malloc.h>
    
    // Using non-DLL version of DynaCall, so don't need to have the
    // methods imported.
    #undef DECLSPEC_IMPORT
    #define DECLSPEC_IMPORT
    extern "C" {
    #include "DynaCall.h"
    }
    
    // Global optimizations cause crash in release builds made with
    // Microsoft 32-bit C/C++ Compiler Version 11.00.7022
    #ifdef _MSC_VER
    #pragma optimize("g",off)
    #endif
    
    // Allocate on-the-stack LPSTR from LPCWSTR
    LPSTR W2AHelp(LPSTR a, LPCWSTR w, int n)
    {
      a[0] = '\0';
      WideCharToMultiByte(CP_ACP, 0, w, -1, a, n, NULL, NULL);
      return a;
    }
    #define W2A(w) (((LPCWSTR)w == NULL) ? NULL : (_clen = \
        (lstrlenW(w)+1)*2,W2AHelp((LPSTR) _alloca(_clen), w, _clen)))
    int _clen;
    
    // Locate index for which c is equal to id in array of n elements
    template <class T> UINT Find(WCHAR c, const T* arr, UINT n)
    {
      for (UINT i = 0; i < n; i++)
        if (arr[i].id == c) 
          return i;
      return -1;
    }
    
    // Allowable tags procedure calling convention
    class CDynCall;
    typedef struct tagTAGINFO
    {
      WCHAR id;     // Character
      HRESULT (*pfn)(CDynCall*, LPWSTR, int);  
        // Parsing callback procedure
    } TAGINFO;
    
    HRESULT iParse(CDynCall* p, LPWSTR w, int c);
    HRESULT rParse(CDynCall* p, LPWSTR w, int c);
    HRESULT fParse(CDynCall* p, LPWSTR w, int c);
    
    const TAGINFO TagInfo[] =
    {
      {'i',iParse}, // Input arguments (see ARGTYPEINFO entries)
      {'r',rParse}, // Return type (see ARGTYPEINFO entries)
      {'f',fParse}, // Calling convention (see FLAGINFO entries)
    };
    #define FindIndexOfTag(wc) \
      Find<TAGINFO>(wc,TagInfo,sizeof(TagInfo)/sizeof(TAGINFO))
    
    // Parameter and return values 
    typedef struct tagARGTYPEINFO
    {
      WCHAR id;      // Character
      UINT size;     // Size of type
      VARTYPE vt;    // Compatible VARTYPE
    } ARGTYPEINFO;
    
    const ARGTYPEINFO ArgInfo[] = 
    {
    {'a', sizeof(IDispatch*),    VT_DISPATCH}, // a   IDispatch*
    {'c', sizeof(unsigned char), VT_I4},       // c   signed char  
    {'d', sizeof(double),        VT_R8},       // d   8 byte real 
    {'f', sizeof(float),         VT_R4},       // f   4 byte real 
    {'k', sizeof(IUnknown*),     VT_UNKNOWN},  // k   IUnknown* 
    {'h', sizeof(long),          VT_I4},       // h   HANDLE 
    {'l', sizeof(long),          VT_I4},       // l   long 
    {'p', sizeof(void*),         VT_PTR},      // p   pointer 
    {'s', sizeof(BSTR),          VT_LPSTR},    // s   string 
    {'t', sizeof(short),         VT_I2},       // t   short 
    {'u', sizeof(UINT),          VT_UINT},     // u   unsigned int 
    {'w', sizeof(BSTR),          VT_LPWSTR},   // w   wide string 
    };
    #define FindIndexOfArg(c) \
      Find<ARGTYPEINFO> \
        (c,ArgInfo,sizeof(ArgInfo)/sizeof(ARGTYPEINFO))
    
    // Calling conventions flags
    typedef struct tagFLAGINFO
    {
      WCHAR id;     // Character
      WORD  wFlag;  // Flag for id
      WORD  wMask;  // Mask for flag value replacement
    } FLAGINFO;
    
    const FLAGINFO FlagInfo[] =
    {
      {'m', DC_MICROSOFT,    ~(DC_MICROSOFT|DC_BORLAND)},
      {'b', DC_BORLAND,      ~(DC_MICROSOFT|DC_BORLAND)},
      {'s', DC_CALL_STD,     ~(DC_CALL_STD|DC_CALL_CDECL)},
      {'c', DC_CALL_CDECL,   ~(DC_CALL_STD|DC_CALL_CDECL)},
      {'4', DC_RETVAL_MATH4, ~(DC_RETVAL_MATH4|DC_RETVAL_MATH8)},
      {'8', DC_RETVAL_MATH8, ~(DC_RETVAL_MATH4|DC_RETVAL_MATH8)},
    };
    
    #define FindIndexOfFlag(c) \
      Find<FLAGINFO>(c,FlagInfo,sizeof(FlagInfo)/sizeof(FLAGINFO))
    
    // DISPID for "Register" method and all those after
    #define REGISTERDISPID 1
    DISPID dispidLastUsed = REGISTERDISPID;
    
    // CServer class holds global object count
    class CServer
    {
    public:
      CServer() : m_hInstance(NULL), m_dwRef(0)
      {}
      HINSTANCE m_hInstance;
      DWORD m_dwRef;
    };
    CServer m_Server;
    
    // CDynCall class manages dynamic procedure calls
    class CDynCall
    {
    public:
      // ctor/dtor
      CDynCall() : dwAddress(0),
                   cArgs(0), 
                   iArg(NULL), 
                   iRet(-1), 
                   wFlags(DC_MICROSOFT|DC_CALL_STD),
                   hDLL(NULL),
                   pNext(NULL),
                   bstrMethod(NULL)
        {}
      ~CDynCall() 
      { 
        SysFreeString(bstrMethod);
        FreeLibrary(hDLL);
        delete [] iArg; 
      }
    
      // Equivalance operators used by CDynCallChain class
      bool operator==(DISPID l) const
      { return l == dispid; }
      bool operator==(LPCWSTR l) const
      { return !lstrcmpiW(l,bstrMethod); }
    
      // Register the procedure
      HRESULT Register(DISPPARAMS* pDispParams, VARIANT* pVarResult)
      {
         // Require at least DLL and procedure name
        if (pDispParams->cArgs < 2)
          return DISP_E_BADPARAMCOUNT;
    
        VARIANTARG* rgvarg = pDispParams->rgvarg;
        int cArgs = pDispParams->cArgs;
        HRESULT hr = E_INVALIDARG;
    
        // Can the library be loaded?
        if ((hDLL = LoadLibraryW(rgvarg[cArgs-1].bstrVal)) != NULL)
        {
          // Find the address of the procedure
          bstrMethod = SysAllocString(rgvarg[cArgs-2].bstrVal);
          if ((dwAddress = SearchProcAddress(hDLL,W2A(bstrMethod))))
          {
            // Load the tags describing the procedure
            hr = S_OK;
            for (int i = cArgs-3; i >= 0 && SUCCEEDED(hr); i--)
              hr = GetTags(rgvarg[i].bstrVal);
          }
        }
        if (SUCCEEDED(hr))
          dispid = ++dispidLastUsed; // Assign a dispid
        if (pVarResult) // Return result if requested by caller
        {
          V_VT(pVarResult) = VT_BOOL;
          V_BOOL(pVarResult) = SUCCEEDED(hr);
        }
        return hr;
      }
    
      // Parse the tags
      HRESULT GetTags(LPWSTR wstrParms)
      {
        while (*wstrParms && iswspace(*wstrParms))
          wstrParms++;
        *wstrParms = towlower(*wstrParms);
    
        // Find the tag, check format and invoke callback
        int len = lstrlenW(wstrParms);
        UINT i = FindIndexOfTag(*wstrParms);
        if ((i == -1) || (len < 3) || (wstrParms[1] != L'='))
          return E_INVALIDARG;
        wstrParms += 2;
        return TagInfo[i].pfn(this,wstrParms,len-2);
      }
    
      // Invokes the procedure
      HRESULT Invoke(DISPPARAMS* pDispParams, VARIANT* pVarResult)
      {
        // Check argument count
        if (cArgs != pDispParams->cArgs)
          return DISP_E_BADPARAMCOUNT;
    
        HRESULT hr = S_OK;
    
        // Allocate DYNPARM structure on stack
        DYNAPARM* Parms = (DYNAPARM*)_alloca(sizeof(DYNAPARM)*cArgs);
        ZeroMemory(Parms,sizeof(DYNAPARM) * cArgs);
        DYNAPARM* Parm = Parms + (cArgs - 1); // Work last to first
        VARIANTARG* rgvarg = pDispParams->rgvarg;
    
        VARIANT va;
        VariantInit(&va);
    
        // Fill in each DYNPARM entry
        for (UINT i = 0; (i < cArgs) && !FAILED(hr); i++, Parm--)
        {
          // Parameter width from table
          Parm->nWidth = ArgInfo[iArg[i]].size; 
          if (Parm->nWidth > 4)
            Parm->dwFlags = DC_FLAG_ARGPTR;
    
          // Parameter value
          VariantClear(&va);
          hr = VariantChangeType(&va,&rgvarg[i],0,ArgInfo[iArg[i]].vt);
          if (SUCCEEDED(hr))
          {
            if (Parm->dwFlags & DC_FLAG_ARGPTR)
            {
              Parm->pArg = _alloca(Parm->nWidth);
              CopyMemory(Parm->pArg,&va.byref,Parm->nWidth);
            }
            else
              Parm->pArg = va.byref;
          }
          else
          {
            // Cases for which VariantChangeType doesn't work
            hr = S_OK;
            switch (ArgInfo[iArg[i]].vt)
            {
            case (VT_I4): // Handle
              if (rgvarg[i].vt <= VT_NULL)
                Parm->pArg = 0;
              else
                hr = E_INVALIDARG;
              break;
    
            case (VT_LPSTR):
              Parm->pArg = W2A(rgvarg[i].bstrVal);
              break;
    
            case (VT_LPWSTR):
              Parm->pArg = rgvarg[i].bstrVal;
              break;
    
            default:
              hr = E_INVALIDARG;
              break;
            }
          }
        }
    
        // Make the dynamic call
        RESULT rc;
        if (SUCCEEDED(hr))
          rc = DynaCall(wFlags,dwAddress,cArgs,Parms,NULL,0);
    
        // Get the return value if requested
        if (pVarResult)
        {
          CopyMemory(&pVarResult->lVal,&rc.Long,ArgInfo[iRet].size);
          pVarResult->vt = ArgInfo[iRet].vt;
        }
    
        // Cleanup
        VariantClear(&va);
    
        // Done
        return hr;
      }
    
      BSTR bstrMethod;   // Name of procedure
      DISPID dispid;     // Assigned DISPID
      HINSTANCE hDLL;    // Handle to DLL containing procedure
      DWORD dwAddress;   // Address of procedure
      WORD wFlags;       // Flags describing calling convention
      UINT cArgs;        // Number of arguments
      LPUINT iArg;       // Indexes to input arguments
      UINT iRet;         // Index of return type
      CDynCall* pNext;   // Pointer to next object in chain
    };
    
    // Parses the input arguments (i=)
    HRESULT iParse(CDynCall* pThis, LPWSTR w, int c)
    {
      pThis->iArg = new UINT[c];
      pThis->cArgs = c;
      UINT* p = pThis->iArg + (c - 1);
      for (; *w; w++)
      {
        UINT j = FindIndexOfArg(towlower(*w));
        if (j == -1)
          return E_INVALIDARG;
        if (p)
          *p = j;
        p--;
      }
      return S_OK;
    }
    
    // Parses the return argument (r=)
    HRESULT rParse(CDynCall* pThis, LPWSTR w, int c)
    {
      pThis->iRet = FindIndexOfArg(towlower(*w));
      return (pThis->iRet != -1) ? S_OK : E_INVALIDARG;
    }
    
    // Parses the calling convention flags (f=)
    HRESULT fParse(CDynCall* pThis, LPWSTR w, int c)
    {
      for (; *w; w++)
      {
        UINT i = FindIndexOfFlag(towlower(*w));
        if (i == -1)
          return E_INVALIDARG;
        pThis->wFlags = 
          (pThis->wFlags & FlagInfo[i].wMask) | FlagInfo[i].wFlag;
      }
      return S_OK;
    }
    
    // CDynCallChain class manages a simple CDynCall linked-list
    class CDynCallChain
    {
    public:
      // ctor/dtor
      CDynCallChain() : m_pFirst(NULL)
      { }
      ~CDynCallChain()
      { 
        while (m_pFirst)
        {
          CDynCall* p = m_pFirst;
          m_pFirst = m_pFirst->pNext;
          delete p;
        }
      }
    
      // Find the DISPID for the given name s
      DISPID FindDISPID(LPWSTR s)
      {
        CDynCall* p = Find(s);
        if (p)
          return p->dispid;
        else if (!lstrcmpiW(s,L"Register"))
          return REGISTERDISPID;
        return DISPID_UNKNOWN;
      }
    
      // Register the procedure (creates a new CDynCall object and
      // adds it to the chain)
      HRESULT Register(DISPPARAMS* pDispParams, VARIANT* pVarResult)
      {
        CDynCall* p = new CDynCall;
        if (!p)
          return E_OUTOFMEMORY;
        HRESULT hr = p->Register(pDispParams,pVarResult);
        if (SUCCEEDED(hr))
        {
          p->pNext = m_pFirst;
          m_pFirst = p;
        }
        else
          delete p;
        return hr;
      }
    
      // Invoke the procedure identifies by dispid
      HRESULT Invoke(DISPID dispid, DISPPARAMS* pParams, 
                     VARIANT* pResult)
      {
        CDynCall* p = Find(dispid);
        if (p)
          return p->Invoke(pParams,pResult);
        else if (dispid == REGISTERDISPID)
          return Register(pParams,pResult);
        return DISPID_UNKNOWN;
      }
    
    protected:
      // Find CDynCall object in chain with value l of type T
      template <class T> CDynCall* Find(T l)
      {
        for (CDynCall* p = m_pFirst; p; p = p->pNext)
        {
          if (*p == l)
            break;
        }
        return p;
      }
    
    protected:
      CDynCall* m_pFirst; // First object in chain
    };
    
    // Template class that provides basic IUnknown implementation
    template <class T, const IID* piid>
    class CInterface : public T
    {
    public:
      CInterface() : m_dwRef(0)
      { m_Server.m_dwRef++; }
      virtual ~CInterface()
      { m_Server.m_dwRef--; }
    
      STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
      {
        if ((riid == IID_IUnknown) || (riid == *piid))
        {
          *ppvObject = (T*)static_cast<T*>(this);
          m_dwRef++;
          return S_OK;
        }
        return E_NOINTERFACE;
      }
      STDMETHOD_(ULONG,AddRef)()
      { return ++m_dwRef; }
      STDMETHOD_(ULONG,Release)()
      {
        if (!(--m_dwRef))
        {
          delete this;
          return 0;
        }
        return m_dwRef;
      }
      DWORD m_dwRef;
    };
    
    
    // COM class that provides for registering and invoking
    // dynamic procedure calls
    class CDynamicWrapper : public CInterface<IDispatch,&IID_IDispatch>
    {
    // IDispatch interface implementation
    public:
        // These methods not implemented
        STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
        { return E_NOTIMPL;  }
        STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**)
        { return E_NOTIMPL;  }
    
        // Defer to CDynCallChain for everything else
        STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR* rgszNames, 
                   UINT cNames, LCID, DISPID* rgDispId)
        {
          for (UINT i = 0; i < cNames; i++)
          {
            rgDispId[i] = m_Chain.FindDISPID(rgszNames[i]);
            if (rgDispId[i] == DISPID_UNKNOWN)
              return DISP_E_MEMBERNOTFOUND;
          }
          return S_OK;
        }
        STDMETHOD(Invoke)(DISPID dispIdMember, REFIID, LCID, WORD, 
                DISPPARAMS* pDispParams, VARIANT* pVarResult,
                EXCEPINFO* pExcepInfo, UINT *puArgErr)
        {
          return m_Chain.Invoke(dispIdMember,pDispParams,pVarResult);
        }
    
    protected:
      CDynCallChain m_Chain;
    };
    
    // Class factory to create CDynamicWrapper COM objects
    class CClassFactory : 
      public CInterface<IClassFactory,&IID_IClassFactory>
    {
    public:
    // IClassFactory interface implementation
      STDMETHOD(CreateInstance)(IUnknown* pUnkOuter, REFIID riid, 
                    void** ppvObject)
      {
        if (pUnkOuter)
          return CLASS_E_NOAGGREGATION;
        CDynamicWrapper* pObject = new CDynamicWrapper;
        HRESULT hr = pObject->QueryInterface(riid,ppvObject);
        if (FAILED(hr))
          delete pObject;
        return hr;
      }
      STDMETHOD(LockServer)(BOOL fLock)
      { return CoLockObjectExternal(this,fLock,TRUE); }
    };
    
    // DllMain
    extern "C"
    BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
    {
      if (dwReason == DLL_PROCESS_ATTACH)
      {
        m_Server.m_hInstance = hInstance;
        DisableThreadLibraryCalls(hInstance);
      }
      return TRUE;
    }
    
    // Required COM in-proc server exports follow
    STDAPI DllRegisterServer(void)
    {
      LPCSTR CLSIDVAL = "{202774D1-D479-11d1-ACD1-00A024BBB05E}";
      LPCSTR CLASSKEY = 
        "CLSID\\{202774D1-D479-11d1-ACD1-00A024BBB05E}\\InProcServer32";
      LPCSTR PRODIDKEY = "DynamicWrapper\\CLSID";
        HRESULT hr = E_FAIL;
        HKEY key = NULL;
        if (!RegCreateKey(HKEY_CLASSES_ROOT,CLASSKEY,&key))
        {
        char szModulePath[_MAX_PATH];
        GetModuleFileName(m_Server.m_hInstance,szModulePath,
                  _MAX_PATH);
        if(!RegSetValue(key,NULL,REG_SZ,szModulePath,0))
        {
          RegCloseKey(key);
          if (!RegCreateKey(HKEY_CLASSES_ROOT,PRODIDKEY,&key))
          {
            if (!RegSetValue(key,NULL,REG_SZ,CLSIDVAL,0))
              hr = S_OK;
          }
        }
        }
        RegCloseKey(key);
        return hr;
    }
    
    STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
    {
      const GUID CLSID_DynWrap = { 0x202774d1, 0xd479, 0x11d1, 
          { 0xac, 0xd1, 0x0, 0xa0, 0x24, 0xbb, 0xb0, 0x5e } };
      HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
      if (rclsid == CLSID_DynWrap)
      {
        CClassFactory* pFactory = new CClassFactory;
        if (FAILED(hr = pFactory->QueryInterface(riid,ppv)))
          delete pFactory;
        hr = S_OK;
      }
      return hr;
    }
    
    STDAPI DllCanUnloadNow()
    { return (m_Server.m_dwRef) ? S_FALSE : S_OK; }
    
  • 相关阅读:
    loopback 03
    loopback 02
    loopback 01
    node.js整理 02文件操作-常用API
    node.js整理 01代码的组织和部署
    express-21 静态内容
    coffeeScript学习02
    coffeeScript学习01
    jade学习02
    Android 读取Assets中资源
  • 原文地址:https://www.cnblogs.com/songxiii/p/1987164.html
Copyright © 2011-2022 走看看