• VC++实现CD/DVD刻录(转)


    本文将就在Windows XP/Windows 2003下如何使用ImapiService来实现CD/DVD刻录功能。

    前提条件:
    操作系统必须为Windows XP及Windows 2003以上。因为,在这两种平台下才提供ImapiService服务,缺省的,在Windows XP下,该服务是被设置为自动启动的,而在Windows 2003下,该服务为禁用的,也就需要手工来将其打开。这里就不写如何开启服务了。

    开发平台,VS.NET 2003/VS.NET 2005并需要额外下载Windows Platform SDK,因为,VS.NET里的PlatformSDK是没有带入Imapi的支持的。安装了Windows PlatformSDK后,你便可以在C:\Program Files\Microsoft SDKs\Windows\v1.0下找到你所需要的imapi.h及imapierror.h文件,这时,你就可以在你的程序中引用它了。由于Imapi使用的是COM接口,所以你无须添加lib文件。

    OK,准备结束。让我开始做这个刻录软件吧。

    首先,我们需实例化IDiscMaster。CLSID_MSDiscMasterObj是它的CLSID。 这里我们使用了ATL的智能指针模板。
    CComQIPtr<IDiscMaster> dm;
    HRESULT m_hr = CoCreateInstance(CLSID_MSDiscMasterObj, &dm, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER);
    如果宏SUCCEEDED( m_hr )返回为TRUE的话,表明IDiscMaster初始化成功。这样,我们可以继续下面的操作。

    初始化成功后,我们就可以调用Open方法来打开DiscMaster,记住,以后的任何一个步骤的前提条件都是要调用这个方法,否则会返回一个IMAPI_E_NOTOPENED错误。

    在真正开始刻录之前,Imapi要求我们首先得告诉它使用哪个刻录机及什么样的格式来进行刻录,讲到这个格式,我们先弄明白,Windows所支持的格式有哪些。其实,这个格式大概的划分起来就两种,一种是众所周知的如CD的音频格式,另一种是我们经常使用的数据CD格式ISO9660及它的扩展Joliet。这里我们将需要使用到下面四种接口:
    IDiscRecorder
    IEnumDiscRecorders
    IJolietDiscMaster
    IRedbookDiscMaster
    其中, IDiscRecorder是用来操作刻录机的COM接口。IEnumDiscRecorders是用来遍历所有的Recorder的接口,我们可以使用下面的方法来遍历所有的刻录机。
    HRESULT hr;
    CComQIPtr<IEnumDiscRecorders> enumRecorders;
    CComQIPtr<IDiscRecorder> Recorders;
    hr = dm->EnumDiscRecorders( &enumRecorders );
    if( SUCCEEDED( hr )  ){
        UINT nRet = 0;
        while( SUCCEEDED( hr= enumRecorder->Next(1, &recorder.p, &nRet)) && nRet==1 ){
                ///You can set the ActiveDiscRecorder and Active format here.
                dm->SetActiveDiscRecorder( recorder );
                ///说明将按数据CD的格式来刻录。
                dm->SetActiveDiscMasterFormat( IID_IJolietDiscMaster, &recorder );
        }
    }

    然后使用IJolietDiscMaster来将DiscMaster特例化,当我也可用IRedbookDiscMaster来将特例化。
    CComQIPtr<IJolietDiscMaster> jdm(dm);

    做完这些后,Imapi刻录机的状态就基本上准备完成了。接下的是我们要准备如何将想要的数据刻录到CD里。那在这里就有必要搞明白一个接口:
    IStorage;
    IStorage是微软提供的用于结构化存储的接口,在该接口中有子存储及子对象之分,分别可以使用方法CreateStorage及CreateStream来创建。而其中所创建的子Storage的话,则会当作目录被刻入到CD中,而Stream就会被当作文件写入到CD中。下面的程序将指定目录下的文件来组织成一个IStorage对象。


    ULONGLONG PerformFileStream( 
    const char *pFileName, IStream *stream ){
        CFile file;
        
    char *pBuffer = NULL;
        
    bool isOpened = false;
        UINT BufferSize 
    = 40960;
        ULONGLONG m_ReadedSize 
    = 0L;
        
    try{
            
    if( file.Open( pFileName, CFile::modeRead ) ){
                isOpened 
    = true;
                pBuffer 
    = new char[BufferSize];
                UINT readed 
    = 0L;
                
    if( pBuffer != NULL ){
                    ZeroMemory( pBuffer, BufferSize );
                    ULONG written 
    = 0;
                    
    while(  (readed = file.Read( pBuffer, BufferSize )) > 0 ){
                        stream
    ->Write( pBuffer, readed, &written );
                        m_ReadedSize 
    += readed;
                    }

                }

            }

        }
    catch(CFileException* e){
            e
    ->ReportError();
        }

        
    catch(){
        }


        
    if( isOpened ){
            file.Close();
        }

        
    if( pBuffer != NULL ){
            delete[] pBuffer;
            pBuffer 
    = NULL;
        }

        
    return m_ReadedSize;
    }


    HRESULT PerformDirectory( 
    const char *path, IStorage *storage ){
        HRESULT hr 
    = 0L;
        
    long hFile = 0;
        USES_CONVERSION;

        _finddata_t fileinfo;

        
    int ch = _chdir( path );

        
    if (( hFile = _findfirst( "*.*"&fileinfo ) ) != -1 ){
            
    do{
                
    if (!(fileinfo.attrib & _A_SUBDIR))
                
    {
                    
    char filename[_MAX_PATH];
                    strcpy( filename, path );
                    strcat( filename, fileinfo.name );
                    CComPtr
    <IStream> fileStream;
                    hr 
    = storage->CreateStream( T2W( fileinfo.name ), STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, NULL, &fileStream );
                    ASSERT( SUCCEEDED( hr ) );
                    PerformFileStream( filename, fileStream );
                }

                
    else{
                    
    if ( strcmp(fileinfo.name,"."!= 0 && strcmp(fileinfo.name,".."!= 0 )
                    
    {
                        
    char subdir[ _MAX_PATH ];
                        strcpy( subdir,path );
                        strcat( subdir,fileinfo.name);
                        strcat(subdir,
    "\\");
                        CComPtr
    <IStorage> sub;
                        hr 
    = storage->CreateStorage( T2W( fileinfo.name ), 
                            STGM_CREATE
    |STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 00
                            
    &sub);
                        ASSERT( SUCCEEDED( hr ) );
                        hr 
    = PerformDirectory( subdir, sub );
                        ASSERT( SUCCEEDED( hr ) );
                    }

                }

            }
    while (_findnext(hFile,&fileinfo) == 0);
            _findclose(hFile);
        }

        
    return hr;
    }


    HRESULT CreateDirectoryStorage( 
    const char *path, IStorage **stg )
    {
        HRESULT hr 
    = 0L;
            hr 
    = StgCreateStorageEx( NULL,
                                     STGM_CREATE
    |STGM_SHARE_EXCLUSIVE|STGM_READWRITE,
                                     STGFMT_STORAGE,
                                        
    // STGFMT_STORAGE => Structured Storage property sets
                                        
    // STGFMT_FILE    => NTFS property sets
                                     0, NULL, NULL,
                                     IID_IStorage,
                                     reinterpret_cast
    <void**>(stg) );

            
    if( FAILED(hr) ) throw L"Failed StgCreateStorageEx";
            hr 
    = PerformDirectory( path, (*stg) );
            
    return hr;
    }

    这样我们就可以将这个创建好的IStorage对象写入到CD或DVD中了。
         hr = jdm->AddData( storage, FALSE );
          if( SUCCEEDED( hr ) ){
           hr = dm->RecordDisc( FALSE, TRUE );
        }

    这里由于在调用了RecordDisc后方写入到CD,同时,这里将可能产生许多问题,如CD不能被刻录等问题都需要在这里进行处理。

    VS.NET 2003/2005都提供了如何使用Imapi进行CD刻录的帮助,详细内容请参考相关的MSDN。


  • 相关阅读:
    UML类图
    mongo存储的DoraCMS系统
    docker+ceph实现私网云盘
    MongoDB sharding分片
    ES数据库安装6.6
    ceph_docker_apache_nginx_ansible面试
    用户中心_单点登录
    金丝雀发布、滚动发布、蓝绿发布到底有什么差距?关键点是什么?
    ticket、token、rpc是什么
    TCP/IP的三次握手以及四次挥手
  • 原文地址:https://www.cnblogs.com/rainbowzc/p/1565969.html
Copyright © 2020-2023  润新知