Windows CD 刻录 API

发布于 2024-07-05 04:58:44 字数 164 浏览 14 评论 0原文

我们需要在使用 Borlands Turbo C++ 开发的 C\C++ Windows XP/Vista 应用程序中以编程方式将文件刻录到 CD。

做到这一点最简单和最好的方法是什么? 我们更喜欢本机 Windows API(不依赖于 MFC),以便不依赖任何可用的第三方软件/驱动程序。

We need to programatically burn files to CD in a C\C++ 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

猫烠⑼条掵仅有一顆心 2024-07-12 04:58:44

我们使用以下方法:

将文件存储在 GetBurnPath 返回的目录中,然后使用 Burn 进行写入。 GetCDRecordableInfo 用于检查 CD 何时准备就绪。

#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;
}

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;
}
我ぃ本無心為│何有愛 2024-07-12 04:58:44

为了补充已接受的答案,我们添加了此辅助函数,以编程方式动态更改刻录目录,因为这是我们的要求。

typedef HMODULE (WINAPI * SHSETFOLDERPATHA)( int , HANDLE , DWORD , LPCTSTR );

int SetBurnPath( char * cpPath )
{
    SHSETFOLDERPATHA pSHSetFolderPath;
    HANDLE hShell = LoadLibraryA( "shell32.dll" );
    if( hShell == NULL )
        return -2;

    DWORD dwOrdinal = 0x00000000 + 231;

    pSHSetFolderPath = (SHSETFOLDERPATHA)GetProcAddress( hShell, (LPCSTR)dwOrdinal );
    if( pSHSetFolderPath == NULL )
        return -3;

    if( pSHSetFolderPath( CSIDL_CDBURN_AREA, NULL, 0, cpPath ) == S_OK )
        return 0;

    return -1;
}

To complement the accepted answer, we added this helper function to programatically change the burn directory on the fly as this was a requirement of ours.

typedef HMODULE (WINAPI * SHSETFOLDERPATHA)( int , HANDLE , DWORD , LPCTSTR );

int SetBurnPath( char * cpPath )
{
    SHSETFOLDERPATHA pSHSetFolderPath;
    HANDLE hShell = LoadLibraryA( "shell32.dll" );
    if( hShell == NULL )
        return -2;

    DWORD dwOrdinal = 0x00000000 + 231;

    pSHSetFolderPath = (SHSETFOLDERPATHA)GetProcAddress( hShell, (LPCSTR)dwOrdinal );
    if( pSHSetFolderPath == NULL )
        return -3;

    if( pSHSetFolderPath( CSIDL_CDBURN_AREA, NULL, 0, cpPath ) == S_OK )
        return 0;

    return -1;
}
清秋悲枫 2024-07-12 04:58:44

这是 MSDN 站点中 IMAPI 的信息 http://msdn.microsoft.com /en-us/library/aa939967.aspx

This is the information for IMAPI in MSDN site http://msdn.microsoft.com/en-us/library/aa939967.aspx

新人笑 2024-07-12 04:58:44

您应该能够使用 shell 的 ICDBurn 接口。 早在 XP 时代,MFC 甚至没有任何用于 CD 刻录的类。 我会看看是否可以为您找到一些示例,但自从我查看此内容以来已经有一段时间了。

You should be able to use the shell's ICDBurn interface. Back in the XP day MFC didn't even have any classes for cd burning. I'll see if I can find some examples for you, but it's been a while since I looked at this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文