1

问题:
我正在尝试编写一个格式化任何类型媒体的程序。到目前为止,我已经成功地格式化了硬盘分区、闪存、SDRAM、RDX。
但是我需要格式化最后一种类型的媒体(DVD-RAM)。我的程序无法格式化此媒体。
我正在FormatEx使用fmifs.dll. 我完全不知道如何使用这个函数,除了它的名字和它驻留在fmifs.dll. 在这个帮助下,我设法找到了一个使用这个库的简单程序。然而,它仍然没有提供有关如何使用它的完整信息。

我已经尝试过:
我正在寻找关于FormatEx、它的参数以及每个参数可以取什么值的完整文档。
我尝试在谷歌和 MSDN 上搜索。就是我发现的。首先,这不是我正在使用的功能。但是即使把它放在一边,也没有足够的信息来说明如何使用这个函数(比如要使用哪些头文件/库)。

编辑:如果有替代品请告诉
我,我不必使用。FormatEx

编辑 2:
在进一步测试期间,我注意到如果 DVD-RAM 的初始文件系统是“FAT32”,我可以格式化它。但是,如果它是任何“UDF”修订格式失败。
此外,快速格式化会立即失败,而常规格式化会在 90+ % 的进度后失败。但是当我检查磁盘内容后,一切都是一样的。好像格式甚至没有尝试。

4

2 回答 2

7

它是由提供源代码的 Mark Russinovich (Sysinternals) 编写的,如果你用谷歌搜索fmifs russinovich ,就会有很多副本。

http://pete.akeo.ie/2012/04/chkdskx-and-formatx-by-mark-russinovich.html

于 2012-11-06T14:14:56.733 回答
1

似乎您唯一的绊脚石是格式化为 UDF。fmfifs.dll 中的 FormatEx 是一个 shim(或帮助程序)实用程序,它作为 Microsoft 可安装文件系统基础结构 ( IFS ) 的一部分将格式化任务分派给较低级别​​的驱动程序。IFS 基本上允许微软添加对新文件系统的支持。

对于 UDF,对应的库是 UUDF.DLL(此约定适用于其他文件系统,例如 NTFS 将由 UNTFS.DLL、UFAT.DLL 等处理)。您的 Windows XP 系统上是否存在此 dll?

查看使用depends.exe 导出的UUDF.dll,我看到了对各种功能的支持,包括臭名昭著的FormatEx。FormatEx 似乎是 cdecl 并且(查看反汇编)需要 16 个字节的参数(可能是 4 个参数)。虽然能够直接调用该函数会很方便,但它没有在任何地方记录,而且弄清楚参数会很痛苦。此外,我假设 fmifs.dll 会做正确的事情,如果可以的话。

UDF 支持多个修订版(请参阅 OSTA 规范) - 您的问题很可能是您在 WinXP 上的 UUDF.dll 版本与您的 DVD-RAM 格式化的 UDF 版本存在问题。

可以做的是将DeviceIOControl函数与IOCTL_SCSCI_PASSHTHROUGH_DIRECT控制代码一起使用,这将使您能够直接与设备对话。应该可以使用 SCSI/MMC(多媒体命令)格式化 DVD-RAM - 查找FORMAT_UNIT 命令的描述。MMC 命令在http://www.t10.org/drafts.htm#MMC_Family T10 工作草稿中指定 - 它们很难掌握,但我相信注册后可以以访客身份下载副本。

如果简单的 (fmifs.dll) 方法不适合您,您将不得不以艰难的方式进行操作,或者找到第三方 dll 来帮助您。

更新:

查看 MSDN,XP Service Pack 2 支持 IMAPI2(Image Mastering API)。使用 fmifs.dll 的替代方法是使用 IDicFormat2Erase 接口的 EraseMedia() 函数擦除光盘,然后使用 IFileSystemImage 接口的 FileSystemsToCreate( ) 函数格式化为 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;

}
于 2012-11-14T10:58:38.693 回答