Для записи метки на дискету использовали SetVolumeLabel, при попытке использовать эту же функцию для записи метки на перезаписываемые носители типа CDR(W)/DVDR(W) получаю ошибку 1005 "не определённая файлавая система"
Может уважаемый All подскажет, как правильно записать метку на такие носители (CDR/DVDR) ?
Метка диска на CDR(W) согласно ISO 9660 есть Volume Identifier, который находится в Primary Volume Descriptor по смещению 41 to 72, такой же идентификатор (для Joilet) находится в Supplementary Volume Descriptor, по тому же смещению.
Как записать? Подготовить фаловую систему диска, согласно ISO 9660 (level 1, 2, 3) + Joilet по-вкусу, в которую и входит Primary (Supplementary) Volume Descriptor как составная часть, и записать все это дело на диск, используя ASPI либо SPTI. Еще можно использовать IMAPI, тогда вообще не нужено заморачиваться — IJolietDiscMaster вся за тебя сделает. Правда это только для XP.
CComPtr<IDiscMaster> disk_master;
disk_master.CoCreateInstance(CLSID_MSDiscMasterObj);
ATLASSERT(disk_master);
HRESULT res = S_FALSE;
res = disk_master->Open();
_ASSERTE(SUCCEEDED(res));
//enum supported formats (interface IDs) if need. Current only two formats supported - RedBook (IID_IRedbookDiscMaster) & Joilet (IID_IJolietDiscMaster)
CComPtr<IEnumDiscMasterFormats> format_enumerator;
res = disk_master->EnumDiscMasterFormats(&format_enumerator);
_ASSERTE(format_enumerator);
//enum recorders if needed. Maybe you have multiple recorders?
CComPtr<IEnumDiscRecorders> recorder_enumerator;
res = disk_master->EnumDiscRecorders(&recorder_enumerator);
ATLASSERT(recorder_enumerator);
IDiscRecorder* recorder = NULL;
if (recorder_enumerator->Next(1, &recorder, &celt_returned) != S_OK) //use 1st recorder
_ASSERTE(FALSE); //no recorders
{ //print recorder props ...
CComBSTR vendor, product, revision;
res = recorder->GetDisplayNames(&vendor, &product, &revision);
_ASSERTE(SUCCEEDED(res));
USES_CONVERSION;
std::cout << count << ": " << W2A(vendor) << "\t" << W2A(product) << "\t" << W2A(revision) << std::endl;
}
res = disk_master->SetActiveDiscRecorder(recorder);
_ASSERTE(SUCCEEDED(res));
CComPtr<IJolietDiscMaster> joilet_master = NULL;
res = disk_master->SetActiveDiscMasterFormat(IID_IJolietDiscMaster, reinterpret_cast<void**>(&joilet_master));
_ASSERTE(joilet_master);
{ //print total number of blocks available for staging a data disc
LONG total_blocks = 0;
res = joilet_master->GetTotalDataBlocks(&total_blocks);
_ASSERTE(SUCCEEDED(res));
std::cout << "Total blocks: " << total_blocks << std::endl;
}
{ //print total data blocks staged in image
LONG used_blocks = 0;
res = joilet_master->GetUsedDataBlocks(&used_blocks);
_ASSERTE(SUCCEEDED(res));
std::cout << "Used blocks: " << used_blocks << std::endl;
}
CComPtr<IPropertyStorage> joilet_properties;
joilet_master->GetJolietProperties(&joilet_properties);
_ASSERTE(joilet_properties);
{ //read & print current disk props if needconst int prop_count = 6;
PROPSPEC prop_specs[prop_count] = { { PRSPEC_LPWSTR },
{ PRSPEC_LPWSTR },
{ PRSPEC_LPWSTR },
{ PRSPEC_LPWSTR },
{ PRSPEC_LPWSTR },
{ PRSPEC_LPWSTR } };
prop_specs[0].lpwstr = L"VolumeName";
prop_specs[1].lpwstr = L"PlaceBootImageOnDisc";
prop_specs[2].lpwstr = L"BootImageManufacturerIDString";
prop_specs[3].lpwstr = L"BootImagePlatform";
prop_specs[4].lpwstr = L"BootImageEmulationType";
prop_specs[5].lpwstr = L"BootImage";
PROPVARIANT prop_values[prop_count] = { 0 };
res = joilet_properties->ReadMultiple(prop_count, prop_specs, prop_values);
_ASSERTE(SUCCEEDED(res));
for (int i = 0; i < prop_count; ++i)
{
USES_CONVERSION;
if (prop_values[i].vt == VT_BSTR)
std::cout << W2A(prop_specs[i].lpwstr) << ": " << W2A(prop_values[i].bstrVal) << std::endl;
}
}
//
//... change needed prop_values, eg. VolumeName, and use SetJolietProperties,
//
CComPtr<IStorage> data_storage;
res = StgCreateStorageEx(L"work", STGM_READWRITE | STGM_CREATE | STGM_DELETEONRELEASE | STGM_SHARE_EXCLUSIVE, STGFMT_STORAGE ,
0, 0, 0, IID_IStorage, reinterpret_cast<void**>(&data_storage));
_ASSERTE(data_storage);
//create and add files data to IStorage. You can add as many files & folder to IStorage as you want.
//Substorages of become folders and streams become files on disk.
CComPtr<IStream> file_stream;
res = SHCreateStreamOnFile("my_cool_file.cool", STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &file_stream);
_ASSERTE(file_stream);
CComPtr<IStream> storage_stream;
res = data_storage->CreateStream(L"my_cool_file.cool", STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &storage_stream);
_ASSERTE(storage_stream);
STATSTG stat_stg = { 0 };
res = file_stream->Stat(&stat_stg, STATFLAG_NONAME);
_ASSERTE(SUCCEEDED(res));
//Copy file data to IStream. You can write your own IStream implementation to use file data "in-place" without copying...
ULARGE_INTEGER bytes_read = { 0 }, bytes_written = { 0 };
res = file_stream->CopyTo(storage_stream, stat_stg.cbSize, &bytes_read, &bytes_written);
_ASSERTE(bytes_written.QuadPart == stat_stg.cbSize.QuadPart);
file_stream.Release();
res = storage_stream->Commit(STGC_DEFAULT);
_ASSERTE(SUCCEEDED(res));
storage_stream.Release();
res = data_storage->Commit(STGC_DEFAULT);
_ASSERTE(SUCCEEDED(res));
res = joilet_master->AddData(data_storage, 0 /*-don't overwrite existing files with the same name*/);
_ASSERTE(SUCCEEDED(res));
//Record disk
res = disk_master->RecordDisc(false, true);
_ASSERTE(SUCCEEDED(res));
res = disk_master->Close();
_ASSERTE(SUCCEEDED(res));
Почетный кавалер ордена Совка.
Re[4]: Записать метку CDR/DVDR
От:
Аноним
Дата:
08.06.05 17:05
Оценка:
Хороший пример.
Только у меня временами
1) не проходит SetActiveDiscRecorder(), вываливается с кодом IMAPI_E_STASHINUSE
2) постоянно вызов RecordDisc() вываливается с кодом IMAPI_E_MEDIUM_INVALIDTYPE (проверял, диск вполне пригодный для записи, Неро пишет на него)
Кто пользовался этим компонентом, посдскажите плз в чем могут быть грабли. Может, у кого есть ещё какой примерчик...
[]
А>1) не проходит SetActiveDiscRecorder(), вываливается с кодом IMAPI_E_STASHINUSE
Скорее всего кто-нить уже пользует компонент, напр. тот же Nero.
А>2) постоянно вызов RecordDisc() вываливается с кодом IMAPI_E_MEDIUM_INVALIDTYPE (проверял, диск вполне пригодный для записи, Неро пишет на него)
IStorage::CreateStream() в качестве 1-го параметра принимает строчку, как сказано в документации, не более 32 символов длиной. Однако, я столкнулся с тем, что длины имен файлов, которые нужно копировать, бывают значительно больше, и прожигалки умеют их записывать.
Я так понимаю, что IJolietDiscMaster записывает имена файлов такие, какие прописаны в том IStorage, который подается в ф-ю AddData().
А как можно записать файл с длиной названия более 32 символов?
Спасибо.