views:

92

answers:

3

I want to programaticly retreive the Interface ID for any or any class so that I can pass it to CoCreateInstance. Any help is very much so appreciated!!

See "How Do I Get This" below:

HRESULT hResult;
CLSID ClassID;
void *pInterface;

if(!(hResult = SUCCEEDED(CoInitialize(NULL))))
{
    return 1;
}

if(S_OK == CLSIDFromProgID(OLESTR("Scripting.FileSystemObject"), &ClassID))
{
    hResult = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER,
        <<How Do I Get This?>>, (LPVOID *)&pInterface);
}

CoUninitialize();

EDIT, Thanks for all of the help, Seems to work perfectly now! :

HRESULT hResult;
CLSID ClassID;
IClassFactory *pClf;
void *pVdb;

if(!(hResult = SUCCEEDED(CoInitialize(NULL))))
{
    return 1;
}

if(SUCCEEDED(CLSIDFromProgID(OLESTR("Scripting.FileSystemObject"), &ClassID))
{
    IDispatch *pDispatch;

    if(SUCCEEDED(CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER,
            IID_IDispatch, (void **)&pDispatch))
    {
        OLECHAR *sMember = L"FileExists";

        DISPID idFileExists;

        if(SUCCEEDED(pDispatch->GetIDsOfNames(
                IID_NULL, &sMember, 1, LOCALE_SYSTEM_DEFAULT, &idFileExists))
        {
            unsigned int puArgErr = 0;

            VARIANT VarResult;
            EXCEPINFO pExcepInfo;

            VariantInit(&VarResult); 
            VariantInit(&pExcepInfo); 

            DISPPARAMS pParams;
            memset(&pParams, 0, sizeof(DISPPARAMS)); 
            pParams.cArgs = 1; 

            VARIANT Arguments[1];
            VariantInit(&Arguments[0]); 

            pParams.rgvarg = Arguments; 
            pParams.cNamedArgs = 0;
            pParams.rgvarg[0].vt = VT_BSTR;
            pParams.rgvarg[0].bstrVal = SysAllocString(L"C:\\Test.txt");

            hResult = pDispatch->Invoke(  
                idFileExists,
                IID_NULL,
                LOCALE_SYSTEM_DEFAULT,
                DISPATCH_METHOD,
                &pParams,
                &VarResult,
                &pExcepInfo,
                &puArgErr
            );

            SysFreeString(pParams.rgvarg[0].bstrVal);

            printf("File Exists? %d\n", abs(VarResult.boolVal));
        }

        pDispatch->Release();
    }
}

CoUninitialize();
+1  A: 

platform SDK is distributed with source code of OleView utility, t contains pretty good example to build tree of all possible CLSIDs and them names

Dewfy
+1  A: 

You need to know upfront what interface you ask for. This you get from the product specifications, from SDK header files, or you can import the TLB of the COM object into your project.

the easisest way is to use #import

Remus Rusanu
If it has to be know upfront, then how can I write a COM DLL in C++ and use it in Classic ASP via Server.CreateObject()? Classic ASP seems to be able to bind to my DLL and interface with it allowing me to call functions within my class.
NTDLS
Because ASP asks for a well knonw interface, IDispatch http://msdn.microsoft.com/en-us/library/ms221608.aspx
Remus Rusanu
Exactly. Using the question from my answer: "Which interface's methods are you going to call on it?" The answer is IDispatch, so you ask for that interface from CoCreateInstance. You then use IDispatch's methods to call other methods whose names and parameters you didn't know at compile time.
Rob Kennedy
Sweet, IDispatch was the Answer! Why not throw that in the awnser so other people can find it without digging through the comments. Thanks-a-million!
NTDLS
+1  A: 

You already know it. It's going to be the compile-time output type that you want the function to store in the pInterface variable that you've given it.

In other words, what interface type are you going to treat that object you've created as? Which interface's methods are you going to call on it?

The type you get from CLSIDFromProgID might be any version of the interface, including one that didn't even exist at the time you compiled your code. You can usually assume that whatever version is available at run time also supports some lesser version that you know about at compile time. You ask the OS to instantiate an instance of the recent version, but then you also ask it to return a reference to the lesser version's interface — the one you know how to handle.

The function calls QueryInterface on the object for you, using the type you requested, something like this:

obj->QueryInterface(riid, pInterface);

If you have nothing more specific to request, just use IUnknown.

Rob Kennedy