The Labs \ Source Viewer \ SSCLI \ System.Globalization \ MemoryMapFile

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Globalization
  16. {
  17.     using System.IO;
  18.     using Microsoft.Win32;
  19.     using Microsoft.Win32.SafeHandles;
  20.     using System.Runtime.InteropServices;
  21.     using System.Runtime.CompilerServices;
  22.     using System.Security;
  23.     using System.Security.Permissions;
  24.     using System.Runtime.Versioning;
  25.    
  26.     ////////////////////////////////////////////////////////////////////////////
  27.     //
  28.     // Open a Memory mapped file using read-only attribute.
  29.     // The memory mapped file can be named or unnamed.
  30.     // The end result will be a byte pointer pointing to the beginning of the specified file.
  31.     //
  32.     // DANGER DANGER DANGER
  33.     // NECESSARY PERMISSIONS TO CREATE MEMORY MAPPED FILE ARE BYPASSED IN THIS CLASS.
  34.     // PLEASE CHECK THAT YOU WON'T HAVE SECURITY PROBLEM IF YOU USE THIS CLASS IN UNTRUSTED
  35.     // SCENARIO.
  36.     //
  37.     // ALSO, WE DON'T PROVIDE A MECHANISM FOR EXPLICITLY UNMAPPING THE MEMORY,
  38.     // BUT THAT HAPPENS IF WE EVER FINALIZE THE SAFEHANDLE STORED IN AN INSTANCE
  39.     // OF THIS CLASS.
  40.     //
  41.     ////////////////////////////////////////////////////////////////////////////
  42.     internal sealed class MemoryMapFile
  43.     {
  44.        
  45.         unsafe private byte* bytes;
  46.        
  47.         //
  48.         // The only handle we keep it open is the mapped memory section and we close
  49.         // both the stream and mapped file handle as the OS keep the memory section
  50.         // mapped even when closing the files.
  51.         // The benefit for closing the file and stream handle is have flexability
  52.         // to rename the file while it is in use.
  53.         //
  54.         private SafeViewOfFileHandle viewOfFileHandle = null;
  55.         private long fileSize = 0;
  56.        
  57.         private const int PAGE_READONLY = 2;
  58.         private const int SECTION_MAP_READ = 4;
  59.        
  60.         [ResourceExposure(ResourceScope.Machine)]
  61.         [ResourceConsumption(ResourceScope.Machine)]
  62.         unsafe internal MemoryMapFile(string fileName) : this(fileName, null)
  63.         {
  64.         }
  65.        
  66.         [ResourceExposure(ResourceScope.Machine)]
  67.         [ResourceConsumption(ResourceScope.Machine)]
  68.         unsafe internal MemoryMapFile(string fileName, string fileMappingName)
  69.         {
  70.             //
  71.             // Use native API to create the file directly.
  72.             //
  73.             SafeFileHandle fileHandle = Win32Native.UnsafeCreateFile(fileName, FileStream.GENERIC_READ, FileShare.Read, null, FileMode.Open, 0, IntPtr.Zero);
  74.             int lastError = Marshal.GetLastWin32Error();
  75.             if (fileHandle.IsInvalid) {
  76.                 BCLDebug.Assert(false, "Failed to create file " + fileName + ", GetLastError = " + lastError);
  77.                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_UnexpectedWin32Error"), lastError));
  78.             }
  79.            
  80.             int highSize;
  81.             int lowSize = Win32Native.GetFileSize(fileHandle, out highSize);
  82.             if (lowSize == Win32Native.INVALID_FILE_SIZE) {
  83.                 BCLDebug.Assert(false, "Failed to get the file size of " + fileName + ", GetLastError = " + lastError);
  84.                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_UnexpectedWin32Error"), lastError));
  85.             }
  86.            
  87.             fileSize = (((long)highSize) << 32) | ((uint)lowSize);
  88.            
  89.             if (fileSize == 0) {
  90.                 // we cannot map zero size file. the caller should check for the file size.
  91.                 fileHandle.Close();
  92.                 return;
  93.             }
  94.            
  95.             SafeFileMappingHandle fileMapHandle = Win32Native.CreateFileMapping(fileHandle, IntPtr.Zero, PAGE_READONLY, 0, 0, fileMappingName);
  96.             fileHandle.Close();
  97.             lastError = Marshal.GetLastWin32Error();
  98.             if (fileMapHandle.IsInvalid) {
  99.                 BCLDebug.Assert(false, "Failed to create file mapping for file " + fileName + ", GetLastError = " + lastError);
  100.                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_UnexpectedWin32Error"), lastError));
  101.             }
  102.            
  103.             viewOfFileHandle = Win32Native.MapViewOfFile(fileMapHandle, SECTION_MAP_READ, 0, 0, UIntPtr.Zero);
  104.             lastError = Marshal.GetLastWin32Error();
  105.             if (viewOfFileHandle.IsInvalid) {
  106.                 BCLDebug.Assert(false, "Failed to map a view of file " + fileName + ", GetLastError = " + lastError);
  107.                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_UnexpectedWin32Error"), lastError));
  108.             }
  109.            
  110.             bytes = (byte*)viewOfFileHandle.DangerousGetHandle();
  111.            
  112.             fileMapHandle.Close();
  113.         }
  114.        
  115.         internal long FileSize {
  116.             get { return fileSize; }
  117.         }
  118.        
  119.         unsafe internal byte* GetBytePtr()
  120.         {
  121.             BCLDebug.Assert(bytes != null, "bytes should not be null");
  122.             return (bytes);
  123.         }
  124.        
  125.     }
  126. }

Developer Fusion