How do I use IFileSystemImage2's put_BootImageOptionsArray from IMAPI2 (getting E_NOINTERFACE)?

StackOverflow https://stackoverflow.com/questions/16607787

  •  29-05-2022
  •  | 
  •  

Question

I am trying to use the IFileSystemImage2 interface to create an ISO with multiple boot records using Imapi2.

To do this, I should be able to use put_BootImageOptionsArray passing in SAFEARRAY* of VT_DISPATCH type, i.e. COM pointers of type IBootOptions for each boot options configuration. As a short demo, I have the following code (I only created one IBootOptions in this case):

SAFEARRAYBOUND bounds[1];
bounds[0].cElements = 1;
bounds[1].lLbound = 0;
IBootOptions* BootOptionsArrayData = NULL;


SAFEARRAY* Array = SafeArrayCreateEx(VT_DISPATCH, 
                                     1, 
                                     bounds, 
                                     (void*) &IID_IBootOptions);
hr = SafeArrayAccessData(Array, 
                         reinterpret_cast<void**>(&BootOptionsArrayData));

BootOptionsArrayData = BootOptions; // BootOptions = IBootOptions*
hr = SafeArrayUnaccessData(Array);

hr = IsoImage->put_BootImageOptionsArray(Array);

However, every time I call put_BootImageOptionsArray I get E_NOINTERFACE returned.

IsoImage is being created as you'd expect:

hr = CoCreateInstance(CLSID_MsftFileSystemImage, 
                      NULL, 
                      CLSCTX_ALL, 
                      __uuidof(IFileSystemImage2), 
                      (void**) &IsoImage);

Using IFileSystemImage2 any inherited functionality from IFileSystemImage works fine. Likewise, I can CoCreateInstance a IFileSystemImage instead, and this interface can be used just fine.

I have attached to my process in WinDbg and set a breakpoint in CMsftFileSystemImage::put_BootOptionsArray, however, this function (the underlying implementation) simply isn't being called.

My question, therefore is simple: the implementation appears to be there, but I don't seem to be able to call it. Does anyone have any experience of using this particular bit of functionality and if so how did you get it to work?

Was it helpful?

Solution

The documentation stipulates the SAFEARRAY must be an array of VARIANT that contain IDispatch interface pointers, so you could do something like this (I'm using smart pointers which is easier...):

CComPtr<IFileSystemImage2> image;
CComPtr<IBootOptions> options;

image.CoCreateInstance(CLSID_MsftFileSystemImage);
options.CoCreateInstance(CLSID_BootOptions);

// set various options here...
options->put_Manufacturer(CComBSTR(L"joe"));

// create a SAFEARRAY of VARIANT
CComSafeArray<VARIANT> a(1);

// create a VARIANT of type VT_UNKNONW (or VT_DISPATCH)
CComVariant v(options);

// put it in the array
a.SetAt(0, v);

HRESULT hr = pImage->put_BootImageOptionsArray(a.m_psa);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top