Click here to Skip to main content
Click here to Skip to main content

Burning CD/DVD Media with the Image Mastering API Version 2.0 (IMAPI2)

By , 12 Dec 2009
 
Prize winner in Competition "Best C++/MFC article of December 2007"

Introduction

If you are looking for a sample in C#/.NET, then check out my article: "Burning and Erasing CD/DVD Media with C# and IMAPI2".

Windows introduced the new IMAPIv2.0 with the release of the Vista Operating System, which was a big improvement over the original IMAPI. The original IMAPI is great for CDROMs, but it has some huge limitations like not being able to write to DVD media. I am sure this limitation is due to almost nobody having a DVD writer when Windows XP was released back in 2001. IMAPIv2 allows you to write to CD and DVD media, as well as read and write ISO files. IMAPIv2.0 had a problem since it was only available with Windows Vista. But in June of 2007, Microsoft released update packages for Windows XP and Windows 2003. You can download the updates here.

You will also need to download and install the Microsoft Windows Software Development Kit to get the header files necessary to compile the application. You can download the SDK here.

After you download and install the SDK, you will need to make sure the SDK's include directory is in Visual Studio's Include path. When using Visual Studio 2005, you must also make the SDK's LIB path as the first entry in the LIB directory list.

Anybody wanting to develop a full application should also read the "Joliet Recording Specification".

Using the Code

I have created several wrappers around the IMAPIv2 interfaces to assist in managing instances of the interfaces:

CDiscMaster wraps the IDiscMaster2 interface which allows you to determine if the computer has any optical devices installed, and if so, allows you to enumerate the CD and DVD drives installed on the computer.

CDiscRecorder wraps the IDiscRecorder2 interface which represents each physical drive. You use this interface to retrieve information about the drive including manufacturer information, logical drive, and supported media.

CDiscFormatData wraps the IDiscFormat2Data interface which is used to write data to the media.

CDiscFormatDataEvent wraps the DDiscFormat2DataEvents notifications which is used to receive the status of the IDiscFormat2Data write function.

For the file system, I created a base class CBaseObject which has three functions: GetPath(), GetName(), and GetSizeOnDisc(). GetPath returns the full path of the file or directory on the computer. GetName returns just the filename of the file or the directory which is used for display purposes, and is also used as the name of the file or directory in the root directory of the recorded image. GetSizeOnDisc is a pure virtual function that the two classes that are derived from CBaseObject, CFileObject, and CDirObject, implement. CFileObject returns the size the file will use on the media. CDirObject returns the size of all files and subdirectories of the directory.

I will cover a few main points here, but you should download the source code to see all the code.

You will need to include the imapi2 header files in your application:

#include <imapi2.h>
#include <imapi2error.h>
#include <imapi2fs.h>
#include <imapi2fserror.h>

imapi2.h and imapi2error.h are needed for the imapi2 interfaces. imapi2fs.h and imapi2fserror.h are needed for the imapi2 file system interfaces.

Then, I create an instance of the CDiscMaster class, initialize it, and get the unique ID for each device. The unique ID is used to initialize a CDiscRecord object, and I use that to get display information for the combobox entry and store the pointer for the item data.

CDiscMaster discMaster;
.
.
discMaster.Initialize();
.
.
long totalDevices = discMaster.GetTotalDevices();
for (long deviceIndex = 0; deviceIndex < totalDevices; deviceIndex++)
{
 CString recorderUniqueID = discMaster.GetDeviceUniqueID(deviceIndex);
 CDiscRecorder* pDiscRecorder = new CDiscRecorder();
 pDiscRecorder->Initialize(recorderUniqueID);
 //
 // Get the volume path(s). usually just 1
 //
 CString volumeList;
 ULONG totalVolumePaths = pDiscRecorder->GetTotalVolumePaths();
 for (ULONG volIndex = 0; volIndex < totalVolumePaths; volIndex++)
 {
  if (volIndex)
   volumeList += _T(",");
  volumeList += pDiscRecorder->GetVolumePath(volIndex);
 }
 //
 // Add Drive to combo and IDiscRecorder as data
 //
 CString productId = pDiscRecorder->GetProductID();
 CString strName;
 strName.Format(_T("%s [%s]"), (LPCTSTR)volumeList, (LPCTSTR)productId);
 int comboBoxIndex = m_deviceComboBox.AddString(strName);
 m_deviceComboBox.SetItemDataPtr(comboBoxIndex, pDiscRecorder);
}

