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