Ultimate task that I am trying to achieve is to read zone information from batch file that I downloaded from the internet. My implementation is based on this SO answer and on some additional resources such as MSDN documentation of UnmanagedMemoryStream
. Below you can see what I was able to came up with, however, that code simply throws NullReferenceException
on ReadByte
and I have absolutely no idea why. Ideas?
private static void Main(string[] args)
{
var mainStream = NativeMethods.CreateFileW(
"<path to batch file directory>any.bat:Zone.Identifier",
NativeConstants.GENERIC_READ,
NativeConstants.FILE_SHARE_READ,
IntPtr.Zero,
NativeConstants.OPEN_EXISTING,
0,
IntPtr.Zero);
unsafe
{
using (var memoryStream = new UnmanagedMemoryStream((byte*)mainStream.ToPointer(), 1, 1, FileAccess.Read))
{
var zoneInfo = memoryStream.ReadByte();
}
}
}
public partial class NativeMethods
{
/// Return Type: HANDLE->void*
///lpFileName: LPCWSTR->WCHAR*
///dwDesiredAccess: DWORD->unsigned int
///dwShareMode: DWORD->unsigned int
///lpSecurityAttributes: LPSECURITY_ATTRIBUTES->_SECURITY_ATTRIBUTES*
///dwCreationDisposition: DWORD->unsigned int
///dwFlagsAndAttributes: DWORD->unsigned int
///hTemplateFile: HANDLE->void*
[CLSCompliantAttribute(false)]
[DllImport("kernel32.dll", EntryPoint = "CreateFileW")]
public static extern System.IntPtr CreateFileW(
[InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
[InAttribute()] System.IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
[InAttribute()] System.IntPtr hTemplateFile
);
}
[CLSCompliantAttribute(false)]
public partial class NativeConstants
{
/// GENERIC_WRITE -> (0x40000000L)
public const uint GENERIC_WRITE = 1073741824;
/// GENERIC_READ -> (0x80000000L)
public const uint GENERIC_READ = 2147483648;
/// FILE_SHARE_READ -> 0x00000001
public const uint FILE_SHARE_READ = 1;
/// OPEN_EXISTING -> 3
public const uint OPEN_EXISTING = 3;
}
Some notes:
mainStream
value is valid, it is not-1
memoryStream
acts like everything is just fine,canRead
returnstrue
etc.
To reproduce this issue, i.e. to get yourself some testing batch file, you can for example create file "any.bat", upload it to e.g. Google drive and download it. That way the zone information should be added into this file and on top of that the value in Zone.Identifier
should be set to 3, which stads for ZONE_INTERNET
.
Stack trace does not reveal anything interesting IMHO:
at System.IO.UnmanagedMemoryStream.ReadByte() at ConsoleApplication1.Program.Main(String[] args) in c:\Users\MH185162\Documents\Visual Studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:line 41 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()