title: Determining if a dll is a .valid CLR dll by reading the PE directly (64bit issue)
body: <p>I am working on migrating a 32bit web application into 64bit and am having some problems with our plugin loader code.</p>
  
  <p>In the 32bit version, we scan the webapps bin directory for all .net dlls, then load them with <code>Assembly.Load</code> to check for the presence of our plugin attributes.</p>
  
  <p>We did this in a rather nifty way using public domain code:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Returns true if the file specified is a real CLR type, 
  /// otherwise false is returned.
  /// False is also returned in the case of an exception being caught
  /// &lt;/summary&gt;
  /// &lt;param name="file"&gt;A string representing the file to check for 
  /// CLR validity&lt;/param&gt;
  /// &lt;returns&gt;True if the file specified is a real CLR type, 
  /// otherwise false is returned.
  /// False is also returned in the case of an exception being 
  /// caught&lt;/returns&gt;
  public static bool IsDotNetAssembly(String file)
  {   
      Stream fs = new FileStream(@file, FileMode.Open, FileAccess.Read);
  
      try
      {
          BinaryReader reader = new BinaryReader(fs);
          //PE Header starts @ 0x3C (60). Its a 4 byte header.
          fs.Position = 0x3C;
          uint peHeader = reader.ReadUInt32();
          //Moving to PE Header start location...
          fs.Position = peHeader;
          uint peHeaderSignature = reader.ReadUInt32();
          ushort machine = reader.ReadUInt16();
          ushort sections = reader.ReadUInt16();
          uint timestamp = reader.ReadUInt32();
          uint pSymbolTable = reader.ReadUInt32();
          uint noOfSymbol = reader.ReadUInt32();
          ushort optionalHeaderSize = reader.ReadUInt16();
          ushort characteristics = reader.ReadUInt16();
  
          // PE Optional Headers 
          // To go directly to the datadictionary, we'll increase the stream's current position to with 96 (0x60). 
          // 28 bytes for Standard fields
          // 68 bytes for NT-specific fields 
          // 128 bytes DataDictionary 
          //  DataDictionay has 16 directories
          //  8 bytes per directory (4 bytes RVA and 4 bytes of Size.) 
          // 15th directory consist of CLR header! (if its 0, it is not a CLR file )
  
          uint[] dataDictionaryRVA = new uint[16];
          uint[] dataDictionarySize = new uint[16];            
          ushort dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 0x60);
  
          fs.Position = dataDictionaryStart;
          for (int i = 0; i &lt; 15; i++)
          {
              dataDictionaryRVA[i] = reader.ReadUInt32();
              dataDictionarySize[i] = reader.ReadUInt32();
          }
          if (dataDictionaryRVA[14] == 0)
          {
              fs.Close();
              return false;
          }
          else
          {
              fs.Close();
              return true;
          }
      }
      catch (Exception)
      {
          return false;
      }
      finally
      {
          fs.Close();
      }
  }
  </code></pre>
  
  <p>Now the problem is that we now have to handle 64bit or platform independent dlls and the offset seems to have changed and this code fails. Does anyone know the correct modifications to the above code to return true for valid 64bit only OR platform independent dlls?</p>