设为首页 收藏本站
查看: 756|回复: 0

[经验分享] PHP调用C++制作的非COM组件DLL

[复制链接]

尚未签到

发表于 2015-8-26 15:17:30 | 显示全部楼层 |阅读模式
  下载DynaWrap.dll  http://download.iyunv.com/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.iyunv.com/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.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.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.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].size;
if (Parm->nWidth > 4)
Parm->dwFlags = DC_FLAG_ARGPTR;
// Parameter value
VariantClear(&va);
hr = VariantChangeType(&va,&rgvarg,0,ArgInfo[iArg].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].vt)
{
case (VT_I4): // Handle
if (rgvarg.vt <= VT_NULL)
Parm->pArg = 0;
else
hr = E_INVALIDARG;
break;
case (VT_LPSTR):
Parm->pArg = W2A(rgvarg.bstrVal);
break;
case (VT_LPWSTR):
Parm->pArg = rgvarg.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.wMask) | FlagInfo.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 = m_Chain.FindDISPID(rgszNames);
if (rgDispId == 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; }

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-104583-1-1.html 上篇帖子: PHP中的正则表达式 下篇帖子: PHP Socket Server端例子
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表