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; }

转载于:https://www.cnblogs.com/songxiii/archive/2011/03/17/1987164.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值