Sunday, May 22, 2011

CIFS performance measurement in Windows

windows has a very strange behavior when it comes to Copy/Move . and what is strange about it is the Progress bar and the information related to the progress bar. it is as far is could get from accuracy in MBps and time remaining , but its not their fault because estimating the time and MBps is very hard since their is so many factors related to those kind of measurements , so i decided to make small utility to get the average Timing and MBps , and i need those readings as a part of network performance benchmark on CIFS shares

check below for the code in C# , i hope that you will benefit from it, take into consideration i wrote the code quick and dirty :-)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace Copy_test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

      //this dictionary will hold the file names and the full path
        public Dictionary<string, string> selectFilesInfo = new Dictionary<string, string>();



        private void browseDSbutton2_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                textBox1.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {

       
            openFileDialog1.Multiselect = true;
            openFileDialog1.Title = "source files to be copied";
            openFileDialog1.Filter = "All Files|*.*";
            openFileDialog1.FileName = "";

            if (openFileDialog1.ShowDialog() ==DialogResult.OK)
            {
             
                for(int i=0;i<openFileDialog1.FileNames.Length;i++)
                {
                 
                  // add filenames and filepath to dictionary
                   selectFilesInfo.Add(openFileDialog1.SafeFileNames[i],openFileDialog1.FileNames[i]);
                 
                    textBox2.Text += openFileDialog1.FileNames[i] + " ";
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
           // create a stopwatch instance which comes in handy
            Stopwatch sw = Stopwatch.StartNew();
           //stop the stop watch because we didn't start taking readings yet
            sw.Stop();
            long filesizes = 0;
            FileInfo fi;

            foreach (KeyValuePair<string, string> kvp in selectFilesInfo)
            {
                 //application core it will measure the timing for every copy process, take the summation of the file sizes
                fi = new FileInfo(kvp.Value);
                filesizes  = filesizes + fi.Length;
                sw.Start();
                File.Copy(kvp.Value,textBox1.Text + "\\" + kvp.Key,true);
                sw.Stop();
            }


            long time = sw.ElapsedMilliseconds/1000;
            filesizes = (filesizes / 1024)/1024;
         
            MessageBox.Show("Copying effictive time took : " + time.ToString() + " seconds to write " +
                filesizes + " MB in avarage speed "+ filesizes/time +"MBps");
        }
    }
}

Friday, May 20, 2011

EasyHook for systemcall hooking

i was researching the web couple of months a go regarding a library which can provide a hooking functionality to windows system calls in order to be able to create transparent encryption layer for Fucked up databases such as FoxPro, i came across to two libraries . the first one is Windows Detours and the other one is  called EasyHook.

first i tried to work With Windows Detours and encounters 1 million problem form installation to compiling to packaging the encryption library, so i said to my self why not give EasyHook a try since i love Opensource projects and i support them with all my heart.  and what i like about it the most that it supports extending (hooking) unmanaged code (APIs) with pure managed ones like C# for 32 and 64 kernels, and it provides unmanaged API which not requires .Net Framework

below i will show who to start working with EasyHook local hooking from managed code "Quick and dirty" but i prefer if you are looking for more don't relay on my code. Go and read the documentation.


1. first you need to initialize the Hook as a parameters you need to pass the DLL filename and the function implemented by that DLL, and you need to provide the function wrapper and your function as an argument below i will initialize IO related functions


CreateWHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "CreateFileW"), new DCreateFileW(CreateFileWHook), this);
                CreateWHook.ThreadACL.SetExclusiveACL(new Int32[0]);

                CreateAHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "CreateFileA"), new DCreateFileA(CreateFileAHook), this);
                CreateAHook.ThreadACL.SetExclusiveACL(new Int32[0]);

                ReadHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "ReadFile"), new DReadFile(ReadFileHook), this);
                ReadHook.ThreadACL.SetExclusiveACL(new Int32[0]);

                WriteHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "WriteFile"), new DWriteFile(WriteFileHook), this);
                WriteHook.ThreadACL.SetExclusiveACL(new Int32[0]);

                CloseHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "CloseHandle"), new DCloseHandle(CloseHandleHook), this);
                CloseHook.ThreadACL.SetExclusiveACL(new Int32[0]);



  MoveAHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "MoveFileA"), new DMoveFileA(MoveFileAHook), this);
                MoveAHook.ThreadACL.SetExclusiveACL(new Int32[0]);

                MoveWHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "MoveFileW"), new DMoveFileW(MoveFileWHook), this);
                MoveWHook.ThreadACL.SetExclusiveACL(new Int32[0]);

                DeleteAHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "DeleteFileA"), new DDeleteFileA(DeleteFileAHook), this);
                DeleteAHook.ThreadACL.SetExclusiveACL(new Int32[0]);

                DeleteWHook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "DeleteFileW"), new DDeleteFileW(DeleteFileWHook), this);
                DeleteWHook.ThreadACL.SetExclusiveACL(new Int32[0]);