When an item is selected in the device combobox, I get the CDiscRecorder object of the selected device, which I placed in the item's data. I then use the CDiscRecorder object to get the supported media types. The supported media types return an integer that is defined in the enum IMAPI_MEDIA_PHYSICAL_TYPE type. Since I get values like IMAPI_MEDIA_TYPE_DVDPLUSR and IMAPI_MEDIA_TYPE_DVDDASHR, I have three member variables (m_isCdromSupported, m_isDvdSupported, and m_isDualLayerDvdSupported) that I set to true if any media in the family is supported. I then add these media types to a media type combobox and let users select what type of media they are going to use. I then use a very "rough" estimate to determine how much of the media the user has filled up.

void CBurnCDDlg::OnCbnSelchangeDeviceCombo()
{
  m_isCdromSupported = false;
  m_isDvdSupported = false;
  m_isDualLayerDvdSupported = false;
  m_mediaTypeCombo.ResetContent();
  int selectedIndex = m_deviceComboBox.GetCurSel();
  ASSERT(selectedIndex >= 0);
  if (selectedIndex < 0)
  {
   return;
  }
  CDiscRecorder* discRecorder =
   (CDiscRecorder*)m_deviceComboBox.GetItemDataPtr(selectedIndex);
  if (discRecorder != NULL)
  {
   CDiscFormatData discFormatData;
   if  (!discFormatData.Initialize(discRecorder, CLIENT_NAME))
   {
    return;
   }
   //
   // Display Supported Media Types
   //
   CString supportedMediaTypes;
   ULONG totalMediaTypes = discFormatData.GetTotalSupportedMediaTypes();
   for (ULONG volIndex = 0; volIndex < totalMediaTypes; volIndex++)
   {
    int mediaType = discFormatData.GetSupportedMediaType(volIndex);
    if (volIndex > 0)
     supportedMediaTypes += _T(", ");
    supportedMediaTypes += GetMediaTypeString(mediaType);
   }
   m_supportedMediaTypes.SetWindowText(supportedMediaTypes);
   //
   // Add Media Selection
   //
   if (m_isCdromSupported)
   {
    int stringIndex = m_mediaTypeCombo.AddString(_T("700MB CD Media"));
    m_mediaTypeCombo.SetItemData(stringIndex, CD_MEDIA);
   }
   if (m_isDvdSupported)
   {
     int stringIndex = m_mediaTypeCombo.AddString(_T("4.7GB DVD Media"));
     m_mediaTypeCombo.SetItemData(stringIndex, DVD_MEDIA);
   }
   if (m_isDualLayerDvdSupported)
   {
    int stringIndex = m_mediaTypeCombo.AddString(_T("8.5GB Dual-Layer DVD"));
    m_mediaTypeCombo.SetItemData(stringIndex, DL_DVD_MEDIA);
   }
   m_mediaTypeCombo.SetCurSel(0);
   OnCbnSelchangeMediaTypeCombo();
  }
}

When the user adds a file to the list, I create a CFileObject and I add it to the file listbox. I then call the UpdateCapacity function which calculates the total storage required by all the items in the file listbox and update the capacity progress bar.

void CBurnCDDlg::OnBnClickedAddFilesButton()
{
  CFileDialog fileDialog(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, _T
        ("All Files (*.*)|*.*||"), NULL, 0);
  if (fileDialog.DoModal() == IDOK)
  {
    CFileObject* pFileObject = new CFileObject(fileDialog.GetPathName());
    int addIndex = m_fileListbox.AddString(pFileObject->GetName());
    m_fileListbox.SetItemDataPtr(addIndex, pFileObject);
    UpdateCapacity();
    EnableBurnButton();
  }
}

When the user adds a folder to the list, I create a CDirObject and I add it to the file listbox. Just like the file object, I call the UpdateCapacity function to calculate the total storage required by all the items in the file listbox and update the capacity progress bar.

void CBurnCDDlg::OnBnClickedAddFolderButton()
{
  BROWSEINFO bi = {0};
  bi.hwndOwner = m_hWnd;
  bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_USENEWUI;
  LPITEMIDLIST lpidl = SHBrowseForFolder(&bi);
  if (!lpidl)
    return;
  TCHAR selectedPath[_MAX_PATH] = {0};
  if (SHGetPathFromIDList(lpidl, selectedPath))
  {
    CDirObject* pDirObject = new CDirObject(selectedPath);
    int addIndex = m_fileListbox.AddString(pDirObject->GetName());
    m_fileListbox.SetItemDataPtr(addIndex, pDirObject);
    UpdateCapacity();
    EnableBurnButton();
  }
}

