Skip to content

Instantly share code, notes, and snippets.

@uemuraj
Created January 31, 2021 06:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uemuraj/f322c2bd88994dfa1405f0cbdf11177c to your computer and use it in GitHub Desktop.
Save uemuraj/f322c2bd88994dfa1405f0cbdf11177c to your computer and use it in GitHub Desktop.
ISO イメージを作成するには...
#include "pch.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <comdef.h>
#include <imapi2fs.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
template<typename T>
using com_ptr_t = _com_ptr_t<_com_IIID<T, &__uuidof(T)>>;
/*
* グローバルな Set-Up と Tear-Down で COM を使用可能にしておきます
* http://opencv.jp/googletestdocs/advancedguide.html#adv-global-setup-teardown
*/
class CoInitializedEnvironment : public testing::Environment
{
public:
void SetUp() override
{
ASSERT_HRESULT_SUCCEEDED(::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
}
void TearDown() override
{
::CoUninitialize();
}
};
int main(int argc, char * argv[])
{
testing::InitGoogleTest(&argc, argv);
AddGlobalTestEnvironment(new CoInitializedEnvironment());
return RUN_ALL_TESTS();
}
class EventConnection
{
IConnectionPointPtr cp;
DWORD cookie = 0;
public:
EventConnection(IConnectionPointContainerPtr cpc, REFIID riid);
~EventConnection();
void Advise(IUnknown * sink);
};
class FileSystemImageEvents : public DFileSystemImageEvents, public DFileSystemImageImportEvents
{
LONG m_count = 0;
public:
// IDispatch を介して継承されました
STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObject) override;
STDMETHODIMP_(ULONG) AddRef(void) override;
STDMETHODIMP_(ULONG) Release(void) override;
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo) override;
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo ** ppTInfo) override;
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) override;
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr) override;
// DFileSystemImageEvents を介して継承されました
STDMETHODIMP Update(IDispatch * object, BSTR currentFile, LONG copiedSectors, LONG totalSectors) override;
// DFileSystemImageImportEvents を介して継承されました
STDMETHODIMP UpdateImport(IDispatch * object, FsiFileSystems fileSystem, BSTR currentItem, LONG importedDirectoryItems, LONG totalDirectoryItems, LONG importedFileItems, LONG totalFileItems) override;
};
struct MsftFileSystemImageTest : public testing::Test
{
com_ptr_t<IFileSystemImage3> m_fileSystemImage;
const wchar_t * m_OutputFileName = VS_TARGETDIR "MsftFileSystemImageTest.iso";
void SetUp() override
{
m_fileSystemImage.CreateInstance(__uuidof(MsftFileSystemImage));
EXPECT_TRUE(::DeleteFile(m_OutputFileName) || ::GetLastError() == ERROR_FILE_NOT_FOUND);
}
};
TEST_F(MsftFileSystemImageTest, CreateImage)
{
EventConnection connection0(m_fileSystemImage, __uuidof(DFileSystemImageEvents));
EventConnection connection1(m_fileSystemImage, __uuidof(DFileSystemImageImportEvents));
connection0.Advise(com_ptr_t<DFileSystemImageEvents>(new FileSystemImageEvents));
connection1.Advise(com_ptr_t<DFileSystemImageImportEvents>(new FileSystemImageEvents));
auto name = testing::UnitTest::GetInstance()->current_test_info()->test_case_name();
ASSERT_HRESULT_SUCCEEDED(m_fileSystemImage->ChooseImageDefaultsForMediaType(IMAPI_MEDIA_TYPE_DISK));
EXPECT_HRESULT_SUCCEEDED(m_fileSystemImage->put_FileSystemsToCreate(static_cast<FsiFileSystems>(FsiFileSystemJoliet | FsiFileSystemISO9660)));
EXPECT_HRESULT_SUCCEEDED(m_fileSystemImage->put_VolumeName(_bstr_t(name)));
{
com_ptr_t<IFsiDirectoryItem> item;
m_fileSystemImage->get_Root(&item);
EXPECT_HRESULT_SUCCEEDED(item->AddTree(_bstr_t(VS_PROJECTDIR), VARIANT_FALSE)); // ものによるが数十秒かかる
}
com_ptr_t<IFileSystemImageResult> result;
EXPECT_HRESULT_SUCCEEDED(m_fileSystemImage->CreateResultImage(&result));
IStreamPtr in;
ASSERT_HRESULT_SUCCEEDED(result->get_ImageStream(&in));
IStreamPtr out;
ASSERT_HRESULT_SUCCEEDED(::SHCreateStreamOnFile(m_OutputFileName, STGM_CREATE | STGM_WRITE, &out));
LONG a{}, b{};
result->get_TotalBlocks(&a);
result->get_BlockSize(&b);
ULARGE_INTEGER cb{};
cb.QuadPart = UInt32x32To64(a, b);
EXPECT_HRESULT_SUCCEEDED(in->CopyTo(out, cb, nullptr, nullptr));
EXPECT_HRESULT_SUCCEEDED(out->Commit(STGC_DEFAULT));
}
EventConnection::EventConnection(IConnectionPointContainerPtr cpc, REFIID riid)
{
EXPECT_HRESULT_SUCCEEDED(cpc->FindConnectionPoint(riid, &cp));
}
EventConnection::~EventConnection()
{
if (cp)
{
cp->Unadvise(cookie);
}
}
void EventConnection::Advise(IUnknown * sink)
{
if (cp)
{
EXPECT_HRESULT_SUCCEEDED(cp->Advise(sink, &cookie));
}
}
HRESULT FileSystemImageEvents::QueryInterface(REFIID riid, void ** ppvObject)
{
if (riid == __uuidof(DFileSystemImageEvents) || riid == IID_IUnknown || riid == IID_IDispatch)
{
AddRef();
*ppvObject = (DFileSystemImageEvents *) this;
return S_OK;
}
if (riid == __uuidof(DFileSystemImageImportEvents))
{
AddRef();
*ppvObject = (DFileSystemImageImportEvents *) this;
return S_OK;
}
*ppvObject = nullptr;
return E_NOINTERFACE;
}
ULONG FileSystemImageEvents::AddRef(void)
{
return ::InterlockedIncrement(&m_count);
}
ULONG FileSystemImageEvents::Release(void)
{
LONG count = ::InterlockedDecrement(&m_count);
if (count == 0)
{
delete this;
}
return count;
}
HRESULT FileSystemImageEvents::GetTypeInfoCount(UINT * pctinfo)
{
return E_NOTIMPL;
}
HRESULT FileSystemImageEvents::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo ** ppTInfo)
{
return E_NOTIMPL;
}
HRESULT FileSystemImageEvents::GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
{
return E_NOTIMPL;
}
HRESULT FileSystemImageEvents::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
switch (dispIdMember)
{
case DISPID_DFILESYSTEMIMAGEEVENTS_UPDATE:
if (pDispParams->cArgs >= 4)
{
auto & object = pDispParams->rgvarg[3];
auto & currentFile = pDispParams->rgvarg[2];
auto & copiedSectors = pDispParams->rgvarg[1];
auto & totalSectors = pDispParams->rgvarg[0];
if (currentFile.vt == VT_BSTR)
{
::OutputDebugString(currentFile.bstrVal);
::OutputDebugString(L"\r\n");
}
return S_OK;
}
break;
case DISPID_DFILESYSTEMIMAGEIMPORTEVENTS_UPDATEIMPORT:
if (pDispParams->cArgs >= 7)
{
auto & object = pDispParams->rgvarg[6];
auto & fileSystem = pDispParams->rgvarg[5];
auto & currentFile = pDispParams->rgvarg[4];
auto & importedDirectoryItems = pDispParams->rgvarg[3];
auto & totalDirectoryItems = pDispParams->rgvarg[2];
auto & importedFileItems = pDispParams->rgvarg[1];
auto & totalFileItems = pDispParams->rgvarg[0];
if (currentFile.vt == VT_BSTR)
{
::OutputDebugString(currentFile.bstrVal);
::OutputDebugString(L"\r\n");
}
return S_OK;
}
break;
}
return S_FALSE;
}
HRESULT FileSystemImageEvents::Update(IDispatch * object, BSTR currentFile, LONG copiedSectors, LONG totalSectors)
{
return S_FALSE; // 常に DISPID による呼び出しが使われるため、ここには来ない
}
HRESULT FileSystemImageEvents::UpdateImport(IDispatch * object, FsiFileSystems fileSystem, BSTR currentItem, LONG importedDirectoryItems, LONG totalDirectoryItems, LONG importedFileItems, LONG totalFileItems)
{
return S_FALSE; // 常に DISPID による呼び出しが使われるため、ここには来ない
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment