在C++中对每个媒体进行格式化的程序
问题: 我正试图编写一个程序来格式化任何类型的媒体。 到目前为止,我已经成功地格式化了硬盘分区、闪存、SDRAM和RDX。 但我需要格式化最后一种媒体DVD-RAM。我的程序无法格式化此媒体。 我正在使用fmifs.dll中的FormatEx函数。我完全不知道如何使用这个函数,除了它的名称和它驻留在fmifs.dll中。在我的帮助下,我设法找到了一个使用这个图书馆的图书馆。但它仍然没有给出关于如何使用它的完整信息 我所尝试的: 我正在寻找有关FormatEx及其参数的完整文档,以及每个参数可以接受的值。 我试着在谷歌和MSDN上搜索。这就是我发现的。首先,这不是我正在使用的函数。但是,即使把它放在一边,也没有足够的信息说明如何使用函数,比如使用哪些头/库 编辑: 我不必使用FormatEx,如果有其他选择,请告诉我 编辑2: 在进一步的测试中,我注意到如果DVD-RAM的初始文件系统是FAT32,我可以格式化它。但如果是任何UDF修订版,格式化都会失败。在C++中对每个媒体进行格式化的程序,c++,windows-xp,format,drive,C++,Windows Xp,Format,Drive,问题: 我正试图编写一个程序来格式化任何类型的媒体。 到目前为止,我已经成功地格式化了硬盘分区、闪存、SDRAM和RDX。 但我需要格式化最后一种媒体DVD-RAM。我的程序无法格式化此媒体。 我正在使用fmifs.dll中的FormatEx函数。我完全不知道如何使用这个函数,除了它的名称和它驻留在fmifs.dll中。在我的帮助下,我设法找到了一个使用这个图书馆的图书馆。但它仍然没有给出关于如何使用它的完整信息 我所尝试的: 我正在寻找有关FormatEx及其参数的完整文档,以及每个参数可以接
此外,快速格式化会立即失败,常规格式化会在90%以上的进度后失败。但当我检查磁盘内容后,一切都一样。似乎格式根本就没有尝试过。它是由马克·罗斯诺维奇(Mark Russinovich Sysinovich)编写的,他提供了源代码,如果你在谷歌上搜索fmifs Russinovich,会有很多副本
它是由马克·鲁西诺维奇(MarkRussinovich)写的,他提供了源代码,如果你用谷歌搜索fmifs鲁西诺维奇,会有很多副本
看起来,唯一的障碍是将格式设置为UDF。fmfifs.dll中的FormatEx是一个垫片或辅助工具实用程序,它将格式化任务分派给较低级别的驱动程序,作为Microsoft可安装文件系统基础结构的一部分。IFS基本上允许Microsoft添加对新文件系统的支持 在UDF的情况下,对应的库将是UUDF.DLL,此约定适用于其他文件系统,例如NTFS将由UNTFS.DLL、UFAT.DLL等处理。您的Windows XP系统上是否存在此dll 通过使用depends.exe查看UUDF.dll的导出,我看到了对各种函数的支持,包括臭名昭著的FormatEx。FormatEx似乎是cdecl,查看DISAssembly需要16字节的参数,可能是4个参数。虽然能够直接调用函数是很方便的,但它并没有在任何地方记录下来,弄清楚参数也是一件痛苦的事情。此外,如果可以的话,我认为fmifs.dll会做正确的事情 UDF支持多个版本-您的问题可能是WinXP上的UUDF.dll版本与DVD-RAM格式化时使用的UDF版本存在问题 你可以做的是使用带有控制代码的函数,这将使你能够直接与设备对话。使用SCSI/MMC多媒体命令格式化DVD-RAM应该是可能的-请查阅说明。MMC命令是在T10工作草案中指定的——它们很难掌握,但我相信注册后可以作为来宾下载副本 如果easy-fmifs.dll方法对您不起作用,您将不得不采用艰难的方法,或者找到第三方dll来帮助您 更新: 从MSDN上看,XP Service Pack 2支持IMAPI2映像主控API。使用fmifs.dll的另一种方法是使用IDicFormat2Erase接口的EraseMedia函数擦除光盘,然后使用IFileSystemImage接口的文件系统创建函数格式化为UDF。可能比DeviceIOControl路由更简单 因为我从来没有这样做过,我决定把一个简单的例子放在一起。它很快就完成了,而且未经测试,在DVD-RW上创建了一个UDF rev 2.50文件系统,仅此而已,但它是Visual Studio 2012的起点:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <Windows.h>
#include <imapi2.h>
#include <imapi2fs.h>
#include <imapi2error.h>
#include <imapi2fserror.h>
#include <comdef.h>
void ShowComError(HRESULT hr)
{
LPWSTR lpMsgBuf;
DWORD ret;
std::cout << "Failed - HRESULT = 0x" << std::hex << hr << std::endl;
ret = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(TEXT("imapi2.dll")),
hr,
0,
(LPWSTR) &lpMsgBuf,
0, NULL );
if(ret)
{
std::wcout << L"HRESULT: " << lpMsgBuf << std::endl;
LocalFree(lpMsgBuf);
}
}
int main()
{
IDiscMaster2* ppMaster = NULL;
IDiscRecorder2* ppRecorder = NULL;
IDiscFormat2Erase* ppFormat2 = NULL;
IDiscFormat2Data* ppFormat2Data = NULL;
IFileSystemImage* ppFileImage = NULL;
IStream* fs = NULL;
IFileSystemImageResult* res = NULL;
HRESULT hr = CoInitialize(NULL);
BSTR clientName = SysAllocStringLen(L"TestBurner", lstrlen(L"TestBurner"));
SAFEARRAY* multi = NULL; // multi-sessions
hr = CoCreateInstance(__uuidof(MsftDiscMaster2),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscMaster2),
(void **) &ppMaster);
if (FAILED(hr))
{
ShowComError(hr);
//nothing-wrong-with-a-goto-when-its-heart's-in-the-right-place ;)
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftDiscRecorder2),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscRecorder2),
(void **) &ppRecorder);
if (FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftDiscFormat2Erase),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscFormat2Erase),
(void**) &ppFormat2);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftDiscFormat2Data),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscFormat2Data),
(void**) &ppFormat2Data);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftFileSystemImage),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IFileSystemImage),
(void**) &ppFileImage);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
// got here - get the optical drives
LONG countDevices;
hr = ppMaster->get_Count(&countDevices);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
VARIANT_BOOL supported;
hr = ppMaster->get_IsSupportedEnvironment(&supported);
// check if it's supported - if yes we use it to format
// and then break out...
if(SUCCEEDED(hr) && supported == VARIANT_TRUE)
{
BSTR deviceName;
for(LONG i = 0; i < countDevices; i++)
{
hr = ppMaster->get_Item(i, &deviceName);
if(SUCCEEDED(hr))
{
std::wcout << L"Using: " << deviceName << std::endl;
hr = ppRecorder->InitializeDiscRecorder(deviceName);
if(FAILED(hr)) goto Clean_Up;
hr = ppRecorder->AcquireExclusiveAccess(VARIANT_TRUE, clientName);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2->put_Recorder(ppRecorder);
if(FAILED(hr)) goto Clean_Up;
// need to set client_name before erasing
hr = ppFormat2->put_ClientName(clientName);
if(FAILED(hr)) ShowComError(hr);
//SysFreeString(clientName);
BSTR owner = NULL;
hr = ppRecorder->get_ExclusiveAccessOwner(&owner);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
if(owner)
{
std::wcout << owner << std::endl;
SysFreeString(owner);
}
// erase the disc
hr = ppFormat2->put_FullErase(VARIANT_TRUE);
if(FAILED(hr)) goto Clean_Up;
hr = ppFormat2->EraseMedia();
if(FAILED(hr))
{
ShowComError(hr); // Need to pull eventual errors out of imapi2error omitted...
//goto Clean_Up;
}
hr = ppFormat2Data->put_Recorder(ppRecorder);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2Data->put_ClientName(clientName);
if(FAILED(hr)) ShowComError(hr);
hr = ppFormat2->IsCurrentMediaSupported(ppRecorder, &supported);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
VARIANT_BOOL blank;
hr = ppFormat2Data->get_MediaHeuristicallyBlank(&blank);
if(blank == VARIANT_FALSE)
{
hr = ppFormat2Data->get_MultisessionInterfaces(&multi);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
}
/*hr = ppFileImage->ChooseImageDefaults(ppRecorder);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}*/
FsiFileSystems imported = FsiFileSystemNone;
if(multi)
{
hr = ppFileImage->put_MultisessionInterfaces(multi);
if(FAILED(hr))
{
ShowComError(hr);
}
hr = ppFileImage->ImportFileSystem(&imported);
}
if(imported == FsiFileSystemNone || imported == FsiFileSystemUnknown)
{
imported = FsiFileSystemUDF;
// ask for UDF revision 2.50
hr = ppFileImage->put_UDFRevision(0x250);
if(FAILED(hr))
{
ShowComError(hr);
}
}
hr = ppFileImage->put_FileSystemsToCreate(imported);
if(FAILED(hr))
{
ShowComError(hr);
}
hr = ppFileImage->CreateResultImage(&res);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = res->get_ImageStream(&fs);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2Data->put_ForceOverwrite(VARIANT_TRUE);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2Data->Write(fs);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppRecorder->EjectMedia();
break;
}
}
}
// clean up
Clean_Up:
if(res) res->Release();
if(fs) fs->Release();
if(multi) SafeArrayDestroy(multi);
if(clientName) SysFreeString(clientName);
if(ppFileImage) ppFileImage->Release();
if(ppFormat2Data) ppFormat2Data->Release();
if(ppFormat2) ppFormat2->Release();
if(ppRecorder) ppRecorder->Release();
if(ppMaster) ppMaster->Release();
CoUninitialize();
/**/
std::cout << "Press any key to continue..." << std::endl;
std::cin.get();
return 0;
}
看起来,唯一的障碍是将格式设置为UDF。fmfifs.dll中的FormatEx是一个垫片或辅助工具实用程序,它将格式化任务分派给较低级别的驱动程序,作为Microsoft可安装文件系统基础结构的一部分。IFS基本上允许Microsoft添加对新文件系统的支持 在UDF的情况下,对应的库将是UUDF.DLL,此约定适用于其他文件系统,例如NTFS将由UNTFS.DLL、UFAT.DLL等处理。您的Windows XP系统上是否存在此dll 通过使用depends.exe查看UUDF.dll的导出,我看到了对各种函数的支持,包括臭名昭著的FormatEx。FormatEx似乎是cdecl,查看DISAssembly需要16字节的参数,可能是4个参数。虽然能够直接调用函数是很方便的,但它并没有在任何地方记录下来,弄清楚参数也是一件痛苦的事情。此外,我假设fmifs.dll 如果可能的话,我会做正确的事情 UDF支持多个版本-您的问题可能是WinXP上的UUDF.dll版本与DVD-RAM格式化时使用的UDF版本存在问题 你可以做的是使用带有控制代码的函数,这将使你能够直接与设备对话。使用SCSI/MMC多媒体命令格式化DVD-RAM应该是可能的-请查阅说明。MMC命令是在T10工作草案中指定的——它们很难掌握,但我相信注册后可以作为来宾下载副本 如果easy-fmifs.dll方法对您不起作用,您将不得不采用艰难的方法,或者找到第三方dll来帮助您 更新: 从MSDN上看,XP Service Pack 2支持IMAPI2映像主控API。使用fmifs.dll的另一种方法是使用IDicFormat2Erase接口的EraseMedia函数擦除光盘,然后使用IFileSystemImage接口的文件系统创建函数格式化为UDF。可能比DeviceIOControl路由更简单 因为我从来没有这样做过,我决定把一个简单的例子放在一起。它很快就完成了,而且未经测试,在DVD-RW上创建了一个UDF rev 2.50文件系统,仅此而已,但它是Visual Studio 2012的起点:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <Windows.h>
#include <imapi2.h>
#include <imapi2fs.h>
#include <imapi2error.h>
#include <imapi2fserror.h>
#include <comdef.h>
void ShowComError(HRESULT hr)
{
LPWSTR lpMsgBuf;
DWORD ret;
std::cout << "Failed - HRESULT = 0x" << std::hex << hr << std::endl;
ret = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(TEXT("imapi2.dll")),
hr,
0,
(LPWSTR) &lpMsgBuf,
0, NULL );
if(ret)
{
std::wcout << L"HRESULT: " << lpMsgBuf << std::endl;
LocalFree(lpMsgBuf);
}
}
int main()
{
IDiscMaster2* ppMaster = NULL;
IDiscRecorder2* ppRecorder = NULL;
IDiscFormat2Erase* ppFormat2 = NULL;
IDiscFormat2Data* ppFormat2Data = NULL;
IFileSystemImage* ppFileImage = NULL;
IStream* fs = NULL;
IFileSystemImageResult* res = NULL;
HRESULT hr = CoInitialize(NULL);
BSTR clientName = SysAllocStringLen(L"TestBurner", lstrlen(L"TestBurner"));
SAFEARRAY* multi = NULL; // multi-sessions
hr = CoCreateInstance(__uuidof(MsftDiscMaster2),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscMaster2),
(void **) &ppMaster);
if (FAILED(hr))
{
ShowComError(hr);
//nothing-wrong-with-a-goto-when-its-heart's-in-the-right-place ;)
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftDiscRecorder2),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscRecorder2),
(void **) &ppRecorder);
if (FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftDiscFormat2Erase),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscFormat2Erase),
(void**) &ppFormat2);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftDiscFormat2Data),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiscFormat2Data),
(void**) &ppFormat2Data);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = CoCreateInstance(__uuidof(MsftFileSystemImage),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IFileSystemImage),
(void**) &ppFileImage);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
// got here - get the optical drives
LONG countDevices;
hr = ppMaster->get_Count(&countDevices);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
VARIANT_BOOL supported;
hr = ppMaster->get_IsSupportedEnvironment(&supported);
// check if it's supported - if yes we use it to format
// and then break out...
if(SUCCEEDED(hr) && supported == VARIANT_TRUE)
{
BSTR deviceName;
for(LONG i = 0; i < countDevices; i++)
{
hr = ppMaster->get_Item(i, &deviceName);
if(SUCCEEDED(hr))
{
std::wcout << L"Using: " << deviceName << std::endl;
hr = ppRecorder->InitializeDiscRecorder(deviceName);
if(FAILED(hr)) goto Clean_Up;
hr = ppRecorder->AcquireExclusiveAccess(VARIANT_TRUE, clientName);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2->put_Recorder(ppRecorder);
if(FAILED(hr)) goto Clean_Up;
// need to set client_name before erasing
hr = ppFormat2->put_ClientName(clientName);
if(FAILED(hr)) ShowComError(hr);
//SysFreeString(clientName);
BSTR owner = NULL;
hr = ppRecorder->get_ExclusiveAccessOwner(&owner);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
if(owner)
{
std::wcout << owner << std::endl;
SysFreeString(owner);
}
// erase the disc
hr = ppFormat2->put_FullErase(VARIANT_TRUE);
if(FAILED(hr)) goto Clean_Up;
hr = ppFormat2->EraseMedia();
if(FAILED(hr))
{
ShowComError(hr); // Need to pull eventual errors out of imapi2error omitted...
//goto Clean_Up;
}
hr = ppFormat2Data->put_Recorder(ppRecorder);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2Data->put_ClientName(clientName);
if(FAILED(hr)) ShowComError(hr);
hr = ppFormat2->IsCurrentMediaSupported(ppRecorder, &supported);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
VARIANT_BOOL blank;
hr = ppFormat2Data->get_MediaHeuristicallyBlank(&blank);
if(blank == VARIANT_FALSE)
{
hr = ppFormat2Data->get_MultisessionInterfaces(&multi);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
}
/*hr = ppFileImage->ChooseImageDefaults(ppRecorder);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}*/
FsiFileSystems imported = FsiFileSystemNone;
if(multi)
{
hr = ppFileImage->put_MultisessionInterfaces(multi);
if(FAILED(hr))
{
ShowComError(hr);
}
hr = ppFileImage->ImportFileSystem(&imported);
}
if(imported == FsiFileSystemNone || imported == FsiFileSystemUnknown)
{
imported = FsiFileSystemUDF;
// ask for UDF revision 2.50
hr = ppFileImage->put_UDFRevision(0x250);
if(FAILED(hr))
{
ShowComError(hr);
}
}
hr = ppFileImage->put_FileSystemsToCreate(imported);
if(FAILED(hr))
{
ShowComError(hr);
}
hr = ppFileImage->CreateResultImage(&res);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = res->get_ImageStream(&fs);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2Data->put_ForceOverwrite(VARIANT_TRUE);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppFormat2Data->Write(fs);
if(FAILED(hr))
{
ShowComError(hr);
goto Clean_Up;
}
hr = ppRecorder->EjectMedia();
break;
}
}
}
// clean up
Clean_Up:
if(res) res->Release();
if(fs) fs->Release();
if(multi) SafeArrayDestroy(multi);
if(clientName) SysFreeString(clientName);
if(ppFileImage) ppFileImage->Release();
if(ppFormat2Data) ppFormat2Data->Release();
if(ppFormat2) ppFormat2->Release();
if(ppRecorder) ppRecorder->Release();
if(ppMaster) ppMaster->Release();
CoUninitialize();
/**/
std::cout << "Press any key to continue..." << std::endl;
std::cin.get();
return 0;
}
谷歌fmifs russinovich;Alex K.的评论和回答指向MarkRussinovich的FormatEx源代码副本。代码几乎记录了fmifs.dll FormatEx函数。函数本身从未被记录。您是否尝试将UDF或FAT32作为格式化参数传递给FormatEx以格式化DVD-RAM?@Anthill,我正在传递FAT32。通过测试不同的东西,我注意到当DVD-RAM已经格式化为FAT32时,我可以格式化它,但当它的初始格式为UDF时,我不能。我想这是FormatEx的一个限制。当试图格式化为UDF时,您的quickformat参数是什么?你传递的信息是假的吗;Alex K.的评论和回答指向MarkRussinovich的FormatEx源代码副本。代码几乎记录了fmifs.dll FormatEx函数。函数本身从未被记录。您是否尝试将UDF或FAT32作为格式化参数传递给FormatEx以格式化DVD-RAM?@Anthill,我正在传递FAT32。通过测试不同的东西,我注意到当DVD-RAM已经格式化为FAT32时,我可以格式化它,但当它的初始格式为UDF时,我不能。我想这是FormatEx的一个限制。当试图格式化为UDF时,您的quickformat参数是什么?你传错了吗?谢谢你的回复。我已经安装了DVD-RAM驱动程序,在windows中使用格式选项可以轻松快速地完成工作。但我无法使用windows搜索找到uudf.dll。要么它正在使用其他dll,要么它隐藏在某个地方。感谢您提供的示例代码。我一有机会就去看看。谢谢你的回复。我已经安装了DVD-RAM驱动程序,在windows中使用格式选项可以轻松快速地完成工作。但我无法使用windows搜索找到uudf.dll。要么它正在使用其他dll,要么它隐藏在某个地方。感谢您提供的示例代码。我一有机会就去看看。