1

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?

1 Answers1

2

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);
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • That was exactly what I needed. SO strikes again! Thanks :) I think I'll also switch to smart pointers for COM, much neater (didn't know they existed). –  May 17 '13 at 12:55