using System;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.ComponentModel;
using Y.FileQueryEngine.Win32.Constants;
using Y.FileQueryEngine.Win32.Structures;
namespace Y.FileQueryEngine.Win32
{
internal class Win32Api
{
private const string KERNEL32DLL = "kernel32.dll";
private const string USER32DLL = "user32.dll";
#region dll imports
///
/// Creates the file specified by 'lpFileName' with desired access, share mode, security attributes,
/// creation disposition, flags and attributes.
///
/// Fully qualified path to a file
/// Requested access (write, read, read/write, none)
/// Share mode (read, write, read/write, delete, all, none)
/// IntPtr to a 'SECURITY_ATTRIBUTES' structure
/// Action to take on file or device specified by 'lpFileName' (CREATE_NEW,
/// CREATE_ALWAYS, OPEN_ALWAYS, OPEN_EXISTING, TRUNCATE_EXISTING)
/// File or device attributes and flags (typically FILE_ATTRIBUTE_NORMAL)
/// IntPtr to a valid handle to a template file with 'GENERIC_READ' access right
/// IntPtr handle to the 'lpFileName' file or device or 'INVALID_HANDLE_VALUE'
[DllImport(KERNEL32DLL, SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
///
/// Closes the file specified by the IntPtr 'hObject'.
///
/// IntPtr handle to a file
/// 'true' if successful, otherwise 'false'
[DllImport(KERNEL32DLL, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(
IntPtr hObject);
///
/// Fills the 'BY_HANDLE_FILE_INFORMATION' structure for the file specified by 'hFile'.
///
/// Fully qualified name of a file
/// Out BY_HANDLE_FILE_INFORMATION argument
/// 'true' if successful, otherwise 'false'
[DllImport(KERNEL32DLL, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetFileInformationByHandle(
IntPtr hFile,
out BY_HANDLE_FILE_INFORMATION lpFileInformation);
///
/// Deletes the file specified by 'fileName'.
///
/// Fully qualified path to the file to delete
/// 'true' if successful, otherwise 'false'
[DllImport(KERNEL32DLL, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteFile(
string fileName);
///
/// Read data from the file specified by 'hFile'.
///
/// IntPtr handle to the file to read
/// IntPtr to a buffer of bytes to receive the bytes read from 'hFile'
/// Number of bytes to read from 'hFile'
/// Number of bytes read from 'hFile'
/// IntPtr to an 'OVERLAPPED' structure
/// 'true' if successful, otherwise 'false'
[DllImport(KERNEL32DLL)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ReadFile(
IntPtr hFile,
IntPtr lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
///
/// Writes the
///
/// IntPtr handle to the file to write
/// IntPtr to a buffer of bytes to write to 'hFile'
/// Number of bytes in 'lpBuffer' to write to 'hFile'
/// Number of bytes written to 'hFile'
/// IntPtr to an 'OVERLAPPED' structure
/// 'true' if successful, otherwise 'false'
[DllImport(KERNEL32DLL, SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WriteFile(
IntPtr hFile,
IntPtr bytes,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
int overlapped);
///
/// Writes the data in 'lpBuffer' to the file specified by 'hFile'.
///
/// IntPtr handle to file to write
/// Buffer of bytes to write to file 'hFile'
/// Number of bytes in 'lpBuffer' to write to 'hFile'
/// Number of bytes written to 'hFile'
/// IntPtr to an 'OVERLAPPED' structure
/// 'true' if successful, otherwise 'false'
[DllImport(KERNEL32DLL, SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WriteFile(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
int overlapped);
///
/// Sends the 'dwIoControlCode' to the device specified by 'hDevice'.
///
/// IntPtr handle to the device to receive 'dwIoControlCode'
/// Device IO Control Code to send
/// Input buffer if required
/// Size of input buffer
/// Output buffer if required
/// Size of output buffer
/// Number of bytes returned in output buffer
/// IntPtr to an 'OVERLAPPED' structure
/// 'true' if successful, otherwise 'false'
[DllImport(KERNEL32DLL, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceIoControl(
IntPtr hDevice,
UInt32 dwIoControlCode,
IntPtr lpInBuffer,
Int32 nInBufferSize,
out USN_JOURNAL_DATA lpOutBuffer,
Int32 nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped);
///
/// Sends the control code 'dwIoControlCode' to the device driver specified by 'hDevice'.
///
/// IntPtr handle to the device to receive 'dwIoControlCode
/// Device IO Control Code to send
/// Input buffer if required
/// Size of input buffer
/// Output buffer if required
/// Size of output buffer
/// Number of bytes returned
/// Pointer to an 'OVERLAPPED' struture
///
[DllImport(KERNEL32DLL, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceIoControl(
IntPtr hDevice,
UInt32 dwIoControlCode,
IntPtr lpInBuffer,
Int32 nInBufferSize,
IntPtr lpOutBuffer,
Int32 nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped);
///
/// Sets the number of bytes specified by 'size' of the memory associated with the argument 'ptr'
/// to zero.
///
///
///
[DllImport(KERNEL32DLL)]
public static extern void ZeroMemory(IntPtr ptr, int size);
[DllImport(USER32DLL, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT pt);
[DllImport(USER32DLL, CharSet = CharSet.Auto)]
public static extern Int32 GetWindowLong(IntPtr hWnd, Int32 nIndex);
[DllImport(USER32DLL, CharSet = CharSet.Auto)]
public static extern Int32 SetWindowLong(IntPtr hWnd, Int32 nIndex, Int32 newVal);
#endregion
#region functions
///
/// Writes the data in 'text' to the alternate stream ':Description' of the file 'currentFile.
///
/// Fully qualified path to a file
/// Data to write to the ':Description' stream
public static void WriteAlternateStream(string currentfile, string text)
{
string AltStreamDesc = currentfile + ":Description";
IntPtr txtBuffer = IntPtr.Zero;
IntPtr hFile = IntPtr.Zero;
DeleteFile(AltStreamDesc);
string descText = text.TrimEnd(' ');
try
{
hFile = CreateFile(AltStreamDesc, Win32ApiConstant.GENERIC_WRITE, 0, IntPtr.Zero,
Win32ApiConstant.CREATE_ALWAYS, 0, IntPtr.Zero);
if (-1 != hFile.ToInt32())
{
txtBuffer = Marshal.StringToHGlobalUni(descText);
uint nBytes, count;
nBytes = (uint)descText.Length;
bool bRtn = WriteFile(hFile, txtBuffer, sizeof(char) * nBytes, out count, 0);
if (!bRtn)
{
if ((sizeof(char) * nBytes) != count)
{
throw new Exception(string.Format("Bytes written {0} should be {1} for file {2}.",
count, sizeof(char) * nBytes, AltStreamDesc));
}
else
{
throw new Exception("WriteFile() returned false");
}
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
catch (Exception exception)
{
//string msg = string.Format("Exception caught in WriteAlternateStream()\n '{0}'\n for file '{1}'.",
// exception.Message, AltStreamDesc);
//Console.WriiteLine(msg);
throw;
}
finally
{
CloseHandle(hFile);
hFile = IntPtr.Zero;
Marshal.FreeHGlobal(txtBuffer);
GC.Collect();
}
}
///
/// Adds the ':Description' alternate stream name to the argument 'currentFile'.
///
/// The file whose alternate stream is to be read
/// A string value representing the value of the alternate stream
public static string ReadAlternateStream(string currentfile)
{
string AltStreamDesc = currentfile + ":Description";
string returnstring = ReadAlternateStreamEx(AltStreamDesc);
return returnstring;
}
///
/// Reads the stream represented by 'currentFile'.
///
/// Fully qualified path including stream
/// Value of the alternate stream as a string
public static string ReadAlternateStreamEx(string currentfile)
{
string returnstring = string.Empty;
IntPtr hFile = IntPtr.Zero;
IntPtr buffer = IntPtr.Zero;
try
{
hFile = CreateFile(currentfile, Win32ApiConstant.GENERIC_READ, 0, IntPtr.Zero, Win32ApiConstant.OPEN_EXISTING, 0, IntPtr.Zero);
if (-1 != hFile.ToInt32())
{
buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
ZeroMemory(buffer, 1000 * sizeof(char));
uint nBytes;
bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero);
if (bRtn)
{
if (nBytes > 0)
{
returnstring = Marshal.PtrToStringAuto(buffer);
//byte[] byteBuffer = new byte[nBytes];
//for (int i = 0; i < nBytes; i++)
//{
// byteBuffer[i] = Marshal.ReadByte(buffer, i);
//}
//returnstring = Encoding.Unicode.GetString(byteBuffer, 0, (int)nBytes);
}
else
{
throw new Exception("ReadFile() returned true but read zero bytes");
}
}
else
{
if (nBytes <= 0)
{
throw new Exception("ReadFile() read zero bytes.");
}
else
{
throw new Exception("ReadFile() returned false");
}
}
}
else
{
Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
if (!excptn.Message.Contains("cannot find the file"))
{
throw excptn;
}
}
}
catch (Exception exception)
{
//string msg = string.Format("Exception caught in ReadAlternateStream(), '{0}'\n for file '{1}'.",
// exception.Message, currentfile);
//Console.WriteLine(msg);
//Console.WriteLine(exception.Message);
throw;
}
finally
{
CloseHandle(hFile);
hFile = IntPtr.Zero;
if (buffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(buffer);
}
GC.Collect();
}
return returnstring;
}
///
/// Read the encrypted alternate stream specified by 'currentFile'.
///
/// Fully qualified path to encrypted alternate stream
/// The un-encrypted value of the alternate stream as a string
public static string ReadAlternateStreamEncrypted(string currentfile)
{
string returnstring = string.Empty;
IntPtr buffer = IntPtr.Zero;
IntPtr hFile = IntPtr.Zero;
try
{
hFile = CreateFile(currentfile, Win32ApiConstant.GENERIC_READ, 0, IntPtr.Zero, Win32ApiConstant.OPEN_EXISTING, 0, IntPtr.Zero);
if (-1 != hFile.ToInt32())
{
buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
ZeroMemory(buffer, 1000 * sizeof(char));
uint nBytes;
bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero);
if (0 != nBytes)
{
returnstring = DecryptLicenseString(buffer, nBytes);
}
}
else
{
Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
if (!excptn.Message.Contains("cannot find the file"))
{
throw excptn;
}
}
}
catch (Exception exception)
{
Console.WriteLine("Exception caught in ReadAlternateStreamEncrypted()");
Console.WriteLine(exception.Message);
}
finally
{
CloseHandle(hFile);
hFile = IntPtr.Zero;
if (buffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(buffer);
}
GC.Collect();
}
return returnstring;
}
///
/// Writes the value of 'LicenseString' as an encrypted stream to the file:stream specified
/// by 'currentFile'.
///
/// Fully qualified path to the alternate stream
/// The string value to encrypt and write to the alternate stream
public static void WriteAlternateStreamEncrypted(string currentFile, string LicenseString)
{
RC2CryptoServiceProvider rc2 = null;
CryptoStream cs = null;
MemoryStream ms = null;
uint count = 0;
IntPtr buffer = IntPtr.Zero;
IntPtr hFile = IntPtr.Zero;
try
{
Encoding enc = Encoding.Unicode;
byte[] ba = enc.GetBytes(LicenseString);
ms = new MemoryStream();
rc2 = new RC2CryptoServiceProvider();
rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
rc2.IV = GetBytesFromHexString("827d961224d99b2d");
cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(ba, 0, ba.Length);
cs.FlushFinalBlock();
buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
ZeroMemory(buffer, 1000 * sizeof(char));
uint nBytes = (uint)ms.Length;
Marshal.Copy(ms.GetBuffer(), 0, buffer, (int)nBytes);
DeleteFile(currentFile);
hFile = CreateFile(currentFile, Win32ApiConstant.GENERIC_WRITE, 0, IntPtr.Zero,
Win32ApiConstant.CREATE_ALWAYS, 0, IntPtr.Zero);
if (-1 != hFile.ToInt32())
{
bool bRtn = WriteFile(hFile, buffer, nBytes, out count, 0);
}
else
{
Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
if (!excptn.Message.Contains("cannot find the file"))
{
throw excptn;
}
}
}
catch (Exception exception)
{
Console.WriteLine("WriteAlternateStreamEncrypted()");
Console.WriteLine(exception.Message);
}
finally
{
CloseHandle(hFile);
hFile = IntPtr.Zero;
if (cs != null)
{
cs.Close();
cs.Dispose();
}
rc2 = null;
if (ms != null)
{
ms.Close();
ms.Dispose();
}
if (buffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(buffer);
}
}
}
///
/// Encrypt the string 'LicenseString' argument and return as a MemoryStream.
///
/// The string value to encrypt
/// A MemoryStream which contains the encrypted value of 'LicenseString'
private static MemoryStream EncryptLicenseString(string LicenseString)
{
Encoding enc = Encoding.Unicode;
byte[] ba = enc.GetBytes(LicenseString);
MemoryStream ms = new MemoryStream();
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
rc2.IV = GetBytesFromHexString("827d961224d99b2d");
CryptoStream cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(ba, 0, ba.Length);
cs.Close();
cs.Dispose();
rc2 = null;
return ms;
}
///
/// Given an IntPtr to a bufer and the number of bytes, decrypt the buffer and return an
/// unencrypted text string.
///
/// An IntPtr to the 'buffer' containing the encrypted string
/// The number of bytes in 'buffer' to decrypt
///
private static string DecryptLicenseString(IntPtr buffer, uint nBytes)
{
byte[] ba = new byte[nBytes];
for (int i = 0; i < nBytes; i++)
{
ba[i] = Marshal.ReadByte(buffer, i);
}
MemoryStream ms = new MemoryStream(ba);
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
rc2.IV = GetBytesFromHexString("827d961224d99b2d");
CryptoStream cs = new CryptoStream(ms, rc2.CreateDecryptor(), CryptoStreamMode.Read);
string licenseString = string.Empty;
byte[] ba1 = new byte[4096];
int irtn = cs.Read(ba1, 0, 4096);
Encoding enc = Encoding.Unicode;
licenseString = enc.GetString(ba1, 0, irtn);
cs.Close();
cs.Dispose();
ms.Close();
ms.Dispose();
rc2 = null;
return licenseString;
}
///
/// Gets the byte array generated from the value of 'hexString'.
///
/// Hexadecimal string
/// Array of bytes generated from 'hexString'.
public static byte[] GetBytesFromHexString(string hexString)
{
int numHexChars = hexString.Length / 2;
byte[] ba = new byte[numHexChars];
int j = 0;
for (int i = 0; i < ba.Length; i++)
{
string hex = new string(new char[] { hexString[j], hexString[j + 1] });
ba[i] = byte.Parse(hex, System.Globalization.NumberStyles.HexNumber);
j = j + 2;
}
return ba;
}
#endregion
}
}