When the user presses the Burn button, I disable the user interface and launch another thread, BurnThread, to perform the burn. This will keep the UI responsive during the burn process.

void CBurnCDDlg::OnBnClickedBurnButton()
{
  if (m_isBurning)
  {
    SetCancelBurning(true);
  }
  else
  {
    SetCancelBurning(false);
    m_isBurning = true;
    UpdateData();
    EnableUI(false);
    AfxBeginThread(BurnThread, this, THREAD_PRIORITY_NORMAL);
  }
}
UINT CBurnCDDlg::BurnThread(LPVOID pParam)
{
  IStream* dataStream = NULL;
  CBurnCDDlg* pThis = (CBurnCDDlg*)pParam;
  if (!CreateMediaFileSystem(pThis, &dataStream))
  { // CreateMediaFileSystem reported error to UI
   return false;
  }
  //
  // Get the selected recording device from the combobox
  //
  int selectedIndex = pThis->m_deviceComboBox.GetCurSel();
  ASSERT(selectedIndex >= 0);
  if (selectedIndex < 0)
  {
    pThis->SendMessage(WM_BURN_FINISHED, 0, 
      (LPARAM)_T("Error: No Device Selected"));
    return 0;
  }
  CDiscRecorder* pOrigDiscRecorder =
    (CDiscRecorder*)pThis->m_deviceComboBox.GetItemDataPtr(selectedIndex);
  if (pOrigDiscRecorder == NULL)
  {
    //
    // This should never happen
    //
    pThis->SendMessage(WM_BURN_FINISHED, 0,
        (LPARAM)_T("Error: No Data for selected device"));
    return 0;
  }
  //
  // Did user cancel?
  //
  if (pThis->GetCancelBurning())
  {
    pThis->SendMessage(WM_BURN_FINISHED, 0, (LPARAM)_T("User Canceled!"));
    return 0;
  }
  pThis->SendMessage(WM_BURN_STATUS_MESSAGE, 0,
        (LPARAM)_T("Initializing Disc Recorder..."));
  //
  // Create another disc recorder because we're in a different thread
  //
  CDiscRecorder discRecorder;
  CString errorMessage;
  if (discRecorder.Initialize(pOrigDiscRecorder->GetUniqueId()))
  {
    //
    //
    //
    if (discRecorder.AcquireExclusiveAccess(true, CLIENT_NAME))
    {
     CDiscFormatData discFormatData;
     if (discFormatData.Initialize(&discRecorder, CLIENT_NAME))
     {
      discFormatData.SetCloseMedia(pThis->m_closeMedia ? true : false);
      //////////////////////////////
      //
      // Burn the media here
      //
      discFormatData.Burn(pThis->m_hWnd, dataStream);
      //
      // Release the IStream after burning
      //
      dataStream->Release();
      //
      // Eject Media if they chose
      //
      if (pThis->m_ejectWhenFinished)
      {
       discRecorder.EjectMedia();
      }
     }
     discRecorder.ReleaseExclusiveAccess();
     //
     // Finished Burning, GetHresult will determine if it was successful or not
     //
     pThis->SendMessage(WM_BURN_FINISHED, discFormatData.GetHresult(),
      (LPARAM)(LPCTSTR)discFormatData.GetErrorMessage());
    }
    else
    {
     errorMessage.Format(_T("Failed: %s is exclusive owner"),
      (LPCTSTR)discRecorder.ExclusiveAccessOwner());
     pThis->SendMessage(WM_BURN_FINISHED, discRecorder.GetHresult(),
      (LPARAM)(LPCTSTR)errorMessage);
    }
   }
   else
   {
    errorMessage.Format(_T("Failed to initialize recorder - Unique ID:%s"),
     (LPCTSTR)pOrigDiscRecorder->GetUniqueId());
    pThis->SendMessage(WM_BURN_FINISHED, discRecorder.GetHresult(),
     (LPARAM)(LPCTSTR)errorMessage);
   }
   return 0;
}

UI Notifications

The worker thread communicates with the UI via SendMessage commands. I send Status Messages (WM_BURN_STATUS_MESSAGE) and Burn Finished (WM_BURN_FINISHED) messages from the worker thread to the UI.

