/*
CLASS {NATIVE_Shortcut_info|_CSharp}, NATIVE:

*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Diagnostics;

using System.IO;


public class AL4_shortcut
{
    
    //[DllImport("shfolder.dll", CharSet = CharSet.Auto)]
    //internal static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath);
	
	[Flags()]
	enum SLGP_FLAGS
	{
	    /// <summary>Retrieves the standard short (8.3 format) file name</summary>
	    SLGP_SHORTPATH = 0x1,
	    /// <summary>Retrieves the Universal Naming Convention (UNC) path name of the file</summary>
	    SLGP_UNCPRIORITY = 0x2,
	    /// <summary>Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded</summary>
	    SLGP_RAWPATH = 0x4
	}
	
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
	public struct WIN32_FIND_DATAW
	{
	    public uint dwFileAttributes;
	    public long ftCreationTime;
	    public long ftLastAccessTime;
	    public long ftLastWriteTime;
	    public uint nFileSizeHigh;
	    public uint nFileSizeLow;
	    public uint dwReserved0;
	    public uint dwReserved1;
	    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
	    public string cFileName;
	    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
	    public string cAlternateFileName;
	}
	
	[Flags()]
	enum SLR_FLAGS
	{
	    /// <summary>
	    /// Do not display a dialog box if the link cannot be resolved. When
	    //SLR_NO_UI is set,
	    /// the high-order word of fFlags can be set to a time-out value that
	    //specifies the
	    /// maximum amount of time to be spent resolving the link. The function
	    //returns if the
	    /// link cannot be resolved within the time-out duration. If the
	    //high-order word is set
	    /// to zero, the time-out duration will be set to the default value of
	    //3,000 milliseconds
	    /// (3 seconds). To specify a value, set the high word of fFlags to the
	    //desired time-out
	    /// duration, in milliseconds.
	    /// </summary>
	    SLR_NO_UI = 0x1,
	    /// <summary>Obsolete and no longer used</summary>
	    SLR_ANY_MATCH = 0x2,
	    /// <summary>If the link object has changed, update its path and list
	    //of identifiers.
	    /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty
	    //to determine
	    /// whether or not the link object has changed.</summary>
	    SLR_UPDATE = 0x4,
	    /// <summary>Do not update the link information</summary>
	    SLR_NOUPDATE = 0x8,
	    /// <summary>Do not execute the search heuristics</summary>
	    SLR_NOSEARCH = 0x10,
	    /// <summary>Do not use distributed link tracking</summary>
	    SLR_NOTRACK = 0x20,
	    /// <summary>Disable distributed link tracking. By default, distributed
	    //link tracking tracks
	    /// removable media across multiple devices based on the volume name.
	    //It also uses the
	    /// Universal Naming Convention (UNC) path to track remote file systems
	    //whose drive letter
	    /// has changed. Setting SLR_NOLINKINFO disables both types of tracking.
	    /// </summary>
	    SLR_NOLINKINFO = 0x40,
	    /// <summary>Call the Microsoft Windows Installer</summary>
	    SLR_INVOKE_MSI = 0x80
	}
	
	
	/// <summary>The IShellLink interface allows Shell links to be created, modified, and resolved</summary>
    [ComImport]
    [Guid("00021401-0000-0000-C000-000000000046")]
    internal class ShellLink
    {
    }

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214F9-0000-0000-C000-000000000046")]
    internal interface IShellLink
    {
        void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
         int cchMaxPath, out WIN32_FIND_DATAW pfd, int fFlags);
        void GetIDList(out IntPtr ppidl);
        void SetIDList(IntPtr pidl);
        void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
        void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
        void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
        void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
        void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
        void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
        void GetHotkey(out short pwHotkey);
        void SetHotkey(short wHotkey);
        void GetShowCmd(out int piShowCmd);
        void SetShowCmd(int iShowCmd);
        void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
        void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
        void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
        void Resolve(IntPtr hwnd, int fFlags);
        void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
    }
	
	[ComImport, Guid("0000010c-0000-0000-c000-000000000046"),
	InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	public interface IPersist
	{
	    [PreserveSig]
	    void GetClassID(out Guid pClassID);
	}
	
	
	[ComImport, Guid("0000010b-0000-0000-C000-000000000046"),
	InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	public interface IPersistFile : IPersist
	{
	    new void GetClassID(out Guid pClassID);
	    [PreserveSig]
	    int IsDirty();
	
	    [PreserveSig]
	    void Load([In, MarshalAs(UnmanagedType.LPWStr)]
	    string pszFileName, uint dwMode);
	
	    [PreserveSig]
	    void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
	        [In, MarshalAs(UnmanagedType.Bool)] bool fRemember);
	
	    [PreserveSig]
	    void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
	
	    [PreserveSig]
	    void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
	}
	
    const uint STGM_READ = 0;
    const int MAX_PATH = 260;

	
	public static string ResolveShortcut(string filename)
	{
		ShellLink link = new ShellLink();
		((IPersistFile)link).Load(filename, STGM_READ);
		// TODO: if I can get hold of the hwnd call resolve first.
		// This handles moved and renamed files.
		// ((IShellLink)link).Resolve(hwnd, 0)
		StringBuilder sb = new StringBuilder(MAX_PATH);
		WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
		((IShellLink)link).GetPath(sb, sb.Capacity, out data, 0);
		return sb.ToString();
		var fileInfo = new FileInfo(filename);
	}
	
	public static void MakeShortcut(string filename, string target_filename,
		string arguments, string workdir)
	{
		ShellLink link = new ShellLink();
		
		((IShellLink)link).SetPath(target_filename);
		((IShellLink)link).SetArguments(arguments);
		((IShellLink)link).SetWorkingDirectory(workdir);
		((IPersistFile)link).Save(filename, true);
	}

}

/*
CONST STR : NATIVE_Import_native_shortcut_info = @
            ""

            NATIVE_Resolve_link = @
            "   RESULT = AL4_shortcut.ResolveShortcut(X_Path);"
            
            NATIVE_Create_link = @
            "	AL4_shortcut.MakeShortcut(X_Path,X_Target,X_Arguments,X_Work);"
            .



END
*/