2. create wrappers


  [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Unicode, SetLastError = true)]

        delegate IntPtr DCreateFileW(String InFileName, UInt32 InDesiredAccess, UInt32 InShareMode,
                                     IntPtr InSecurityAttributes, UInt32 InCreationDisposition,
                                     UInt32 InFlagsAndAttributes, IntPtr InTemplateFile);


  [UnmanagedFunctionPointer(CallingConvention.StdCall,
                 CharSet = CharSet.Ansi, SetLastError = true)]

        delegate IntPtr DCreateFileA(String InFileName, UInt32 InDesiredAccess, UInt32 InShareMode,
                                     IntPtr InSecurityAttributes, UInt32 InCreationDisposition,
                                     UInt32 InFlagsAndAttributes, IntPtr InTemplateFile);



        [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Ansi, SetLastError = true)]

        unsafe delegate bool DReadFile(IntPtr hFile, void* pBuffer, int NumberOfBytesToRead,
                                        int* pNumberOfBytesRead, int Overlapped);



 [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Unicode, SetLastError = true)]

        delegate bool DWriteFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite,
                                  out uint lpNumberOfBytesWritten, [In]
                                  ref System.Threading.NativeOverlapped lpOverlapped);


 [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Unicode, SetLastError = true)]

        delegate bool DCloseHandle(IntPtr hObject);


 [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Ansi, SetLastError = true)]
        delegate int DMoveFileA(String lpExistingFileName, String lpNewFileName);


 [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Unicode, SetLastError = true)]
        delegate int DMoveFileW(String lpExistingFileName, String lpNewFileName);


 [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Ansi, SetLastError = true)]
        delegate bool DDeleteFileA(string path);


 [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Unicode, SetLastError = true)]
        delegate bool DDeleteFileW(string path);

3. define the functions to be externalized


[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            CallingConvention = CallingConvention.StdCall)]

        static extern IntPtr CreateFileW(String InFileName, UInt32 InDesiredAccess, UInt32 InShareMode,
                                         IntPtr InSecurityAttributes, UInt32 InCreationDisposition,
                                         UInt32 InFlagsAndAttributes, IntPtr InTemplateFile);


  [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true,
            CallingConvention = CallingConvention.StdCall)]

        static extern IntPtr CreateFileA(String InFileName, UInt32 InDesiredAccess, UInt32 InShareMode,
                                         IntPtr InSecurityAttributes, UInt32 InCreationDisposition,
                                         UInt32 InFlagsAndAttributes, IntPtr InTemplateFile);


   [DllImport("kernel32", SetLastError = true)]

        static extern unsafe bool ReadFile(IntPtr hFile, void* pBuffer, int NumberOfBytesToRead,
                                             int* pNumberOfBytesRead, int Overlapped);

  [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            CallingConvention = CallingConvention.StdCall)]

        static extern bool WriteFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite,
                                      out uint lpNumberOfBytesWritten,
                                     [In] ref System.Threading.NativeOverlapped lpOverlapped);

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            CallingConvention = CallingConvention.StdCall)]
        static extern bool CloseHandle(IntPtr hObject);

 [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
        internal static extern int MoveFileA(String lpExistingFileName, String lpNewFileName);

 [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern int MoveFileW(String lpExistingFileName, String lpNewFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        static extern bool DeleteFileA(string path);
  [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern bool DeleteFileW(string path);

3. Implement your functions


protected static unsafe IntPtr CreateFileWHook(String InFileName, UInt32 InDesiredAccess,
                                                    UInt32 InShareMode, IntPtr InSecurityAttributes,
                                                    UInt32 InCreationDisposition, UInt32 InFlagsAndAttributes,
                                                    IntPtr InTemplateFile)
        {  /*your implementation goes here */  }


protected static unsafe IntPtr CreateFileAHook(String InFileName, UInt32 InDesiredAccess,
                                                    UInt32 InShareMode, IntPtr InSecurityAttributes,
                                                    UInt32 InCreationDisposition, UInt32 InFlagsAndAttributes,
                                                    IntPtr InTemplateFile)
      {  /*your implementation goes here */  }


protected unsafe bool ReadFileHook(IntPtr hFile, void* pBuffer, int NumberOfBytesToRead,
                                                int* pNumberOfBytesRead, int Overlapped)
      {  /*your implementation goes here */  }


protected bool WriteFileHook(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite,
                                          out uint lpNumberOfBytesWritten,
                                          [In] ref System.Threading.NativeOverlapped lpOverlapped)
       {  /*your implementation goes here */  }

protected bool CloseHandleHook(IntPtr hObject)
       {  /*your implementation goes here */  }


 protected int MoveFileAHook(String lpExistingFileName, String lpNewFileName)
       {  /*your implementation goes here*/  }

protected int MoveFileWHook(String lpExistingFileName, String lpNewFileName)
       {  /*your implementation goes here */  }

protected bool DeleteFileAHook(string path)
       {  /*your implementation goes here*/  }

protected bool DeleteFileWHook(string path)
       {  /*your implementation goes here*/  }

note the unsafe definition ; why ?

and thats it. see how easy as in EasyHook .