1
0
Files
2025-10-31 08:58:36 +01:00

312 lines
14 KiB
C#

using System;
//using System.Collections.Generic;
using System.IO;
//using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
//using Shell32;
using IWshRuntimeLibrary;
//using System.Threading.Tasks;
namespace PinTo10v2
{
static public class Utils
{
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static string originalImagePathName;
static int unicodeSize = IntPtr.Size * 2;
static void GetPointers(out IntPtr imageOffset, out IntPtr imageBuffer)
{
IntPtr pebBaseAddress = GetBasicInformation().PebBaseAddress;
var processParameters = Marshal.ReadIntPtr(pebBaseAddress, 4 * IntPtr.Size);
imageOffset = processParameters.Increment(4 * 4 + 5 * IntPtr.Size + unicodeSize + IntPtr.Size + unicodeSize);
imageBuffer = Marshal.ReadIntPtr(imageOffset, IntPtr.Size);
}
internal static void ChangeImagePathName(string newFileName)
{
IntPtr imageOffset, imageBuffer;
GetPointers(out imageOffset, out imageBuffer);
//Read original data
var imageLen = Marshal.ReadInt16(imageOffset);
originalImagePathName = Marshal.PtrToStringUni(imageBuffer, imageLen / 2);
var newImagePathName = Path.Combine(Path.GetDirectoryName(originalImagePathName), newFileName);
if (newImagePathName.Length > originalImagePathName.Length) throw new Exception("new ImagePathName cannot be longer than the original one");
//Write the string, char by char
var ptr = imageBuffer;
foreach (var unicodeChar in newImagePathName)
{
Marshal.WriteInt16(ptr, unicodeChar);
ptr = ptr.Increment(2);
}
Marshal.WriteInt16(ptr, 0);
//Write the new length
Marshal.WriteInt16(imageOffset, (short)(newImagePathName.Length * 2));
}
internal static void RestoreImagePathName()
{
IntPtr imageOffset, ptr;
GetPointers(out imageOffset, out ptr);
foreach (var unicodeChar in originalImagePathName)
{
Marshal.WriteInt16(ptr, unicodeChar);
ptr = ptr.Increment(2);
}
Marshal.WriteInt16(ptr, 0);
Marshal.WriteInt16(imageOffset, (short)(originalImagePathName.Length * 2));
}
public static ProcessBasicInformation GetBasicInformation()
{
uint status;
ProcessBasicInformation pbi;
int retLen;
var handle = System.Diagnostics.Process.GetCurrentProcess().Handle;
if ((status = NtQueryInformationProcess(handle, 0,
out pbi, Marshal.SizeOf(typeof(ProcessBasicInformation)), out retLen)) >= 0xc0000000)
throw new Exception("Windows exception. status=" + status);
return pbi;
}
[DllImport("ntdll.dll")]
public static extern uint NtQueryInformationProcess(
[In] IntPtr ProcessHandle,
[In] int ProcessInformationClass,
[Out] out ProcessBasicInformation ProcessInformation,
[In] int ProcessInformationLength,
[Out] [Optional] out int ReturnLength
);
public static IntPtr Increment(this IntPtr ptr, int value)
{
unchecked
{
if (IntPtr.Size == sizeof(Int32))
return new IntPtr(ptr.ToInt32() + value);
else
return new IntPtr(ptr.ToInt64() + value);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct ProcessBasicInformation
{
public uint ExitStatus;
public IntPtr PebBaseAddress;
public IntPtr AffinityMask;
public int BasePriority;
public IntPtr UniqueProcessId;
public IntPtr InheritedFromUniqueProcessId;
}
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
// //////////////////////////////////////////////////////////////////////
public static void CreateShortcut(string targetFileLocation)
{
string currentuserstart = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Microsoft\Windows\Start Menu\Programs";
string wholefileName = Path.GetFileName(targetFileLocation);
string extension = Path.GetExtension(wholefileName);
string filenamenoextension = Path.GetFileNameWithoutExtension(wholefileName);
string DirectoryName = Path.GetDirectoryName(targetFileLocation);
string shortcutLocation = currentuserstart + @"\" + filenamenoextension + ".lnk"; //System.IO.Path.Combine(Environment.SpecialFolder.StartMenu.ToString(), "Dummy.lnk");
WshShell shell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutLocation);
//shortcut.Description = ""; // The description of the shortcut
shortcut.WorkingDirectory = DirectoryName; // The "Start in" path of the new shortcut
shortcut.TargetPath = targetFileLocation; // The path of the file that will launch when the shortcut is run
shortcut.Save(); // Save the shortcut
}
public static bool PinUnpinTaskbar(string filePath, bool pin)
{
if (!System.IO.File.Exists(filePath))
{
Console.WriteLine("\n\r" + "Specified file not found. Exiting...");
Environment.Exit(1);
};
//throw new FileNotFoundException(filePath);
int MAX_PATH = 255;
var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
string localizedVerb = szPinToStartLocalized.ToString();
string path = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
// create the shell application object
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
var name = verb.Name;
//Console.WriteLine("Verb Name = " + name);
if (verb.Name.Equals(localizedVerb))
{
//Console.WriteLine("Trying to do it...");
verb.DoIt();
return true;
}
}
return false;
}
// //////////////////////////////////////////////////////////////////////
public static bool PinUnpinStart(string filePath, bool pin)
{
//Console.WriteLine("Pinning to Start...");
if (!System.IO.File.Exists(filePath)) throw new FileNotFoundException(filePath);
int MAX_PATH = 255;
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
StringBuilder szInvPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
string osversionfromreg = Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion", "ProductName", "nullvalue").ToString();
string win10 = "Windows 10";
string win7 = "Windows 7";
bool iswin10 = osversionfromreg.Contains(win10);
bool iswin7 = osversionfromreg.Contains(win7);
var actionIndex = pin ? 51201 : 51394;
var invActionIndex = pin ? 51394 : 51201;
if (iswin10)
{
actionIndex = pin ? 51201 : 51394;
invActionIndex = pin ? 51394 : 51201;
}
if (iswin7)
{
actionIndex = pin ? 5381 : 5382;
invActionIndex = pin ? 5382 : 5381;
}
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
string localizedVerb = szPinToStartLocalized.ToString();
LoadString(hShell32, (uint)invActionIndex, szInvPinToStartLocalized, MAX_PATH);
string invLocalizedVerb = szInvPinToStartLocalized.ToString();
string path = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
// create the shell application object
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
dynamic verbs = link.Verbs();
int counter = 0;
while (1 == 1) // setup a loop to keep trying to pin to start - will try 20 times at 500ms interval and then fail if not successful
{
shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
directory = shellApplication.NameSpace(path);
link = directory.ParseName(fileName);
verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
if (verb.Name.Equals(localizedVerb))
{
verb.DoIt();
System.Threading.Thread.Sleep(500);
counter = counter = + 1;
}
if (verb.Name.Equals(invLocalizedVerb)) // check for the existance of the opposite verb to confirm if it's been successful
{
//Console.WriteLine("I think it's done! Exiting...");
return true;
}
if (counter == 20) // Try 20 times (10 seconds) and then fail...
{
return false;
}
}
}
}
public static bool CheckifVerbExists(string filePath, bool pin, bool startmenu)
{
//Console.WriteLine("Pinning to Start...");
if (!System.IO.File.Exists(filePath)) throw new FileNotFoundException(filePath);
int MAX_PATH = 255;
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
StringBuilder szInvPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
string osversionfromreg = Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion", "ProductName", "nullvalue").ToString();
string win10 = "Windows 10";
string win7 = "Windows 7";
bool iswin10 = osversionfromreg.Contains(win10);
bool iswin7 = osversionfromreg.Contains(win7);
var actionIndex = pin ? 51201 : 51394;
var invActionIndex = pin ? 51394 : 51201;
if (iswin10)
{
if (startmenu)
{
actionIndex = pin ? 51201 : 51394;
}
if (!startmenu)
{
actionIndex = pin ? 5386 : 5387;
}
}
if (iswin7)
{
if (startmenu)
{
actionIndex = pin ? 5381 : 5382;
}
if (!startmenu)
{
actionIndex = pin ? 5386 : 5387;
}
}
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
string localizedVerb = szPinToStartLocalized.ToString();
string path = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
// create the shell application object
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
var name = verb.Name;
//Console.WriteLine("Verb name = " + name);
if (verb.Name.Equals(localizedVerb))
{
// verb.DoIt();
return true;
}
}
return false;
}
}
}