Adding Stream to ISO as File

I am using the IMAPI2FS Image Mastering API on Windows and I am trying to figure out how to add a stream to a file to a file system image before I create an ISO.

var fsi = new MsftFileSystemImage();
fsi.ChooseImageDefaultsForMediaType(IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK);
fsi.FileSystemsToCreate = 
    FsiFileSystems.FsiFileSystemISO9660 | FsiFileSystems.FsiFileSystemJoliet;

using (var stream = new MemoryStream())
{
    stream.Write(buffer, 0, bufferSize);

    // Here is where I need to either instantiate an FsiStream and copy
    // stream to it, but I can't figure out how to do this.

    fsi.Root.AddFile(relativePathFromImageRoot, iStreamObject);
}

      

+3


source to share


1 answer


You are trying to use the IMAPI2FS type library and are facing a common problem with this library. It was poorly written and quite difficult to use directly from a .NET program. Most of the api targeting programs were written in C ++ and use the imap2fs.h SDK header file.

The specific problem you are facing is that the type library importer has converted the second argument to AddFile () to FsiStream, a class type. This is a type you cannot create, it has the [noncreatable] library attribute. The type library converter was confused, the method actually takes an IStream argument. What you have to do is create your own IStream implementation and pass an instance from it as the second argument.

This can be worked around with the C # version 4 dynamic keyword, so the compiler is not going to complain about FsiStream. Here's an example of an implementation class that implements IStream:

using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.IO;

[ComVisible(true)]
class FsiStreamImpl : IStream {
    private Stream source;
    private FsiStreamImpl() { }
    public static dynamic Create(Stream from) {
        var stream = new FsiStreamImpl();
        stream.source = from;
        return stream;
    }

    public void Read(byte[] pv, int cb, IntPtr pcbRead) {
        int read = source.Read(pv, 0, cb);
        Marshal.WriteInt32(pcbRead, read);
    }

    public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) {
        long pos = source.Seek(dlibMove, (SeekOrigin)dwOrigin);
        Marshal.WriteInt64(plibNewPosition, pos);
    }

    public void Stat(out STATSTG pstatstg, int grfStatFlag) {
        var stat = new STATSTG();
        stat.type = 2;
        stat.cbSize = source.Length;
        stat.grfMode = 2;
        pstatstg = stat;
    }

    // Methods that we don't have to implement:
    public void Write(byte[] pv, int cb, IntPtr pcbWritten) {
        throw new NotImplementedException();
    }
    public void Clone(out IStream ppstm) {
        throw new NotImplementedException();
    }
    public void Commit(int grfCommitFlags) {
        throw new NotImplementedException();
    }
    public void SetSize(long libNewSize) {
        throw new NotImplementedException();
    }
    public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) {
        throw new NotImplementedException();
    }
    public void LockRegion(long libOffset, long cb, int dwLockType) {
        throw new NotImplementedException();
    }
    public void Revert() {
        throw new NotImplementedException();
    }
    public void UnlockRegion(long libOffset, long cb, int dwLockType) {
        throw new NotImplementedException();
    }
}

      

Now you can write your code like this:



using (var stream = new MemoryStream(buffer))
{
    stream.Write(buffer, 0, bufferSize);
    stream.Position = 0;
    fsi.Root.AddFile(relativePathFromImageRoot, FsiStreamImpl.Create(stream)));
}

      

Or code like this that I tested:

using (var file = new FileStream(@"c:\temp\test.txt", FileMode.Open, FileAccess.Read)) {
    fsi.Root.AddFile("test.txt", FsiStreamImpl.Create(file));
}

      

You may run into some additional problems, I only tested the snippets you posted. I have to point this to the Codeproject.com project written by a programmer who also fought with IMAPI2. He took a much broader approach, rather dangerous, and rewrote the entire type library with manual C # declarations. He has spent a lot of time on this, and the support questions only focus on how to use IMAPI2, so you can probably be sure of it.

+3


source







All Articles