Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
248 views
in Technique[技术] by (71.8m points)

c++ - Windows CD Burning API

We need to programatically burn files to CD in a CC++ Windows XP/Vista application we are developing using Borlands Turbo C++.

What is the simplest and best way to do this? We would prefer a native windows API (that doesnt rely on MFC) so as not to rely on any third party software/drivers if one is available.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

We used the following:

Store files in the directory returned by GetBurnPath, then write using Burn. GetCDRecordableInfo is used to check when the CD is ready.

#include <stdio.h>
#include <imapi.h>
#include <windows.h>

struct MEDIAINFO {
    BYTE nSessions;
    BYTE nLastTrack;
    ULONG nStartAddress;
    ULONG nNextWritable;
    ULONG nFreeBlocks;
};
//==============================================================================
//  Description:    CD burning on Windows XP
//==============================================================================
#define CSIDL_CDBURN_AREA               0x003b
SHSTDAPI_(BOOL) SHGetSpecialFolderPathA(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate);
SHSTDAPI_(BOOL) SHGetSpecialFolderPathW(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
#ifdef UNICODE
#define SHGetSpecialFolderPath  SHGetSpecialFolderPathW
#else
#define SHGetSpecialFolderPath  SHGetSpecialFolderPathA
#endif
//==============================================================================
// Interface IDiscMaster
const IID IID_IDiscMaster = {0x520CCA62,0x51A5,0x11D3,{0x91,0x44,0x00,0x10,0x4B,0xA1,0x1C,0x5E}};
const CLSID CLSID_MSDiscMasterObj = {0x520CCA63,0x51A5,0x11D3,{0x91,0x44,0x00,0x10,0x4B,0xA1,0x1C,0x5E}};

typedef interface ICDBurn ICDBurn;
// Interface ICDBurn
const IID IID_ICDBurn =    {0x3d73a659,0xe5d0,0x4d42,{0xaf,0xc0,0x51,0x21,0xba,0x42,0x5c,0x8d}};
const CLSID CLSID_CDBurn = {0xfbeb8a05,0xbeee,0x4442,{0x80,0x4e,0x40,0x9d,0x6c,0x45,0x15,0xe9}};

MIDL_INTERFACE("3d73a659-e5d0-4d42-afc0-5121ba425c8d")
ICDBurn : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetRecorderDriveLetter(
        /* [size_is][out] */ LPWSTR pszDrive,
        /* [in] */ UINT cch) = 0;

    virtual HRESULT STDMETHODCALLTYPE Burn(
        /* [in] */ HWND hwnd) = 0;

    virtual HRESULT STDMETHODCALLTYPE HasRecordableDrive(
        /* [out] */ BOOL *pfHasRecorder) = 0;
};
//==============================================================================
//  Description:    Get burn pathname
//  Parameters:     pathname - must be at least MAX_PATH in size
//  Returns:        Non-zero for an error
//  Notes:          CoInitialize(0) must be called once in application
//==============================================================================
int GetBurnPath(char *path)
{
    ICDBurn* pICDBurn;
    int ret = 0;

    if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL,CLSCTX_INPROC_SERVER,IID_ICDBurn,(LPVOID*)&pICDBurn))) {
        BOOL flag;
        if (pICDBurn->HasRecordableDrive(&flag) == S_OK) {
            if (SHGetSpecialFolderPath(0, path, CSIDL_CDBURN_AREA, 0)) {
                strcat(path, "");
            }
            else {
                ret = 1;
            }
        }
        else {
            ret = 2;
        }
        pICDBurn->Release();
    }
    else {
        ret = 3;
    }
    return ret;
}
//==============================================================================
//  Description:    Get CD pathname
//  Parameters:     pathname - must be at least 5 bytes in size
//  Returns:        Non-zero for an error
//  Notes:          CoInitialize(0) must be called once in application
//==============================================================================
int GetCDPath(char *path)
{
    ICDBurn* pICDBurn;
    int ret = 0;

    if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL,CLSCTX_INPROC_SERVER,IID_ICDBurn,(LPVOID*)&pICDBurn))) {
        BOOL flag;
        WCHAR drive[5];
        if (pICDBurn->GetRecorderDriveLetter(drive, 4) == S_OK) {
            sprintf(path, "%S", drive);
        }
        else {
            ret = 1;
        }
        pICDBurn->Release();
    }
    else {
        ret = 3;
    }
    return ret;
}
//==============================================================================
//  Description:    Burn CD
//  Parameters:     None
//  Returns:        Non-zero for an error
//  Notes:          CoInitialize(0) must be called once in application
//==============================================================================
int Burn(void)
{
    ICDBurn* pICDBurn;
    int ret = 0;

    if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL,CLSCTX_INPROC_SERVER,IID_ICDBurn,(LPVOID*)&pICDBurn))) {
        if (pICDBurn->Burn(NULL) != S_OK) {
            ret = 1;
        }
        pICDBurn->Release();
    }
    else {
        ret = 2;
    }
    return ret;
}
//==============================================================================
bool GetCDRecordableInfo(long *FreeSpaceSize)
{
    bool Result = false;
    IDiscMaster *idm = NULL;
    IDiscRecorder *idr = NULL;
    IEnumDiscRecorders *pEnumDiscRecorders = NULL;
    ULONG cnt;
    long type;
    long mtype;
    long mflags;
    MEDIAINFO mi;

    try {
        CoCreateInstance(CLSID_MSDiscMasterObj, 0, CLSCTX_ALL, IID_IDiscMaster, (void**)&idm);
        idm->Open();
        idm->EnumDiscRecorders(&pEnumDiscRecorders);
        pEnumDiscRecorders->Next(1, &idr, &cnt);
        pEnumDiscRecorders->Release();

        idr->OpenExclusive();
        idr->GetRecorderType(&type);
        idr->QueryMediaType(&mtype, &mflags);
        idr->QueryMediaInfo(&mi.nSessions, &mi.nLastTrack, &mi.nStartAddress, &mi.nNextWritable, &mi.nFreeBlocks);
        idr->Release();

        idm->Close();
        idm->Release();
        Result = true;
    }
    catch (...) {
        Result = false;
    }

    if (Result == true) {
        Result = false;
        if (mtype == 0) {
            //  No Media inserted
            Result = false;
        }
        else {
            if ((mflags & 0x04) == 0x04) {
                // Writable Media
                Result = true;
            }
            else {
                Result = false;
            }

            if (Result == true) {
                *FreeSpaceSize = (mi.nFreeBlocks * 2048);
            }
            else {
                *FreeSpaceSize = 0;
            }
        }
    }

    return Result;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...