// Оригинальная версия написана Cristian Forsberg
// и находится по адресу 
//http://www.businessanyplace.net/?p=spfileman


// Переделано и переведено на русский для Windows Mobile 6
// Visual Studio 2008
// Александр Климов

//------------------------------------------------------------------------------
/// <copyright from='2004' to='2005' company='Christian Forsberg'>
///		Copyright (c) Christian Forsberg, chris@businessanyplace.net.
///
///   This program is distributed in the hope that it will be useful,
///   but WITHOUT ANY WARRANTY; without even the implied warranty of
///   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
/// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace FileManager
{
	/// <summary>
	/// Utility class for launch programs and files.
	/// </summary>
	public class ShellExecute
	{
    public static void Start(string fileName, string parameters)
    {
      int nSize;
      SHELLEXECUTEEX see;
      IntPtr pFile;
      IntPtr pParams;

      see = new SHELLEXECUTEEX();

      nSize = fileName.Length * 2 + 2;
      pFile = localAlloc(MemoryAllocFlags.LPtr, nSize);
      Marshal.Copy(Encoding.Unicode.GetBytes(fileName), 0, pFile, nSize - 2);

      nSize = parameters.Length * 2 + 2;
      pParams = localAlloc(MemoryAllocFlags.LPtr, nSize);
      Marshal.Copy(Encoding.Unicode.GetBytes(parameters), 0, pParams, nSize - 2);
			
      see.lpFile = pFile;
      see.lpParameters = pParams;
			
      ShellExecuteEx(see);

      LocalFree(pFile);
      LocalFree(pParams);
      //return see.hProcess;
    }

    public static void Start(string fileName)
    {
      Start(fileName, "");
    }

    private static IntPtr localAlloc(MemoryAllocFlags uFlags, int uBytes)
    {
      const int GMEM_FIXED = 0x0000;
      const int LMEM_ZEROINIT  = 0x0040;
      const int LPTR = (GMEM_FIXED | LMEM_ZEROINIT);

      IntPtr ptr = LocalAlloc(LPTR, (uint)uBytes);
      if (ptr == IntPtr.Zero)
        throw new Exception("Out of memory!");
      return ptr; 
    }

    private enum MemoryAllocFlags : int
    {
      Fixed		 = 0x00,
      ZeroInit = 0x40,
      LPtr     = ZeroInit | Fixed
    }

    #region APIs
    [DllImport("coredll.dll")]
    private static extern IntPtr LocalAlloc(uint uFlags, uint Bytes);

    [DllImport("coredll")]
    private static extern IntPtr LocalFree(IntPtr hMem);

    [DllImport("coredll")]
    private extern static int ShellExecuteEx( SHELLEXECUTEEX ex );

    private class SHELLEXECUTEEX
    {
      public UInt32 cbSize		= 60; 
      public UInt32 fMask			= 0; 
      public IntPtr hwnd			= IntPtr.Zero; 
      public IntPtr lpVerb		= IntPtr.Zero; 
      public IntPtr lpFile		= IntPtr.Zero; 
      public IntPtr lpParameters	= IntPtr.Zero; 
      public IntPtr lpDirectory	= IntPtr.Zero; 
      public int nShow			= 0; 
      public IntPtr hInstApp		= IntPtr.Zero; 
      public IntPtr lpIDList		= IntPtr.Zero; 
      public IntPtr lpClass		= IntPtr.Zero; 
      public IntPtr hkeyClass		= IntPtr.Zero; 
      public UInt32 dwHotKey		= 0; 
      public IntPtr hIcon			= IntPtr.Zero; 
      public IntPtr hProcess		= IntPtr.Zero; 
    }
    #endregion
  }
}