I send event notifications to the UI with a WM_IMAPI_UPDATE message from the CDiscFormatDataEvent::Update function. I create an instance of the CDiscFormatDataEvent class, which implements the DDiscFormat2DataEvents interface, in the CDiscFormatData::Burn function. When it receives an event, it gets the data and sends it to the UI so it can update the status.

History

  • v1 - Dec 29, 2007

    • Initial release.
  • v2 - Jan 8, 2008

    • Converted project from Visual Studio 2008 to Visual Studio 2005.
    • Removed ATL from the CDiscFormatDataEvent class.
    • Sample application statically linked with MFC DLLs.

    v3 - Jan 16, 2008

    • Bug fix - Not setting image to size of media.
    • Supports extra large files. Thanks Dale Stewart.
    • Does not assert when InitializeDiscRecorder fails because of Virtual CDROMs, etc.
  • v4 - Dec 12, 2009

    • Updated the link to the latest Windows SDK.
    • Fixed a leak where an IStream wasn't being released.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Eric Haddan
Software Developer (Senior) Tranxition Corp
United States United States
Member
Thank you for voting on my articles!
 
MCSD.NET in C#
 
LinkedIn[^]
 
The Tranxition Developer's Blog[^]

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Layout  Per page   
Questionerror-code-0x80004005memberDaryappa22 May '13 - 21:55 
While writing/burning data to disc, i have encountered error-code-0x80004005. After this error my DVD is no more usable. System goes in infinite loop when I click the DVD drive and can not access it. Please let me know what to do to avoid this error.
 
Thanks,
Daryappa
QuestionStash filememberMember 974141211 Apr '13 - 23:37 
Hello,
 
I'm writting my own application inspired from your code (great article! Thx!! Smile | :) ) but I have an issue with the stash file.
 
When I use the "AddTree" method (or "AddFile" method - I have two ways for building my image file system) and the file to add is "big" (180 Mb for example), the method failed with a general IMAPI error (IMAPI_E_STASHFILE_WRITE_FAILURE - 0xC0AAB13A).
 
In retrieving the working directory ("get_WorkingDirectory" method) I can see the "stash file" growing and getting bigger until the program fails.
The reason is a lack of space on my hard drive, which cannot be modified (150 Mb only are available!!).
 
1) Is there a way to burn "on the fly" with IMAPI2?
2) The "put_stageFiles" method returns "NOT_IMPL". Is that really the case in IMAPI2?? Could it be usefull anyway?
 
Thx for your help!
QuestionError Readable CD or dvd for burning data againmembergauri_21vaidya23 Aug '12 - 21:26 
If i am using the same Readable CD or dvd for burning data again.
 
It shows following error.
 
An exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll but was not handled in user code
 
Additional information: Cross-thread operation not valid: Control 'MainForm' accessed from a thread other than the thread it was created on.
QuestionWindows 7 with IMAPI2membertantle1 Feb '12 - 8:50 
I am incorporating IMAPI2 into a software package to be used on Windows XP and Windows 7.
 
The host code is written in Java 1.5.0_21 and uses JNI to communication with the IMAPI. I have also used Java 1.6.0_22 – the version of Java seems to be irrelevant. The IMAPI interface is written using Microsoft Visual C++ 2008. The versions of IMAPI2 for XP with SP2 and SP3 work fine consistently. The media type is CD-R.
 
When running the software with Windows 7, I get inconsistent behavior writing the same image. Sometimes the data is written to the CD with no errors and sometimes it crashes with a large traceback dumping to a file such as “hs_err_pid2312” (see details below).
 
The version of IMAPI2.DLL, IMAPI2FS.DLL and CDROM.SYS files for Windows 7 with no service pack is 6.1.7600.16385 dated 7/13/2009
The version of these files with SP1 is 6.1.7601.17514 dated 11/20/2010.
It always fails at the same location with both versions. The API method that is being called at the time of failure is AddFile in the IFsiDirectoryItem interface. I have a check for the return value upon completion of this method, but the problem upon failure is that it never returns. If I am passing bad data into the method, I would expect to receive one of the error return codes that I could check and report an error. I can run it twice back to back one may succeed and one may fail. I have found no particular pattern.
When it crashes, the traceback always shows [imapi2fs.dll+0x60e9e]
 
----------------------------- FULL DETAILS -------------------------------------------
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x693e0e9e, pid=2312, tid=2684
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_21-b01 mixed mode, sharing)
# Problematic frame:
# C [imapi2fs.dll+0x60e9e]
----------------------------------------------------------------------------------------------
 
