views:

247

answers:

1

I realize .NET 4.0 is in Beta, but I'm hoping someone has a resolution for this. I'm trying to create a memory mapped file from a DLL:

FileStream file = File.OpenRead("C:\mydll.dll");
using (MemoryMappedFile mappedFile = MemoryMappedFile.CreateFromFile(file,
    "PEIMAGE", 1024 * 1024, MemoryMappedFileAccess.ReadExecute))
{
    using (MemoryMappedViewStream viewStream = mappedFile.CreateViewStream())
    {
        // read from the view stream
    }
}

Unfortunately, no matter what I do, I always get an UnauthorizedAccessException, for which the MSDN documentation states:

The operating system denied the specified access to the file; for example, access is set to Write or ReadWrite, but the file or directory is read-only.

I've monitored my application with Sysinternals Process Monitor, which shows that the file is indeed being opened successfully. I've also tried memory mapping other non-DLL files, but with the same result.

+1  A: 

Well, I've got an example based on the above which runs without exceptions. I've made two important changes:

  • I'm only specified MemoryMappedFileAccess.Read when creating the MemoryMappedFile. You've opened it for read, so you can only read. I haven't tried fixing it to allow execute as well by changing how the FileStream is opened.
  • I've made the CreateViewStream call explicitly use MemoryMappedFileAccess.Read as well. I'm not sure why it doesn't use the existing access rights by itself, but there we go.

Full program:

using System.IO;
using System.IO.MemoryMappedFiles;

class Test
{
    static void Main()
    {
        FileStream file = File.OpenRead("Test.cs");
        using (MemoryMappedFile mappedFile = MemoryMappedFile.CreateFromFile
               (file, "PEIMAGE", file.Length, MemoryMappedFileAccess.Read))
        {
            using (var viewStream = mappedFile.CreateViewStream
                   (0, file.Length, MemoryMappedFileAccess.Read))
            {
                // read from the view stream
            }
        }
    }
}
Jon Skeet
That code works for me, as well. However, what I'm trying to do is get the DLL loaded into memory as if it were about to be executed, so I can avoid doing all of the PE section mapping myself when reading the DLL's export table. For this, I need to map the file with ReadExecute access. But there doesn't appear to be a matching FileAccess.ReadExecute or even a FileAccess.Execute flag for FileStream.Open().
David Brown
Right. I'll see what I can do, but I think there's some distance between "I can't use it for this purpose" and "it's completely unusable" :)
Jon Skeet
Indeed. Perhaps I was a bit harsh in that regard. Actually, at the time, I didn't realize there was a difference between how a file is opened for Read access and for ReadExecute access. I thought it was simply a matter of how the file was handled **after** being opened. Thanks for the help, by the way!
David Brown
No problem - I just wish I could help you with the ReadExecute part. It may be worth logging a Connect issue - or email the BCL team directly. MS devs have always been very friendly IME :)
Jon Skeet