• 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; }
    
  • 相关阅读:
    37. Sudoku Solver(js)
    36. Valid Sudoku(js)
    35. Search Insert Position(js)
    34. Find First and Last Position of Element in Sorted Array(js)
    33. Search in Rotated Sorted Array(js)
    32. Longest Valid Parentheses(js)
    函数的柯里化
    俞敏洪:我和马云就差了8个字
    vue路由传值params和query的区别
    简述vuex的数据传递流程
  • 原文地址:https://www.cnblogs.com/songxiii/p/1987164.html
Copyright © 2020-2023  润新知