واجهة برمجة تطبيقات حرق الأقراص المضغوطة لنظام التشغيل Windows

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

  •  01-07-2019
  •  | 
  •  

سؤال

نحتاج إلى نسخ الملفات برمجيًا على قرص مضغوط في تطبيق C\C++ Windows XP/Vista الذي نقوم بتطويره باستخدام Borlands Turbo C++.

ما هي أبسط وأفضل طريقة للقيام بذلك؟نفضل واجهة برمجة تطبيقات Windows الأصلية (التي لا تعتمد على MFC) حتى لا نعتمد على أي برامج/برامج تشغيل تابعة لجهة خارجية في حالة توفرها.

هل كانت مفيدة؟

المحلول

استخدمنا ما يلي:

قم بتخزين الملفات في الدليل الذي تم إرجاعه بواسطة GetBurnPath، ثم اكتب باستخدام Burn.يتم استخدام GetCDRecordableInfo للتحقق من أن القرص المضغوط جاهز.

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

نصائح أخرى

لاستكمال الإجابة المقبولة، أضفنا هذه الوظيفة المساعدة لتغيير دليل النسخ برمجيًا بشكل سريع حيث كان هذا أحد متطلباتنا.

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

هذه هي المعلومات الخاصة بـ IMAPI في موقع MSDN http://msdn.microsoft.com/en-us/library/aa939967.aspx

يجب أن تكون قادرًا على استخدام واجهة ICDBurn الخاصة بالصدفة.مرة أخرى في يوم XP، لم يكن لدى MFC أي فئات لنسخ الأقراص المضغوطة.سأرى ما إذا كان بإمكاني العثور على بعض الأمثلة لك، ولكن لقد مر وقت طويل منذ أن نظرت إلى هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top