Has anyone experienced something similar to this and found a solution?
Is there a way to find out what is actually failing by the IMAPI2FS.DLL offset value of 0x60e9e?
 
Thanks
Terry
QuestionWrite SpeedmemberMember 849723420 Dec '11 - 2:49 
Hello, I think this tool is great.
 
Is it possible to add the write speed?
 
I have add a ComboBox to the GUI and I have found this:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364891%28v=vs.85%29.aspx
 
How can I get the Data from the Recorder and fill the ComboBox?
How can I set the Write Speed to the Recorder?
QuestionBorland 6.0 Imapi2memberstankomix122 Nov '11 - 23:26 
I tried to build this application in BCB 6.0, but have some problem with Imapi2.h, can't compile that. Show me some error base on __RPC. I also tried with Import Type Library and make Imapi2_tlb and Imapi2fs_tlb. Then have a problem with create interface, CoCreateInstance() function return NULL.
How I can bild this application in Borland? My OS is XP SP2 + KB932716
QuestionError 0x80040154memberMember 79192399 Nov '11 - 10:39 
I downloaded your executable file and attempted to run it on Win XP SP 3. I am getting an error that says "Unable to Initialize IDiscMaster2 - Error:0x80040154".
GeneralUnable to Initialize IDiscMaster2 - Error:0x800401f0memberPraChauhan20 Apr '11 - 20:13 
I remade a whole new project as practice but now that I have it all up and running I keep getting this error:
Unable to Initialize IDiscMaster2 - Error:0x800401f0 in VS 2008.
 
It's from
 

if (m_discMaster == NULL)
{
m_hResult = CoCreateInstance(__uuidof(MsftDiscMaster2), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IDiscMaster2), (void**)&m_discMaster);
if (!SUCCEEDED(m_hResult))
{
m_errorMessage.Format(_T("Unable to Initialize IDiscMaster2 - Error:0x%08x"), m_hResult);
return false;
}
}
 
I am using Win XP SP3.
Please give any suggestion.
.
GeneralRe: Unable to Initialize IDiscMaster2 - Error:0x800401f0memberxbanana8 May '11 - 12:06 
I justed stumbled over the same error.
 
You need to call 'CoInitialize' before invoking 'CoCreateInstance'.
Look for the following line in the demo project to see where best to put it:
 
::CoInitializeEx(NULL, COINIT_MULTITHREADED);
GeneralRe: Unable to Initialize IDiscMaster2 - Error:0x800401f0memberjiachangyu08 Feb '12 - 22:54 
CO_E_NOTINITIALIZED
0x800401F0 CoInitialize has not been called.
GeneralRe: Unable to Initialize IDiscMaster2 - Error:0x800401f0memberjiachangyu08 Feb '12 - 22:55 
Big Grin | :-D CO_E_NOTINITIALIZED
0x800401F0   CoInitialize has not been called.
QuestionMultisession?memberaravindkrgec8 Mar '11 - 22:06 
Hi, This was very informative. But I thought you said in an earlier post that multisession is not supported. Can you please say how to add it to this code.
GeneralWindows XP SP3 + IMAPIv2.0 for Windows XP SP2 SP3 (KB932716) - ERRORmemberpasztor.laszlo20 Feb '11 - 21:39 
Hi!
 
I want to use this app under Windows XP SP3. I downloaded and isntalled IMAPIv2.0 for Windows XP SP2 SP3 (KB932716).
 
The app seems to work (erases disc, writes disc), but on startup I always got the following error message:

Error: -2147467259 - Please, install IMAPI2!
 
Error HRESULT E_FAIL has been returned from a call to a COM component.

 
Under Win7 it works without any errors.
But I need it to work under XP.
 
Could anyone help me how to solve this?
Thanks!
Generalbackup files to CDmemberLoAnn8 Dec '10 - 10:58 
Hi, I tried to use your application to backup files to CD but it doesn't work. First of all, if I select the "Close Media" then I am unable to burn more files to the same CD. If I leave it un-close (not selecting Close Media), I can write additional files/folders the second time around but it mess up the whole CD, and even my CD/DVD drive. My drive doesn't recognize any CD there after. I have to restart my computer in order for the CD drive to work again. Do you have any suggestion on how to backup files to CD? I need a software where I can write the several files to CD at different time/interval.
Thank you.
QuestionCoCreateInstance ErrormemberZhang Long24 Oct '10 - 18:59 
I got Error: "Unable to Initialize IDiscMaster2 - Error : 0x80040154" (Class not registered). What can I do?
AnswerRe: CoCreateInstance Errormemberherowolf1 Jun '11 - 23:24 
reg imapi2.dll and imapi2fs.dll.
QuestionHow to read cd / dvd manufacturer using IMAPI / IMAPI v2 ?????memberjavadpro212 Jun '10 - 19:14 
As you know CDs have ATIP ( DVDs have ADIP ) that contains disc manufacturer , capacity and . . .
 
