I am applying a proxy for my application's WebBrowser control using WinInet and the good thing about that method is that it doesn't affect the system's proxy and only applies the proxy to my application. However it only works with proxies that have no username and password.
Here is the code
private const int INTERNET_OPEN_TYPE_DIRECT = 1;
private const int INTERNET_OPEN_TYPE_PRECONFIG = 0;
public static string ApplicationName;
[DllImport("user32.dll", SetLastError = true)]
public static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static bool ShowWindow(IntPtr hwnd, User32.WindowShowStyle nCmdShow);
[DllImport("user32.dll")]
public static bool EnableWindow(IntPtr hwnd, bool enabled);
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static IntPtr InternetOpen(string lpszAgent, int dwAccessType, string lpszProxyName, string lpszProxyBypass, int dwFlags);
[DllImport("wininet.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static bool InternetCloseHandle(IntPtr hInternet);
[DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
private static bool InternetSetOption(IntPtr hInternet, User32.InternetOption dwOption, IntPtr lpBuffer, int lpdwBufferLength);
[DllImport("wininet.dll", EntryPoint = "InternetQueryOption", CharSet = CharSet.Ansi, SetLastError = true)]
private static bool InternetQueryOptionList(IntPtr handle, User32.InternetOption optionFlag, ref User32.InternetPerConnOptionList optionList, ref int size);
public static bool SetConnectionProxy(string proxyServer)
{
IntPtr hInternet = User32.InternetOpen(User32.ApplicationName, 1, (string) null, (string) null, 0);
User32.InternetPerConnOption[] internetPerConnOptionArray = new User32.InternetPerConnOption[2]
{
new User32.InternetPerConnOption()
{
dwOption = 1,
Value = {
dwValue = 2
}
},
new User32.InternetPerConnOption()
{
dwOption = 2,
Value = {
pszValue = Marshal.StringToHGlobalAnsi(proxyServer)
}
}
};
IntPtr ptr1 = Marshal.AllocCoTaskMem(Marshal.SizeOf((object) internetPerConnOptionArray[0]) + Marshal.SizeOf((object) internetPerConnOptionArray[1]));
IntPtr ptr2 = ptr1;
foreach (User32.InternetPerConnOption internetPerConnOption in internetPerConnOptionArray)
{
Marshal.StructureToPtr((object) internetPerConnOption, ptr2, false);
ptr2 = (IntPtr) ((int) ptr2 + Marshal.SizeOf((object) internetPerConnOption));
}
User32.InternetPerConnOptionList perConnOptionList = new User32.InternetPerConnOptionList()
{
pOptions = ptr1
};
perConnOptionList.Size = Marshal.SizeOf((object) perConnOptionList);
perConnOptionList.Connection = IntPtr.Zero;
perConnOptionList.OptionCount = internetPerConnOptionArray.Length;
perConnOptionList.OptionError = 0;
int num1 = Marshal.SizeOf((object) perConnOptionList);
IntPtr num2 = Marshal.AllocCoTaskMem(num1);
Marshal.StructureToPtr((object) perConnOptionList, num2, true);
bool flag = User32.InternetSetOption(hInternet, User32.InternetOption.InternetOptionPerConnectionOption, num2, num1);
Marshal.FreeCoTaskMem(ptr1);
Marshal.FreeCoTaskMem(num2);
User32.InternetCloseHandle(hInternet);
if (!flag)
throw new ApplicationException(" Set Internet Option Failed!");
else
return true;
}
private static User32.InternetPerConnOptionList GetSystemProxy()
{
User32.InternetPerConnOption[] internetPerConnOptionArray = new User32.InternetPerConnOption[3]
{
new User32.InternetPerConnOption()
{
dwOption = 1
},
new User32.InternetPerConnOption()
{
dwOption = 2
},
new User32.InternetPerConnOption()
{
dwOption = 3
}
};
IntPtr num = Marshal.AllocCoTaskMem(Marshal.SizeOf((object) internetPerConnOptionArray[0]) + Marshal.SizeOf((object) internetPerConnOptionArray[1]) + Marshal.SizeOf((object) internetPerConnOptionArray[2]));
IntPtr ptr = num;
foreach (User32.InternetPerConnOption internetPerConnOption in internetPerConnOptionArray)
{
Marshal.StructureToPtr((object) internetPerConnOption, ptr, false);
ptr = (IntPtr) ((int) ptr + Marshal.SizeOf((object) internetPerConnOption));
}
User32.InternetPerConnOptionList optionList = new User32.InternetPerConnOptionList()
{
pOptions = num
};
optionList.Size = Marshal.SizeOf((object) optionList);
optionList.Connection = IntPtr.Zero;
optionList.OptionCount = internetPerConnOptionArray.Length;
optionList.OptionError = 0;
int size = Marshal.SizeOf((object) optionList);
if (!User32.InternetQueryOptionList(IntPtr.Zero, User32.InternetOption.InternetOptionPerConnectionOption, ref optionList, ref size))
throw new ApplicationException(" Set Internet Option Failed! ");
else
return optionList;
}
public static bool RestoreSystemProxy()
{
IntPtr hInternet = User32.InternetOpen(User32.ApplicationName, 1, (string) null, (string) null, 0);
User32.InternetPerConnOptionList systemProxy = User32.GetSystemProxy();
int num1 = Marshal.SizeOf((object) systemProxy);
IntPtr num2 = Marshal.AllocCoTaskMem(num1);
Marshal.StructureToPtr((object) systemProxy, num2, true);
bool flag = User32.InternetSetOption(hInternet, User32.InternetOption.InternetOptionPerConnectionOption, num2, num1);
Marshal.FreeCoTaskMem(systemProxy.pOptions);
Marshal.FreeCoTaskMem(num2);
if (!flag)
throw new ApplicationException(" Set Internet Option Failed! ");
User32.InternetSetOption(hInternet, User32.InternetOption.InternetOptionSettingsChanged, IntPtr.Zero, 0);
User32.InternetSetOption(hInternet, User32.InternetOption.InternetOptionRefresh, IntPtr.Zero, 0);
User32.InternetCloseHandle(hInternet);
return true;
}
public enum WindowShowStyle : uint
{
Hide = 0U,
ShowNormal = 1U,
ShowMinimized = 2U,
Maximize = 3U,
ShowMaximized = 3U,
ShowNormalNoActivate = 4U,
Show = 5U,
Minimize = 6U,
ShowMinNoActivate = 7U,
ShowNoActivate = 8U,
Restore = 9U,
ShowDefault = 10U,
ForceMinimized = 11U,
}
private enum InternetOption
{
InternetOptionRefresh = 37,
InternetOptionSettingsChanged = 39,
InternetOptionPerConnectionOption = 75,
}
private enum InternetOptionPerConnFlags
{
ProxyTypeDirect = 1,
ProxyTypeProxy = 2,
ProxyTypeAutoProxyUrl = 4,
ProxyTypeAutoDetect = 8,
}
private struct InternetPerConnOption
{
public int dwOption;
public User32.InternetPerConnOptionOptionUnion Value;
}
private struct InternetPerConnOptionList
{
public int Size;
public IntPtr Connection;
public int OptionCount;
public int OptionError;
public IntPtr pOptions;
}
[StructLayout(LayoutKind.Explicit)]
private struct InternetPerConnOptionOptionUnion
{
[FieldOffset(0)]
public int dwValue;
[FieldOffset(0)]
public IntPtr pszValue;
[FieldOffset(0)]
private readonly System.Runtime.InteropServices.ComTypes.FILETIME ftValue;
}
private enum InternetPerConnOptionEnum
{
InternetPerConnFlags = 1,
InternetPerConnProxyServer = 2,
InternetPerConnProxyBypass = 3,
InternetPerConnAutoconfigUrl = 4,
InternetPerConnAutodiscoveryFlags = 5,
InternetPerConnAutoconfigSecondaryUrl = 6,
InternetPerConnAutoconfigReloadDelayMins = 7,
InternetPerConnAutoconfigLastDetectTime = 8,
InternetPerConnAutoconfigLastDetectUrl = 9,
InternetPerConnFlagsUi = 10,
}
Question: How could i use that code to apply a proxy with username and password ?
Notes:
I know that there is a couple of similar questions here but i cannot
get a good answer out of them.
I heard that this can be achieved using InternetSetOption however
i can't find how to implement that cause i don't have enough
knowledge about windoes functions etc...
The proper options to set the proxy credentials in WinINET are INTERNET_OPTION_PROXY_USERNAME and INTERNET_OPTION_PROXY_PASSWORD as shown at http://msdn.microsoft.com/en-us/library/windows/desktop/aa385328(v=vs.85).aspx
You may need to implement IAuthenticate instead, since the other calls are really intended for WinINET handles, which aren't exposed when you're using the Web Browser control.
Related
I am developing an automation interface program and I looking to enhance capability with a machine software which uses a COPYDATA API aimed at C++. The goal is to control and report status of the machine through my own software.
The method uses pointers and memory allocation which I have not had any experience with thus far.
I have looked at a number of other sources, such as this with no luck at the moment. I have tried the following code to try and run a program on the machine software.
class Program
{
[DllImport("User32.dll", SetLastError = true, EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll", SetLastError = true, EntryPoint = "SendMessage")]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public IntPtr dwData; // Any value the sender chooses. Perhaps its main window handle?
public int cbData; // The count of bytes in the message.
public IntPtr lpData; // The address of the message.
}
const int WM_COPYDATA = 0x004A;
const int EXTERNAL_CD_COMMAND_RUN_ASYNC = 0x8001;
static void Main(string[] args)
{
Console.WriteLine("{0} bit process.", (IntPtr.Size == 4) ? "32" : "64");
Console.Write("Press ENTER to run test.");
Console.ReadLine();
IntPtr hwnd = FindWindow(null, "InSpecAppFrame");
Console.WriteLine("hwnd = {0:X}", hwnd.ToInt64());
var cds = new COPYDATASTRUCT();
byte[] buff = Encoding.ASCII.GetBytes("C:\\Users\\Desktop\\COPYDATATEST.iwp");
cds.dwData = (IntPtr)EXTERNAL_CD_COMMAND_RUN_ASYNC;
cds.lpData = Marshal.AllocHGlobal(buff.Length);
Marshal.Copy(buff, 0, cds.lpData, buff.Length);
cds.cbData = buff.Length;
var ret = SendMessage(hwnd, WM_COPYDATA, 0, ref cds);
Console.WriteLine("Return value is {0}", ret);
Marshal.FreeHGlobal(cds.lpData);
Console.ReadLine();
}
}
Running this code returns 0 for both hwnd and ret and the machine software does not react.
Sending a command is the first step, the next will be to try and get a response so I can monitor machine statuses etc.
As a sidenote to what Alejandro wrote (and that I think is correct), you can simplify a little the code, removing a copy of the data. You can directly "pin" your byte[]. It is important that you remember to "unpin" it (for this reason the try/finally block)
There is another potential problem in your code (a problem that I saw only on a second pass of the code): C strings must be \0 terminated (so "Foo" must be "Foo\0"). Your Encoding.ASCII doesn't guarantee a \0 termination. The classical way to do it is to make the byte[] "a little larger" than necessary. I've done the changes necessary.
[DllImport("User32.dll", SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public IntPtr dwData; // Any value the sender chooses. Perhaps its main window handle?
public int cbData; // The count of bytes in the message.
public IntPtr lpData; // The address of the message.
}
[StructLayout(LayoutKind.Sequential)]
public struct ExternalGetPositionType
{
public double X;
public double Y;
public double Z;
public double W;
}
const int WM_COPYDATA = 0x004A;
const int EXTERNAL_CD_COMMAND_RUN_ASYNC = 0x8001;
const int EXTERNAL_CD_GET_POSITION_PCS = 0x8011;
const int EXTERNAL_CD_GET_POSITION_MCS = 0x8012;
static void Main(string[] args)
{
Console.WriteLine("{0} bit process.", (IntPtr.Size == 4) ? "32" : "64");
Console.Write("Press ENTER to run test.");
Console.ReadLine();
IntPtr hwnd = FindWindow(null, "Form1");
Console.WriteLine("hwnd = {0:X}", hwnd.ToInt64());
if (hwnd == IntPtr.Zero)
{
throw new Exception("hwnd not found");
}
IntPtr ret = RunAsync(hwnd, #"C:\Users\Desktop\COPYDATATEST.iwp");
Console.WriteLine($"Return value for EXTERNAL_CD_COMMAND_RUN_ASYNC is {ret}");
ret = GetPosition(hwnd, true, new ExternalGetPositionType { X = 1, Y = 2, Z = 3, W = 4 });
Console.WriteLine($"Return value for EXTERNAL_CD_GET_POSITION_PCS is {ret}");
ret = GetPosition(hwnd, false, new ExternalGetPositionType { X = 10, Y = 20, Z = 30, W = 40 });
Console.WriteLine($"Return value for EXTERNAL_CD_GET_POSITION_MCS is {ret}");
Console.ReadLine();
}
public static IntPtr RunAsync(IntPtr hwnd, string str)
{
// We have to add a \0 terminator, so len + 1 / len + 2 for Unicode
int len = Encoding.Default.GetByteCount(str);
var buff = new byte[len + 1]; // len + 2 for Unicode
Encoding.Default.GetBytes(str, 0, str.Length, buff, 0);
IntPtr ret;
GCHandle h = default(GCHandle);
try
{
h = GCHandle.Alloc(buff, GCHandleType.Pinned);
var cds = new COPYDATASTRUCT();
cds.dwData = (IntPtr)EXTERNAL_CD_COMMAND_RUN_ASYNC;
cds.lpData = h.AddrOfPinnedObject();
cds.cbData = buff.Length;
ret = SendMessage(hwnd, WM_COPYDATA, 0, ref cds);
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
return ret;
}
public static IntPtr GetPosition(IntPtr hwnd, bool pcs, ExternalGetPositionType position)
{
// We cheat here... It is much easier to pin an array than to copy around a struct
var positions = new[]
{
position
};
IntPtr ret;
GCHandle h = default(GCHandle);
try
{
h = GCHandle.Alloc(positions, GCHandleType.Pinned);
var cds = new COPYDATASTRUCT();
cds.dwData = pcs ? (IntPtr)EXTERNAL_CD_GET_POSITION_PCS : (IntPtr)EXTERNAL_CD_GET_POSITION_MCS;
cds.lpData = h.AddrOfPinnedObject();
cds.cbData = Marshal.SizeOf<ExternalGetPositionType>();
ret = SendMessage(hwnd, WM_COPYDATA, 0, ref cds);
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
return ret;
}
Note even that instead of ASCII you can use the Default encoding, that is a little better.
If you want to receive the messages, in your Winforms do:
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_COPYDATA)
{
COPYDATASTRUCT cds = Marshal.PtrToStructure<COPYDATASTRUCT>(m.LParam);
if (cds.dwData == (IntPtr)EXTERNAL_CD_COMMAND_RUN_ASYNC)
{
string str = Marshal.PtrToStringAnsi(cds.lpData);
Debug.WriteLine($"EXTERNAL_CD_COMMAND_RUN_ASYNC: {str}");
m.Result = (IntPtr)100; // If you want to return a value
}
else if (cds.dwData == (IntPtr)EXTERNAL_CD_GET_POSITION_PCS)
{
if (cds.cbData >= Marshal.SizeOf<ExternalGetPositionType>())
{
var position = Marshal.PtrToStructure<ExternalGetPositionType>(cds.lpData);
Debug.WriteLine($"EXTERNAL_CD_GET_POSITION_PCS: X = {position.X}, Y = {position.Y}, Z = {position.Z}, W = {position.W}");
m.Result = (IntPtr)200;
}
else
{
m.Result = (IntPtr)0;
}
}
else if (cds.dwData == (IntPtr)EXTERNAL_CD_GET_POSITION_MCS)
{
if (cds.cbData >= Marshal.SizeOf<ExternalGetPositionType>())
{
var position = Marshal.PtrToStructure<ExternalGetPositionType>(cds.lpData);
Debug.WriteLine($"EXTERNAL_CD_GET_POSITION_MCS: X = {position.X}, Y = {position.Y}, Z = {position.Z}, W = {position.W}");
m.Result = (IntPtr)300;
}
else
{
m.Result = (IntPtr)0;
}
}
return;
}
base.WndProc(ref m);
}
Note that if you control both the sender AND the receiver, it is better much better to use Unicode for the string parameter. You'll have to modify both the sender and the receiver: Encoding.Unicode.GetByteCount/Encoding.Unicode.GetBytes, the +2 instead of +1 and Marshal.PtrToStringUni.
I was looking for a short way to eject USB-devices via C#-code, so I coded a little class myself, yet it simply doesn't work. Since there's no popup that says "Lock success!" I assume that the problem relies within the "LockVolume"-function, but I don't know where.
Does anybody see the mistake I made?
class USBEject
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr SecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
byte[] lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
private IntPtr handle = IntPtr.Zero;
const int GENERIC_READ = 0x80000000;
const int GENERIC_WRITE = 0x40000000;
const int FILE_SHARE_READ = 0x1;
const int FILE_SHARE_WRITE = 0x2;
const int FSCTL_LOCK_VOLUME = 0x00090018;
const int FSCTL_DISMOUNT_VOLUME = 0x00090020;
const int IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808;
const int IOCTL_STORAGE_MEDIA_REMOVAL = 0x002D4804;
/// <summary>
/// Constructor for the USBEject class
/// </summary>
/// <param name="driveLetter">This should be the drive letter. Format: F:/, C:/..</param>
public USBEject(string driveLetter)
{
string filename = #"\\.\" + driveLetter[0] + ":";
handle = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 0x3, 0, IntPtr.Zero);
}
public bool Eject()
{
if (LockVolume(handle) && DismountVolume(handle))
{
PreventRemovalOfVolume(handle, false);
return AutoEjectVolume(handle);
}
return false;
}
private bool LockVolume(IntPtr handle)
{
uint byteReturned;
for (int i = 0; i < 10; i++)
{
if (DeviceIoControl(handle, FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero))
{
System.Windows.Forms.MessageBox.Show("Lock success!");
return true;
}
Thread.Sleep(500);
}
return false;
}
private bool PreventRemovalOfVolume(IntPtr handle, bool prevent)
{
byte[] buf = new byte[1];
uint retVal;
buf[0] = (prevent) ? (byte)1 : (byte)0;
return DeviceIoControl(handle, IOCTL_STORAGE_MEDIA_REMOVAL, buf, 1, IntPtr.Zero, 0, out retVal, IntPtr.Zero);
}
private bool DismountVolume(IntPtr handle)
{
uint byteReturned;
return DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
}
private bool AutoEjectVolume(IntPtr handle)
{
uint byteReturned;
return DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
}
private bool CloseVolume(IntPtr handle)
{
return CloseHandle(handle);
}
}
Changed just a little bit your code and it goes as follows:
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr SecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
byte[] lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
private IntPtr handle = IntPtr.Zero;
const uint GENERIC_READ = 0x80000000;
const uint GENERIC_WRITE = 0x40000000;
const int FILE_SHARE_READ = 0x1;
const int FILE_SHARE_WRITE = 0x2;
const int FSCTL_LOCK_VOLUME = 0x00090018;
const int FSCTL_DISMOUNT_VOLUME = 0x00090020;
const int IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808;
const int IOCTL_STORAGE_MEDIA_REMOVAL = 0x002D4804;
/// <summary>
/// Constructor for the USBEject class
/// </summary>
/// <param name="driveLetter">This should be the drive letter. Format: F:/, C:/..</param>
public IntPtr USBEject(string driveLetter)
{
string filename = #"\\.\" + driveLetter[0] + ":";
return CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 0x3, 0, IntPtr.Zero);
}
public bool Eject(IntPtr handle)
{
bool result = false;
if (LockVolume(handle) && DismountVolume(handle))
{
PreventRemovalOfVolume(handle, false);
result = AutoEjectVolume(handle);
}
CloseHandle(handle);
return result;
}
private bool LockVolume(IntPtr handle)
{
uint byteReturned;
for (int i = 0; i < 10; i++)
{
if (DeviceIoControl(handle, FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero))
{
System.Windows.Forms.MessageBox.Show("Lock success!");
return true;
}
Thread.Sleep(500);
}
return false;
}
private bool PreventRemovalOfVolume(IntPtr handle, bool prevent)
{
byte[] buf = new byte[1];
uint retVal;
buf[0] = (prevent) ? (byte)1 : (byte)0;
return DeviceIoControl(handle, IOCTL_STORAGE_MEDIA_REMOVAL, buf, 1, IntPtr.Zero, 0, out retVal, IntPtr.Zero);
}
private bool DismountVolume(IntPtr handle)
{
uint byteReturned;
return DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
}
private bool AutoEjectVolume(IntPtr handle)
{
uint byteReturned;
return DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
}
private bool CloseVolume(IntPtr handle)
{
return CloseHandle(handle);
}
So you can use it in two ways:
handle = USBEject("D:");
Eject(handle);
or directly:
Eject(USBEject("D:"));
It works for me on my Windows 10 machine (preview 14291)
Found the answer for my issue by using some of Roger Deep's code for the CreateFile call.
My code to remove a USB drive inside WPF Window:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
EjectDrive('K');
}
void EjectDrive(char driveLetter)
{
string path = #"\\.\" + driveLetter + #":";
IntPtr handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 0x3, 0, IntPtr.Zero);
if ((long)handle == -1)
{
MessageBox.Show("Unable to open drive " + driveLetter);
return;
}
int dummy = 0;
DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0,
IntPtr.Zero, 0, ref dummy, IntPtr.Zero);
CloseHandle(handle);
MessageBox.Show("OK to remove drive.");
}
[DllImport("kernel32", SetLastError = true)]
private static extern IntPtr CreateFile
(string filename, uint desiredAccess,
uint shareMode, IntPtr securityAttributes,
int creationDisposition, int flagsAndAttributes,
IntPtr templateFile);
[DllImport("kernel32")]
private static extern int DeviceIoControl
(IntPtr deviceHandle, uint ioControlCode,
IntPtr inBuffer, int inBufferSize,
IntPtr outBuffer, int outBufferSize,
ref int bytesReturned, IntPtr overlapped);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
Here's some code that I converted from a powershell script. You need to run with admin privileges and It works to "unmount" the USB drive. However, when you try to unplug the USB drive and plug it in again, it doesn't show up as a drive letter. (To get around that you need to type "WindowsKey-X" and select Disk-Manager to reassign the drive less to the USB device. (If anybody knows how to fix that problem please post to commits.) Here's the Code:
// Right click Project and Add Reference to System.Management.dll
using System.Management;
string mq = "SELECT * FROM Win32_Volume Where Name = 'E:\\'";
ManagementObjectSearcher ms = new ManagementObjectSearcher(mq);
foreach (ManagementObject mo in ms.Get())
{
mo["DriveLetter"] = null;
mo.Put();
ManagementBaseObject inParams = mo.GetMethodParameters("Dismount");
inParams["Force"] = false;
inParams["Permanent"] = false;
mo.InvokeMethod("Dismount", inParams, null);
}
Note that the powershell script also has the same problem of reattaching the USB device after ejecting. Here's the powershell script for your reference:
$vol = get-wmiobject -Class Win32_Volume |
where{$_.Name -eq 'E:\'}
$vol.DriveLetter = $null
$vol.Put()
$vol.Dismount($false, $false)
Here's a class that I just wrote to Manage Mounting and Unmounting of Removable USB Drives using WMI:
using System;
using System.IO;
using System.Text;
using System.Windows;
using System.Management; //<-- right-click on project and add reference
using System.Collections.Generic;
using System.Text.RegularExpressions;
// This Class implements Mount/Unmount for USB Removable Drives
// in a way similar to "Disk Manager" in the Control Panel.
//
// Currently, It doesn't implement "Eject" like when you right
// right-click on the USB icon on lower right of screen.
// The "Unmount" is similar to "Eject" except it dosn't
// cleanup the registry so that the USB drive can be automatically
// recognized again without manually mounting it from "Disk Manager"
// If somebody knows how to fix this class to gain this function...
// please post it to their thread. Thanks.
namespace WPM {
public struct UsbDriveItem_t {
public int Index;
public string DeviceId;
public char DriveLetter;
public string Label;
public override string ToString() {
if (Index < 0)
return "<none>";
else
return String.Format("{0}: {1}", DriveLetter, Label);
}
};
delegate void UsbEvent();
class UsbDriveRemovable {
public static int Unmount(char DriveLetter) {
bool success = ValidateAdmin("UsbDriveRemovable.Unmount()");
if (!success) return -1;
string Name = "'" + DriveLetter + ":\\\\'";
string mq = "SELECT * FROM Win32_Volume Where Name = " + Name;
ManagementObjectSearcher ms = new ManagementObjectSearcher(mq);
ManagementObjectCollection mc = ms.Get();
foreach (ManagementObject mo in mc) {
var DriveLetterI = mo["DriveLetter"].ToString();
mo["DriveLetter"] = null;
mo.Put();
ManagementBaseObject inParams = mo.GetMethodParameters("Dismount");
inParams["Force"] = false;
inParams["Permanent"] = false;
ManagementBaseObject outParams = mo.InvokeMethod("Dismount", inParams, null);
string rc = outParams["ReturnValue"].ToString();
mo.Dispose();
}
mc.Dispose();
ms.Dispose();
return 0;
}
public static int Mount(string DeviceId, char Letter = '?') {
bool success = ValidateAdmin("UsbDriveRemovable.Mount()");
if (!success) return -1;
if (Letter == '?' || Letter == '#') {
GetFirstUnsedLetter(out Letter);
}
string FixDeviceId = Regex.Replace(DeviceId, #"\\", #"\\");
string mq = "SELECT * FROM Win32_Volume WHERE DeviceId = '"
+ FixDeviceId
+ "'";
ManagementObjectSearcher ms = new ManagementObjectSearcher(mq);
ManagementObjectCollection mc = ms.Get();
foreach (ManagementObject mo in mc) {
ManagementBaseObject inParams = mo.GetMethodParameters("AddMountPoint");
inParams["Directory"] = Letter + ":\\";
ManagementBaseObject outParams = mo.InvokeMethod("AddMountPoint", inParams, null);
string rc = outParams["ReturnValue"].ToString();
mo.Dispose();
}
mc.Dispose();
ms.Dispose();
return 0;
}
/*List<UsbDriveItem_t>*/
public static int ListDrives(ref List<UsbDriveItem_t> DriveList) {
DriveList.Clear();
string mq = "SELECT * FROM Win32_Volume Where DriveType = '2'";
ManagementObjectSearcher ms = new ManagementObjectSearcher(mq);
ManagementObjectCollection mc = ms.Get();
int count = 0;
foreach (ManagementObject mo in mc) {
UsbDriveItem_t item = new UsbDriveItem_t();
item.Index = count;
item.Label = (mo["Label"] == null) ? "<none>" : mo["Label"].ToString();
item.DriveLetter = (mo["DriveLetter"] == null) ? '#' : mo["DriveLetter"].ToString()[0];
item.DeviceId = (mo["DeviceId"] == null) ? "<none>" : mo["DeviceId"].ToString();
DriveList.Add(item);
mo.Dispose();
}
count++;
mc.Dispose();
ms.Dispose();
return 0;
}
public static void MountItem(UsbDriveItem_t DriveItem) {
char DriveLetter = DriveItem.DriveLetter;
string DriveLabel = DriveItem.Label;
string DeviceId = DriveItem.DeviceId;
// Mount Drive if its not already Mounted
if (DriveLetter == '#') {
UsbDriveRemovable.GetFirstUnsedLetter(out DriveLetter);
UsbDriveRemovable.Mount(DeviceId, DriveLetter);
}
return;
}
public static void UnmountItem(UsbDriveItem_t DriveItem) {
char DriveLetter = DriveItem.DriveLetter;
UsbDriveRemovable.Unmount(DriveLetter);
return;
}
public static int GetFirstUnsedLetter(out char Letter) {
bool[] alphabet = new bool[26];
for (int i=0; i < 26; i++) {
alphabet[i] = false;
}
string mq = "SELECT * FROM Win32_Volume";
ManagementObjectSearcher ms = new ManagementObjectSearcher(mq);
ManagementObjectCollection mc = ms.Get();
foreach (ManagementObject mo in mc) {
if (mo["DriveLetter"] != null) {
char cc = mo["DriveLetter"].ToString()[0];
int ci = char.ToUpper(cc) - 65;
alphabet[ci] = true;
}
mo.Dispose();
}
mc.Dispose();
ms.Dispose();
int found = -1;
for (int i=3; i < 26; i++) {
if (alphabet[i] == false) {
found = i;
break;
}
}
if (found >= 0) {
Letter = (char)(found + 65);
return 0;
}
else {
Letter = '?';
return -1;
}
}
public static object
RegisterInsertEvent(UsbEvent InsertEvent) {
var insertQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
var insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += delegate(object sender, EventArrivedEventArgs e) {
// string driveName = e.NewEvent.Properties["DriveName"].Value.ToString();
Action action = delegate {
InsertEvent();
};
Application.Current.Dispatcher.BeginInvoke(action);
};
insertWatcher.Start();
return (object)insertWatcher;
}
public static object RegisterRemoveEvent(UsbEvent RemoveEvent) {
var removeQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
var removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += delegate(object sender, EventArrivedEventArgs e) {
// string driveName = e.NewEvent.Properties["DriveName"].Value.ToString();
Action action = delegate {
RemoveEvent();
};
Application.Current.Dispatcher.BeginInvoke(action);
};
removeWatcher.Start();
return (object)removeWatcher;
}
// Mount all UsbRemovable Drives that are not currently mounted
public static int MountAll() {
List<UsbDriveItem_t> DriveList = new List<UsbDriveItem_t>();
ListDrives(ref DriveList);
foreach (UsbDriveItem_t item in DriveList) {
if (item.DriveLetter == '?') {
Mount(item.DeviceId);
}
}
return 0;
}
// Unmount all UsbRemovable Drives
public static int UnmountAll() {
List<UsbDriveItem_t> DriveList = new List<UsbDriveItem_t>();
ListDrives(ref DriveList);
foreach (UsbDriveItem_t item in DriveList) {
if (item.DriveLetter != '?') {
Unmount(item.DriveLetter);
}
}
return 0;
}
public static bool IsAdministrator()
{
var id = System.Security.Principal.WindowsIdentity.GetCurrent();
var prin = new System.Security.Principal.WindowsPrincipal(id);
return prin.IsInRole(
System.Security.Principal.WindowsBuiltInRole.Administrator);
}
public static bool ValidateAdmin(string CalledFrom = null) {
if (CalledFrom == null) {
CalledFrom = "";
}
if (!IsAdministrator()) {
string msg = "Please rerun this application with admin privileges.\r\n\r\n"
+ "Access denied to call " + CalledFrom + "\r\n\r\n";
MessageBox.Show(msg, "ERROR");
return false;
}
return true;
}
public static void StartExplorer(char DriveLetter)
{
var proc1 = new System.Diagnostics.Process();
proc1.StartInfo.FileName = #"C:\\Windows\\System32\\explorer.exe";
proc1.StartInfo.Arguments = DriveLetter.ToString();
proc1.StartInfo.CreateNoWindow = true;
proc1.StartInfo.UseShellExecute = false;
proc1.StartInfo.RedirectStandardOutput = true;
proc1.StartInfo.RedirectStandardError = true;
proc1.Start();
proc1.WaitForExit();
string proc1out = proc1.StandardOutput.ReadToEnd();
string proc1err = proc1.StandardError.ReadToEnd();
//if (proc1.ExitCode != 0) {
// string msg = proc1out + "\r\n\r\n" + proc1err;
// MessageBox.Show(msg, "Error: Mountvol /R");
//}
proc1.Close();
}
} //class
} //namespace
/* DOESN'T WORK WELL...
// Kludge to get USB Drive to be recognized again
void UsbCleanup() {
var proc1 = new System.Diagnostics.Process();
proc1.StartInfo.FileName = #"C:\\Windows\\System32\\mountvol.exe";
proc1.StartInfo.Arguments = #"/R";
proc1.StartInfo.CreateNoWindow = true;
proc1.StartInfo.UseShellExecute = false;
proc1.StartInfo.RedirectStandardOutput = true;
proc1.StartInfo.RedirectStandardError = true;
proc1.Start();
proc1.WaitForExit();
string proc1out = proc1.StandardOutput.ReadToEnd();
string proc1err = proc1.StandardError.ReadToEnd();
if (proc1.ExitCode != 0) {
string msg = proc1out + "\r\n\r\n" + proc1err;
MessageBox.Show(msg, "Error: Mountvol /R");
}
proc1.Close();
var proc2 = new System.Diagnostics.Process();
proc2.StartInfo.FileName = #"C:\\Windows\\System32\\mountvol.exe";
proc2.StartInfo.Arguments = #"/E";
proc2.StartInfo.CreateNoWindow = true;
proc2.StartInfo.UseShellExecute = false;
proc2.StartInfo.RedirectStandardOutput = true;
proc2.StartInfo.RedirectStandardError = true;
proc2.Start();
proc2.WaitForExit();
string proc2out = proc2.StandardOutput.ReadToEnd();
string proc2err = proc2.StandardError.ReadToEnd();
if (proc2.ExitCode != 0) {
string msg = proc1out + "\r\n\r\n" + proc1err;
MessageBox.Show(msg, "Error: Mountvol /E");
}
proc2.Close();
return;
}
*/
You could convert the following PowerShell into C#:
$Eject = New-Object -comObject Shell.Application
$Eject.NameSpace(17).ParseName($usbDrvLetter+“:”).InvokeVerb(“Eject”)
this is the code to turn on the proxy:
Public struct Struct_INTERNET_PROXY_INFO
{
public int dwAccessType;
public IntPtr proxy;
public IntPtr proxyBypass;
};
[DllImport("wininet.dll", SetLastError = true)]
private static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int lpdwBufferLength);
private void RefreshIESettings(string strProxy)
{
const int INTERNET_OPTION_PROXY = 38;
const int INTERNET_OPEN_TYPE_PROXY = 3;
Struct_INTERNET_PROXY_INFO struct_IPI;
// Filling in structure
struct_IPI.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
struct_IPI.proxy = Marshal.StringToHGlobalAnsi(strProxy);
struct_IPI.proxyBypass = Marshal.StringToHGlobalAnsi("local");
// Allocating memory
IntPtr intptrStruct = Marshal.AllocCoTaskMem(Marshal.SizeOf(struct_IPI));
// Converting structure to IntPtr
Marshal.StructureToPtr(struct_IPI, intptrStruct, true);
bool iReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY, intptrStruct, Marshal.SizeOf(struct_IPI));
}
private void SomeFunc()
{
RefreshIESettings("192.168.1.200:1010");
System.Object nullObject = 0;
string strTemp = String.Empty;
System.Object nullObjStr = strTemp;
axWebBrowser1.Navigate("http://willstay.tripod.com", ref nullObject, ref nullObjStr, ref nullObjStr, ref nullObjStr);
}
but how can i turn off??????
thanks
Change Internet Proxy settings
Enable/Disable Proxy in IE through C#
Looks like this question was asked some time ago, but I just spent the last 2 hours researching this and couldn't find an answer. Finally I found some obscure site on accident with code that works.
Try your code above again, but instead of specifying the actual proxy address, use ":" instead.
Call RefreshIESettings like so: RefreshIESettings(":")
Change RefreshIESettings like this code block.
Just call this code like this. RefreshIESettings(":")
public static void RefreshIESettings(string strProxy)
{
const int INTERNET_OPTION_PROXY = 38;
const int INTERNET_OPEN_TYPE_PROXY = 3;
const int INTERNET_OPEN_TYPE_DIRECT = 1;
Struct_INTERNET_PROXY_INFO struct_IPI;
// Filling in structure
if (strProxy==":")
{
struct_IPI.dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
}
else
{
struct_IPI.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
}
struct_IPI.proxy = Marshal.StringToHGlobalAnsi(strProxy);
struct_IPI.proxyBypass = Marshal.StringToHGlobalAnsi("local");
// Allocating memory
IntPtr intptrStruct = Marshal.AllocCoTaskMem(Marshal.SizeOf(struct_IPI));
// Converting structure to IntPtr
Marshal.StructureToPtr(struct_IPI, intptrStruct, true);
bool iReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY, intptrStruct, Marshal.SizeOf(struct_IPI));
}
It's a pointer to an array of LSA_UNICODE_STRING structures. I found some code that does the inverse, i.e., create a LSA_UNICODE_STRING from a C# string. You can see that in the helper code section below.
What I have up to and including the call to LsaEnumerateAccountRights() seems to work just fine. Sensible values are returned for the array pointer and for the count.
I am at a loss as to how to get at those blasted strings. Help please? Pretty please?
UPDATE: nobugz's helper function in his answer below is ALMOST right, you only have to divide the length by UnicodeEncoding.CharSize. Thanks to him, I can now see the FIRST string in the array. See the updates at the end of both code sections below.
Now, how the netherworld do I do pointer arithmetic?
UPDATE 2.5: See answer for the functioning code. I lost the old, "wrong" code.
Found it! In this blog post. Now the amended code below works fully. It's even 64-bit safe!
The main code:
IntPtr sid = IntPtr.Zero;
int sidSize = 0;
StringBuilder domainName = new StringBuilder();
int nameSize = 0;
int accountType = 0;
LookupAccountName("\\\\" + tbHost.Text, tbUsername.Text, sid, ref sidSize,
domainName, ref nameSize, ref accountType);
domainName = new StringBuilder(nameSize);
sid = Marshal.AllocHGlobal(sidSize);
bool result = LookupAccountName("\\\\" + tbHost.Text, tbUsername.Text, sid, ref sidSize,
domainName, ref nameSize, ref accountType);
myResults.Text += String.Format("LookupAccountName(): Result {0}, SID {1}\n", result, sid);
LSA_UNICODE_STRING systemName = string2LSAUS("\\\\" + tbHost.Text);
IntPtr policyHandle = IntPtr.Zero;
LSA_OBJECT_ATTRIBUTES objAttrs = new LSA_OBJECT_ATTRIBUTES();
uint retVal = LsaOpenPolicy(ref systemName, ref objAttrs,
POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, out policyHandle);
myResults.Text += String.Format("LsaOpenPolicy(): Result {0}, Policy Handle {1}\n", retVal, policyHandle);
IntPtr rightsArray = IntPtr.Zero;
ulong rightsCount = 0;
long lretVal = LsaEnumerateAccountRights(policyHandle, sid, out rightsArray, out rightsCount);
retVal = LsaNtStatusToWinError(lretVal);
if (retVal != 0)
throw new System.ComponentModel.Win32Exception((int)retVal);
myResults.Text += String.Format("LsaEnumerateAccountRights(): Result {0}, RightsArray {1}, Count {2}\n",
retVal, rightsArray, rightsCount);
LSA_UNICODE_STRING myLsaus = new LSA_UNICODE_STRING();
for (ulong i = 0; i < rightsCount; i++)
{
IntPtr itemAddr = new IntPtr(rightsArray.ToInt64() + (long)(i * (ulong) Marshal.SizeOf(myLsaus)));
myLsaus = (WinNetUtils.LSA_UNICODE_STRING)Marshal.PtrToStructure(itemAddr, myLsaus.GetType());
string thisRight = WinNetUtils.LSAUS2string(myLsaus);
NonBlockingPrint(wmiResults, "Right #{0}: {1}\n", i+1, thisRight);
}
LsaClose(policyHandle);
The helper functions, imports etc:
public const int POLICY_VIEW_LOCAL_INFORMATION = 0x1;
public const int POLICY_LOOKUP_NAMES = 0x00000800;
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, PreserveSig = true)]
public static extern UInt32 LsaNtStatusToWinError(
long Status);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true, PreserveSig = true)]
public static extern bool ConvertStringSidToSid(
string StringSid, out IntPtr pSid);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true, PreserveSig = true)]
public static extern bool LookupAccountName(
string lpSystemName, string lpAccountName,
IntPtr psid, ref int cbsid,
StringBuilder domainName, ref int cbdomainLength,
ref int use );
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, PreserveSig = true)]
public static extern UInt32 LsaOpenPolicy(
ref LSA_UNICODE_STRING SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
Int32 DesiredAccess,
out IntPtr PolicyHandle );
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern long LsaEnumerateAccountRights(
IntPtr PolicyHandle, IntPtr AccountSid,
out /* LSA_UNICODE_STRING[] */ IntPtr UserRights,
out ulong CountOfRights);
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern long LsaClose(
IntPtr PolicyHandle);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LSA_UNICODE_STRING
{
public UInt16 Length;
public UInt16 MaximumLength;
public IntPtr Buffer;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LSA_OBJECT_ATTRIBUTES
{
public IntPtr RootDirectory;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
public LSA_UNICODE_STRING ObjectName;
public UInt32 Attributes;
public UInt32 Length;
}
public static LSA_UNICODE_STRING string2LSAUS(string myString)
{
LSA_UNICODE_STRING retStr = new LSA_UNICODE_STRING();
retStr.Buffer = Marshal.StringToHGlobalUni(myString);
retStr.Length = (UInt16)(myString.Length * UnicodeEncoding.CharSize);
retStr.MaximumLength = (UInt16)((myString.Length + 1) * UnicodeEncoding.CharSize);
return retStr;
}
public static string LSAUS2string(LSA_UNICODE_STRING lsaus)
{
char[] cvt = new char[lsaus.Length / UnicodeEncoding.CharSize];
Marshal.Copy(lsaus.Buffer, cvt, 0, lsaus.Length / UnicodeEncoding.CharSize);
return new string(cvt);
}
This ought to work for you:
private static string LSAUS2String(LSA_UNICODE_STRING lsa) {
char[] cvt = new char[lsa.Length];
Marshal.Copy(lsa.Buffer, cvt, 0, lsa.Length);
return new string(cvt);
}
I have a problem that I am hoping someone can help with. I have a c# application that needs to get the File Owner information from a file that resides on a Linux server. The .Net System.IO GetFileInfo throws an exception and the WMI calls fail. I know there is the PInvoke method GetFileOwner however the example on pinvoke.net is not complete and does not compile. Does anyone have a good complete example or a link to find this information?
This is a .Net c# 3.5 windows application and does have permissions to access the file, however I want to get the owner information before it does the rest of the processing.
Thanks
Below is the code sample I used. It works in my application and in my environment. Should work in others. Sorry this was not posted sooner, was new to StackOverFlow. I hope this posts properly.
public class GetUserInfo{
private const int NAME_SIZE = 0x40;
// Methods
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool ConvertSidToStringSid(IntPtr Sid, ref IntPtr StringSid);
public string ConvertSidToStringSidNT(IntPtr Sid)
{
string ans = string.Empty;
if (IsValidSid(Sid))
{
ans = "S-1-";
SID_IDENTIFIER_AUTHORITY psia = (SID_IDENTIFIER_AUTHORITY) Marshal.PtrToStructure(GetSidIdentifierAuthority(Sid), typeof(SID_IDENTIFIER_AUTHORITY));
int num = Marshal.ReadInt16(GetSidSubAuthorityCount(Sid));
if ((psia.Value[0] != 0) & (psia.Value[1] != 0))
{
ans = ((ans + Conversion.Hex(psia.Value[0]) + Conversion.Hex(psia.Value[1]).PadLeft(2, '0')) + Conversion.Hex(psia.Value[2]).PadLeft(2, '0') + Conversion.Hex(psia.Value[3]).PadLeft(2, '0')) + Conversion.Hex(psia.Value[4]).PadLeft(2, '0') + Conversion.Hex(psia.Value[5]).PadLeft(2, '0');
}
else
{
long top = psia.Value[5];
top += psia.Value[4] * 0x100;
top += (psia.Value[3] * 0x100) * 0x100;
ans = ans + ((top + (((psia.Value[2] * 0x100) * 0x100) * 0x100))).ToString();
}
int VB$t_i4$L0 = num - 1;
for (int i = 0; i <= VB$t_i4$L0; i++)
{
ans = ans + "-" + Marshal.ReadInt32(GetSidSubAuthority(Sid, i)).ToString();
}
}
return ans;
}
public string GetFileOwner(string Path)
{
string MachineName;
IntPtr OwnerSid;
int peUse;
IntPtr SD;
string UserName;
IntPtr VB$t_struct$N0;
SE_OBJECT_TYPE ObjectType = SE_OBJECT_TYPE.SE_FILE_OBJECT;
if (GetNamedSecurityInfo(ref Path, ObjectType, SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION, ref OwnerSid, ref VB$t_struct$N0, ref VB$t_struct$N0, ref VB$t_struct$N0, ref SD) != 0)
{
return "Error";
}
Marshal.FreeHGlobal(SD);
if (Path.StartsWith(#"\\"))
{
MachineName = Path.Split(new char[] { '\\' })[2];
}
else
{
MachineName = "";
}
int name_len = 0x40;
int domain_len = 0x40;
string name = Strings.Space(name_len);
string domain_name = Strings.Space(domain_len);
if (!LookupAccountSid(ref MachineName, OwnerSid, ref name, ref name_len, ref domain_name, ref domain_len, ref peUse))
{
string SidString;
if (Marshal.GetLastWin32Error() != 0x534)
{
return "Error";
}
if (Environment.Version.Major == 4)
{
SidString = this.ConvertSidToStringSidNT(OwnerSid);
}
else
{
IntPtr StringPtr;
if (!ConvertSidToStringSid(OwnerSid, ref StringPtr))
{
return "Error";
}
SidString = Marshal.PtrToStringAuto(StringPtr);
Marshal.FreeHGlobal(StringPtr);
}
domain_len = 0;
name = SidString;
name_len = Strings.Len(name);
}
if (domain_len > 0)
{
UserName = Strings.Left(name, name_len);
}
else
{
UserName = Strings.Left(name, name_len);
}
return UserName;
}
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int GetNamedSecurityInfo([MarshalAs(UnmanagedType.VBByRefStr)] ref string pObjectName, SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, ref IntPtr ppsidOwner, ref IntPtr ppsidGroup, ref IntPtr ppDacl, ref IntPtr ppSacl, ref IntPtr ppSecurityDescriptor);
[DllImport("advapi32.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
private static extern IntPtr GetSidIdentifierAuthority(IntPtr pSid);
[DllImport("advapi32.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
private static extern IntPtr GetSidSubAuthority(IntPtr pSid, int nSubAuthority);
[DllImport("advapi32.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
private static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
[DllImport("advapi32.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
private static extern bool IsValidSid(IntPtr pSid);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool LookupAccountSid([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpSystemName, IntPtr lpSid, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpName, ref int cchName, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpReferenceDomainName, ref int cchReferencedDomainName, ref int peUse);
// Nested Types
private enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32
}
private enum SECURITY_INFORMATION
{
DACL_SECURITY_INFORMATION = 4,
GROUP_SECURITY_INFORMATION = 2,
OWNER_SECURITY_INFORMATION = 1,
PROTECTED_DACL_SECURITY_INFORMATION = 0x20,
PROTECTED_SACL_SECURITY_INFORMATION = 0x10,
SACL_SECURITY_INFORMATION = 8,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x80,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x40
}
[StructLayout(LayoutKind.Sequential)]
private struct SID_IDENTIFIER_AUTHORITY
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
public byte[] Value;
} }