Search code examples
c++com

Create instance failed. Code 80040154 issue when trying to create a component using IDispatch


I am new to COM, I am trying to create a simple c++ console Calendar app. Here is my code:

// CalendarProps.cpp 
//
// DClient.cpp - Dispatch client implementation
// This client connects to the component "Êàëåíäàðü"
// through the dispinterface.
//
#include <windows.h>
#include <stdio.h>
#include <iostream>


int main()
{
    std::cout << "Hello World!\n";
#pragma region Create the component
    //
    DWORD clsctx;

    clsctx = CLSCTX_INPROC_SERVER;
    HRESULT hr = OleInitialize(NULL);

    if (FAILED(hr))
    {
        printf("Failed to initialize Ole. Code %X \n", hr);//+
        return 1;
    }
    // Get the CLSID for the application.
    wchar_t progid1[] = L"MSCAL.Calendar.7";//ProgId - component Id
    CLSID clsid;
    hr = ::CLSIDFromProgID(progid1, &clsid);
    if (FAILED(hr))
    {
        printf("Failed to get CLSID.Code %X \n", hr);//+
        return 1;
    }
    // Create the component.
    IDispatch* pIDispatch = NULL;
    hr = ::CoCreateInstance(clsid,
        NULL,
        clsctx,
        IID_IDispatch,
        (void**)&pIDispatch);
    if (FAILED(hr))
    {
        printf("Create instance failed.Code %X \n", hr);//+
        OleUninitialize();
        return 1;
    }
    printf("CoCreateInstance succeeded.\n");//+

#pragma endregion

#pragma region Get Day
    printf("===============get Day==================\n");

    // First we need to get the IDs for the function names.
    printf("Get DispID for property \"Day\".\n");//+

    DISPID dispid1;
    OLECHAR* name1 = (OLECHAR*)L"Day";//*
    hr = pIDispatch->GetIDsOfNames(IID_NULL,
        &name1,
        1,
        GetUserDefaultLCID(),
        &dispid1);
    if (FAILED(hr))
    {
        printf("Query GetIDsOfNames failed. Code %X \n", hr);//+
        pIDispatch->Release();
        return 1;
    }

    // DISPPARAMS
    DISPPARAMS param1;
    param1.cArgs = 0;                       // Number of arguments
    param1.rgvarg = NULL;                   // Arguments
    param1.cNamedArgs = 0;                  // Number of named args
    param1.rgdispidNamedArgs = NULL;        // Named arguments

    // "Day" 
    VARIANTARG varres1;
    ::VariantInit(&varres1);            // Initialize the VARIANT
    varres1.vt = VT_I2;                 // Type of VARIANT data
    varres1.iVal = 0;                   // Data for the VARIANT

    printf("Get property \"Day\".\n");//+
    hr = pIDispatch->Invoke(dispid1,
        IID_NULL,
        GetUserDefaultLCID(),
        DISPATCH_PROPERTYGET,
        &param1,
        &varres1,//*
        NULL,
        NULL);
    if (FAILED(hr))
    {
        printf("Invoke call failed.Code %X \n", hr);//+
        pIDispatch->Release();
        return 1;
    }

    // Display the returned Value//*
    if (varres1.vt == VT_I2)//*
    {
        printf("Day from Calendar: %d", varres1.iVal);//+
    }
    printf("\n=========================================\n\n");
    /////////////////////////////////////////////////////////
#pragma endregion

#pragma region Put Year
    //HRESULT hr2 = OleInitialize(NULL);
    printf("===============put Year==================\n");

    // First we need to get the IDs for the function names.
    printf("Get DispID for property \"Year\".\n");//+

    DISPID dispid2;
    OLECHAR* name2 = (OLECHAR*)L"Year";//*
    hr = pIDispatch->GetIDsOfNames(IID_NULL,
        &name2,
        1,
        GetUserDefaultLCID(),
        &dispid2);
    if (FAILED(hr))
    {
        printf("Query GetIDsOfNames failed.Code %X \n", hr);//+
        pIDispatch->Release();
        return 1;
    }

    // Allocate and initialize a VARIANT argument.
    VARIANTARG vargs2;//*
    ::VariantInit(&vargs2);             // Initialize the VARIANT.
    vargs2.vt = VT_I2;                  // Type of VARIANT data
    vargs2.iVal = 2023;                 // Data for the VARIANT

    DISPID dispid = DISPID_PROPERTYPUT;  // !!!!!!

    DISPPARAMS param2;
    param2.cArgs = 1;                   // Number of arguments
    param2.rgvarg = &vargs2;            // Arguments
    param2.cNamedArgs = 1;              // Number of named args !!!
    param2.rgdispidNamedArgs = &dispid; // Named arguments !!!!

    printf("Put the property \"Year\".\n");//+
    hr = pIDispatch->Invoke(dispid2,
        IID_NULL,
        GetUserDefaultLCID(),
        DISPATCH_PROPERTYPUT,
        &param2,
        NULL,
        NULL,
        NULL);
    if (FAILED(hr))
    {
        printf("Invoke call failed.Code %X \n", hr);//+
        pIDispatch->Release();
        return 1;
    }
#pragma endregion

#pragma region Display the new Year value
    // Display the new Year value
    // DISPPARAMS Year
    param2.cArgs = 0;                   // Number of arguments
    param2.rgvarg = 0;            // Arguments
    param2.cNamedArgs = 0;              // Number of named args
    param2.rgdispidNamedArgs = 0;   // Named arguments

    VARIANTARG varres2;//*
    ::VariantInit(&varres2);            // Initialize the VARIANT.//*
    varres2.vt = VT_I2;                 // Type of VARIANT data//*
    varres2.iVal = 0;                   // Data for the VARIANT//*

    printf("Get the property \"Year\"\n");//+
    hr = pIDispatch->Invoke(dispid2,
        IID_NULL,
        GetUserDefaultLCID(),
        DISPATCH_PROPERTYGET,
        &param2,
        &varres2,
        NULL,
        NULL);
    if (FAILED(hr))
    {
        printf("Invoke call failed.Code %X \n", hr);
        pIDispatch->Release();
        return 1;
    }
    // Display the returned Year value
    if (varres2.vt == VT_I2)
    {
        printf("Property Year  in component Calendar: %d", vargs2.iVal);
    }
    printf("\n=========================================\n\n");

    // Release the dispatch interface.

#pragma endregion

#pragma region Removing a Component
    // Release the dispatch interface.
    pIDispatch->Release();

    // Uninitialize the OLE library.
    OleUninitialize();
#pragma endregion
    return 0;

}


I have create a reg.file with the stored ProdId and merged it successfully:

    wchar_t progid1[] = L"MSCAL.Calendar.7";//ProgId - component Id

the file has:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\MSCAL.Calendar.7] @="MSCAL.Calendar.7"

[HKEY_CLASSES_ROOT\MSCAL.Calendar.7\CLSID] @="{here I generated GUID using VS GUID tool}"

When I try to run my app, I am getting any issue: issue

Please, help me to find an issue!

I am expecting the COM to be created and my app to be running.


Solution

  • The answer from @Igor Tandetnik was right, I do not need to register any other ProdId, coz mine example is already installed on my machine.

    There would also need to be a key HKEY_CLASSES_ROOT\CLSID{Your actual GUID here}, and under that key, the details of where and how the component is actually implemented. Taking a step back, MSCAL.Calendar.7 sounds like some component provided by Microsoft - why are you making up a GUID for it? If it's installed on your machine, the necessary registry entries should already be present. If it's not installed on your machine, then making up random registry keys won't magically conjure it up.