i need to read CD / DVD manufacturer of blank and writed CDs ( and DVDs if possible) with IMAPI / IMAPI v2
 
please post some code to do this .
 
thanks
GeneralEnhanced VersionmemberNic Wilson11 Jun '10 - 19:39 
Hi,
 
I have taken your source code as a base and I have making major enhancements to it such as adding, ISO write, added BD-R/RE writing into it, auto detection of media type, auto setting of progress values, auto calculation of actual number of sectors available and setting progress bars accordingly. I plan to do a lot more customization of the entire program and turn it into a fully usable suite. I plan to then eventually release it probably as freeware. Unless you have any objections.
 
You may contact me directly at nic@nicwilson.com if you feel the need.
 
Thanks for the base code, it saved heaps of time in starting such a project from scratch.
 
regards
NicW
GeneralRe: Enhanced Versionmemberbayview16 Sep '10 - 11:51 
I downloaded this souce code and built it on vista sp2. The excuteable crashed on AddFile. Do you have this problem?
 
Even I ran the excutable BurnCD.exe from the download, it also crashed on AddFile.
 
I am using Visual Studio 8.
 
Thanks.
 
bayview
GeneralRe: Enhanced Versionmemberbayview16 Sep '10 - 12:17 
Forget my previous email. I figured out why.
GeneralCreating ISO imagememberpodeeshk5 Apr '10 - 23:26 
Using IMAPI Can we create ISO image of a DVD in c++? How it is possible.Give me sample code and tips.Thanks in advance
QuestionHow to connect IDiscFormat2Data and DDiscFormat2DataEvents without MFC or ATL?memberguardianoc9 Mar '10 - 23:01 
How can I connect IDiscFormat2Data and DDiscFormat2DataEvents without usage of MFC or ATL?
 
Thanks in advance!
AnswerRe: How to connect IDiscFormat2Data and DDiscFormat2DataEvents without MFC or ATL?memberEric Haddan10 Mar '10 - 7:56 
Hi guardianoc,
 
Hopefully you are just talking about the CDiscFormatDataEvent::ConnectDiscFormatData function. The only MFC function in there is AfxConnectionAdvise and it basically looks like this:
 
BOOL AFXAPI AfxConnectionAdvise(LPUNKNOWN pUnkSrc, REFIID iid,
LPUNKNOWN pUnkSink, BOOL bRefCount, DWORD* pdwCookie)
{
BOOL bSuccess = FALSE;
 
LPCONNECTIONPOINTCONTAINER pCPC;
 
if (SUCCEEDED(pUnkSrc->QueryInterface(
IID_IConnectionPointContainer,
(LPVOID*)&pCPC)))
{
ASSERT_POINTER(pCPC, IConnectionPointContainer);
 
LPCONNECTIONPOINT pCP;
 
if (SUCCEEDED(pCPC->FindConnectionPoint(iid, &pCP)))
{
ASSERT_POINTER(pCP, IConnectionPoint);
 
if (SUCCEEDED(pCP->Advise(pUnkSink, pdwCookie)))
bSuccess = TRUE;
 
pCP->Release();
 
if (bSuccess && !bRefCount)
pUnkSink->Release();
}
 
pCPC->Release();
}
 
return bSuccess;
}

 
Hope that helps. Wink | ;)
GeneralRe: How to connect IDiscFormat2Data and DDiscFormat2DataEvents without MFC or ATL?memberguardianoc10 Mar '10 - 21:44 
Yes that helps, thanks a lot. But the second resp. the first problem is MFC's GetIDispatch(BOOL) function. I'm using the VS Express edition and therefore i don't have the MFC sources. Is this function as simple as the AfxConnectionAdvise or is there another way to get the addref'd IDispatch?
GeneralRe: How to connect IDiscFormat2Data and DDiscFormat2DataEvents without MFC or ATL?memberEric Haddan11 Mar '10 - 2:45 
I ran across this article on CodeProject a while back:
How to compile MFC code in Visual C++ Express[^]

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 12 Dec 2009
Article Copyright 2007 by Eric Haddan
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid