C++でのCreateObject
2006年1月19日
前の記事の続き。IDispatchの取得方法。
C++で"WScript.Shell"オブジェクトを作成し、Invokeで"CurrentDirectory"プロパティを取得してみた。
実行結果

C++で"WScript.Shell"オブジェクトを作成し、Invokeで"CurrentDirectory"プロパティを取得してみた。
#include <windows.h>
UINT HexToByte(LPSTR hex,int pos){
UINT b1,b2;
static const LPSTR ZeroToF="0123456789ABCDEFabcdef";
for (b1=0;hex[pos]!=ZeroToF[b1];b1++);
if (15<b1) b1=b1-6;
for (b2=0;hex[pos+1]!=ZeroToF[b2];b2++);
if (15<b2) b2=b2-6;
return (b1<<4)+b2;
}
IDispatch* CreateObject(LPSTR ComName){
int i,j;
char ANSI[MAX_PATH];
//Resolve DLL file name
HKEY key;
CLSID clsid;
for (i=0;ANSI[i]=ComName[i];i++);
for (j=0;ANSI[i]="\\CLSID"[j++];i++);
if (ERROR_SUCCESS!=RegOpenKeyEx(HKEY_CLASSES_ROOT,ANSI,0,KEY_READ,&key)) return 0;
for (i=0;ANSI[i]="CLSID\\"[i];i++);
i=MAX_PATH-6;
if (ERROR_SUCCESS!=RegQueryValueEx(key,NULL,0,NULL,(LPBYTE)(ANSI+6),(LPDWORD)&i)) return 0;
RegCloseKey(key);
for (i=0;ANSI[i];i++);
for (j=0;ANSI[i]="\\InProcServer32"[j++];i++);
if (ERROR_SUCCESS!=RegOpenKeyEx(HKEY_CLASSES_ROOT,ANSI,0,KEY_READ,&key)) return 0;
clsid.Data1=(((((HexToByte(ANSI,7)<<8)+HexToByte(ANSI,9))<<8)+HexToByte(ANSI,11))<<8)+HexToByte(ANSI,13);
clsid.Data2=(HexToByte(ANSI,16)<<8)+HexToByte(ANSI,18);
clsid.Data3=(HexToByte(ANSI,21)<<8)+HexToByte(ANSI,23);
for (i=0;i<2;i++) clsid.Data4[i]=HexToByte(ANSI,26+i*2);
for (i=2;i<8;i++) clsid.Data4[i]=HexToByte(ANSI,27+i*2);
i=MAX_PATH;
if (ERROR_SUCCESS!=RegQueryValueEx(key,NULL,0,NULL,(LPBYTE)ANSI,(LPDWORD)&i)) return 0;
RegCloseKey(key);
//Load DLL & check DllGetClassObject
HINSTANCE hDLL;
void* Address;
if (!(hDLL=LoadLibrary(ANSI))) return 0;
if (!(Address=GetProcAddress(hDLL,"DllGetClassObject"))) return 0;
//DllGetClassObject(&clsid,IID_IClassFactory,(LPVOID*)&ppv);
IClassFactory* ppv=0;
void *Stack1,*Stack2,*Stack3;
Stack3=&ppv;
Stack2=(void*)&IID_IClassFactory;
Stack1=&clsid;
_asm push Stack3;
_asm push Stack2;
_asm push Stack1;
_asm call Address;
_asm mov i,eax;
if (i!=S_OK || !ppv) return 0;
IDispatch* ppvObject=0;
if (S_OK!=ppv->QueryInterface(IID_IClassFactory, (void**) &ppv)) return 0;
ppv->Release();
if (S_OK!=ppv->CreateInstance(NULL,IID_IUnknown,(void**)&ppvObject)) return 0;
ppv->Release();
if (!ppvObject) return 0;
if (S_OK!=ppvObject->QueryInterface(IID_IDispatch,(void**)&ppvObject)) return 0;
ppvObject->Release();
return ppvObject;
}
WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int intShowCmd) {
IDispatch* pDisp=CreateObject("WScript.Shell");
if (!pDisp) return 1;
LPOLESTR* rgszNames;
rgszNames=new LPOLESTR;
DISPID* rgDispId;
rgDispId=new DISPID;
rgszNames[0]=L"CurrentDirectory";
int ret=pDisp->GetIDsOfNames(GUID_NULL, rgszNames,1, NULL, rgDispId);
if (ret!=S_OK) return ret;
DISPPARAMS* pDispParams;
VARIANT* pVarResult;
pDispParams=new DISPPARAMS;
pVarResult=new VARIANT;
pDispParams->rgdispidNamedArgs = NULL;
pDispParams->cNamedArgs = 0;
pDispParams->cArgs=0;
pDispParams->rgvarg=NULL;
ret=pDisp->Invoke(rgDispId[0], GUID_NULL, NULL,DISPATCH_PROPERTYGET,pDispParams, pVarResult,NULL, NULL);
if (ret!=S_OK) return ret;
if (pVarResult->vt!=VT_BSTR) return 1;
MessageBoxW(0,pVarResult->bstrVal,L"CurrentDirectory",0);
return 0;
}実行結果

コメント
Kat (2008年7月6日 16:11:33)
このコードでは問題ないが、利用するCOMオブジェクトによっては、
OleInitialize(NULL);
を最初に実行しておかないと、うまく働かないことがある。msscript.ocx(ScriptControl)などがそれ。
参考:
http://msdn.microsoft.com/en-us/library/ms690134(VS.85).aspx
OleInitialize(NULL);
を最初に実行しておかないと、うまく働かないことがある。msscript.ocx(ScriptControl)などがそれ。
参考:
http://msdn.microsoft.com/en-us/library/ms690134(VS.85).aspx