We have an existing piece of software that uses shellwidnows to access an internet explorer page and modify data on a form. However, we are porting it to Citrix seamless application and shell windows does not work there.
I have looked around on the internet and found a way to create a HtmlDocument from an existing IE window.
However, I am having a problem when trying to run "SendMessageTimeout". It runs without error but the result returned is 0 when it should be a non-zero amount. And thus, I can not go to the next phase of creating the HTML Document.
The line causing the problem is:
IntPtr result = SendMessageTimeout(htmlWindow, lMsg, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lRes);
Here is the full code. Iam using VS 2008 due to corporate conventions. I am new to C# so some conventions and styling may be incorrect. Thanks for any help.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using mshtml;
using System.Diagnostics;
public delegate bool IECallBack(int hwnd, int lParam);
public delegate bool IEChildCallBack(int hWndParent, int lpEnumFunc, int lParam);
namespace GetIEWindows
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("Oleacc.Dll")]
public static extern int ObjectFromLresult(UIntPtr lResult, UUID _riid, int wParam, mshtml.HTMLDocument _ppvObject);
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
private static extern int FindWindowEx(int parentWindow, int childWindow, string _ClassName, string _WindowName);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.Dll")]
public static extern int EnumWindows(IECallBack x, long y);
[DllImport("user32.Dll")]
public static extern int EnumChildWindows(int parent, IECallBack x, long y);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
[DllImport("User32.Dll")]
public static extern void GetWindowText(IntPtr h, StringBuilder s, long nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("User32.Dll")]
public static extern void GetClassName(int h, StringBuilder s, int
nMaxCount);
[DllImport("User32.Dll")]
public static extern uint RegisterWindowMessage(string lpString);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags flags, uint timeout, out UIntPtr result);
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
[Flags]
public enum SendMessageTimeoutFlags : uint
{
SMTO_NORMAL = 0x0,
SMTO_BLOCK = 0x1,
SMTO_ABORTIFHUNG = 0x2,
SMTO_NOTIMEOUTIFNOTHUNG = 0x8
}
public const int SMTO_ABORTIFHUNG = 0x2;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct UUID
{
public long Data1;
public int Data2;
public int Data3;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data4;
}
public static mshtml.HTMLDocument GetHTMLContent(IntPtr htmlWindow)
{
HTMLDocument htmlDocument = new mshtml.HTMLDocument();
HTMLDocument thedoc = new mshtml.HTMLDocument();
IHTMLDocument htmlDoc = null;
Guid guid = new Guid("626FC520-A41E-11cf-A731-00A0C9082637");
int foundWindow = htmlWindow.ToInt32();
string htmlContent = "";
UUID IID_IHTMLDocument = new UUID();
UIntPtr lRes;
uint lMsg = 0;
int hr = 0;
if (foundWindow != 0)
{
// Register the message
lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
//lMsg = RegisterWindowMessage("WM_GETTEXT");
// Get the object
IntPtr result = SendMessageTimeout(htmlWindow, lMsg, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lRes);
if (result.ToInt32() != 0)
{
if (lRes != UIntPtr.Zero)
{
// Initialize the interface ID
IID_IHTMLDocument.Data1 = 0x626FC520;
IID_IHTMLDocument.Data2 = 0xA41E;
IID_IHTMLDocument.Data3 = 0x11CF;
IID_IHTMLDocument.Data4 = new byte[8];
IID_IHTMLDocument.Data4[0] = 0xA7;
IID_IHTMLDocument.Data4[1] = 0x31;
IID_IHTMLDocument.Data4[2] = 0x0;
IID_IHTMLDocument.Data4[3] = 0xA0;
IID_IHTMLDocument.Data4[4] = 0xC9;
IID_IHTMLDocument.Data4[5] = 0x8;
IID_IHTMLDocument.Data4[6] = 0x26;
IID_IHTMLDocument.Data4[7] = 0x37;
// Get the object from lRes
try
{
hr = ObjectFromLresult(lRes, IID_IHTMLDocument, 0, thedoc);
//htmlDoc = (mshtml.IHTMLDocument)ObjectFromLresult(, IID_IHTMLDocument, 0, htmlDoc);
}
catch (Exception e)
{
MessageBox.Show("Did not get IHTMLDocument: " + e.Message);
}
}
}
}
return thedoc;
}
public static void getHWnd()
{
string currentTitle;
string windowName = null;
string windowClass = "#32770";
HTMLDocument pageToBeEdited;
IntPtr hWnd = FindWindow(windowClass, windowName);
while (hWnd.ToInt32() != 0) {
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
currentTitle = sb.ToString();
if (currentTitle.Contains("Internet Explorer")) {
pageToBeEdited = GetHTMLContent(hWnd);
return;
}
hWnd = GetWindow(hWnd, GetWindow_Cmd.GW_HWNDNEXT);
}
return;
}
private void btnRun_Click(object sender, EventArgs e)
{
getHWnd();
}
}
}
For anybody who is interested, the problem was resolved by using a different way of getHWnd:
public static IntPtr getHWnd(string title)
{
IntPtr hWnd = FindWindow(null, title);
BringWindowToTop(hWnd);
SetActiveWindow(hWnd);
SetForegroundWindow(hWnd);
Thread.Sleep(500);
foreach (Process process in Process.GetProcessesByName("IExplore"))
{
if (process.MainWindowTitle.ToLower().Contains(title.ToLower()))
{
hWnd = process.MainWindowHandle;
break;
}
}
EnumProc proc = new EnumProc(EnumWindows);
EnumChildWindows(hWnd, proc, ref hWnd);
return hWnd;
}
public HTMLDocument GetHTMLDocument(IntPtr hWnd)
{
HTMLDocument document = null;
int iMsg = 0;
int iRes = 0;
iMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
if (iMsg != 0)
{
SendMessageTimeout(hWnd, iMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, out iRes);
if (iRes != 0)
{
int hr = ObjectFromLresult(iRes, ref IID_IHTMLDocument, 0, ref document);
}
}
return document;
}
private static int EnumWindows(IntPtr hWnd, ref IntPtr lParam)
{
int iRet = 1;
StringBuilder classname = new StringBuilder(128);
GetClassName(hWnd, classname, classname.Capacity);
if ((bool)(string.Compare(classname.ToString(), "Internet Explorer_Server") == 0))
{
lParam = hWnd;
iRet = 0;
}
return iRet;
}
Here is how you can get HTMLDocument using Hwnd :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using mshtml;
namespace HookBrowser
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
#region API CALLS
[DllImport("user32.dll", EntryPoint = "GetClassNameA")]
public static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);
/*delegate to handle EnumChildWindows*/
public delegate int EnumProc(IntPtr hWnd, ref IntPtr lParam);
[DllImport("user32.dll")]
public static extern int EnumChildWindows(IntPtr hWndParent, EnumProc lpEnumFunc, ref IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "RegisterWindowMessageA")]
public static extern int RegisterWindowMessage(string lpString);
[DllImport("user32.dll", EntryPoint = "SendMessageTimeoutA")]
public static extern int SendMessageTimeout(IntPtr hwnd, int msg, int wParam, int lParam, int fuFlags, int uTimeout, out int lpdwResult);
[DllImport("OLEACC.dll")]
public static extern int ObjectFromLresult(int lResult, ref Guid riid, int wParam, ref IHTMLDocument2 ppvObject);
public const int SMTO_ABORTIFHUNG = 0x2;
public Guid IID_IHTMLDocument = new Guid("626FC520-A41E-11CF-A731-00A0C9082637");
#endregion
public IHTMLDocument2 document;
private void button1_Click(object sender, EventArgs e)
{
document = documentFromDOM();
/// check that we have hold of the IHTMLDocument2...
if (!(bool)(document == null))
{
this.Text = document.url;
}
}
private IHTMLDocument2 documentFromDOM()
{
Process[] processes = Process.GetProcessesByName("iexplore");
if (processes.Length > 0)
{
IntPtr hWnd = processes[0].MainWindowHandle;
int lngMsg = 0;
int lRes;
EnumProc proc = new EnumProc(EnumWindows);
EnumChildWindows(hWnd, proc, ref hWnd);
if (!hWnd.Equals(IntPtr.Zero))
{
lngMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
if (lngMsg != 0)
{
SendMessageTimeout(hWnd, lngMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, out lRes);
if (!(bool)(lRes == 0))
{
int hr = ObjectFromLresult(lRes, ref IID_IHTMLDocument, 0, ref document);
if ((bool)(document == null))
{
MessageBox.Show("NoLDocument Found!", "Warning");
}
}
}
}
}
return document;
}
private int EnumWindows(IntPtr hWnd, ref IntPtr lParam)
{
int retVal = 1;
StringBuilder classname = new StringBuilder(128);
GetClassName(hWnd, classname, classname.Capacity);
/// check if the instance we have found is Internet Explorer_Server
if ((bool)(string.Compare(classname.ToString(), "Internet Explorer_Server") == 0))
{
lParam = hWnd;
retVal = 0;
}
return retVal;
}
}
}
Please refer to this link for more info :
http://www.xtremevbtalk.com/code-library/295336-internet-explorer-dom-using-objectfromlresult.html
Related
I'm trying to make a listener for reading data which comes from my barcode scanner.I made a keylogger but it catches keys that come from my laptop keyboard and barcode-scanner . I want to catch data which come only my barcode scanner. I don't know how can i do that so any suggestion can help me.
Here is my SetHook fonction maybe someone knows how can i focus to hid with editing that fonction.
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
Below is the code i have written for the same problem. The code works like,
In HookHandleProc, it is waiting the following keys to be downed in less than 50 ms
private const Keys HK_PRE = Keys.F5; //0x0007;
private const Keys HK_PRE_VALID = Keys.OemOpenBrackets;
If it's done, then we set _hookFlag = true, so again in HookHandleProc, we swallow keys into _buffer till
private const Keys HK_SUFF = Keys.Oemtilde; //0x000A;
So if you program your barcode reader to include these prefix and suffix values, you can know where the data comes from
Here is the code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Keys = System.Windows.Forms.Keys;
namespace BarcodeScanner
{
public class CouldntHookException : Exception
{
public override string Message
{
get
{
return "barcode_input_handler couldnt add itself to the hook chain.";
}
}
public override string ToString()
{
return Message;
}
}
public class BarcodeHandler : IDisposable
{
private delegate long delLowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void delInput(string scanCode);
public event delInput InputEvent;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern long SetWindowsHookEx(int idHook,
delLowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(long hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern long CallNextHookEx(long hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;
private const Keys HK_PRE = Keys.F5; //0x0007;
private const Keys HK_PRE_VALID = Keys.OemOpenBrackets;
private const Keys HK_SUFF = Keys.Oemtilde; //0x000A;
private long _hHook = 0;
private StringBuilder _buffer;
private bool _hookFlag;
private bool _hookValid;
delLowLevelKeyboardProc _procHook;
taglParam _lastKey;
struct taglParam
{
public int _vkCode, _scanCode, _flags, _time;
public taglParam(int vkCode, int scanCode, int flags, int time)
{ _vkCode = vkCode; _scanCode = scanCode; _flags = flags; _time = time; }
};
public BarcodeHandler()
{
_buffer = new StringBuilder(128);
_hookFlag = false;
_hookValid = false;
_procHook = new delLowLevelKeyboardProc(HookHandleProc);
_hHook = SetHook();
if (_hHook == 0)
throw new CouldntHookException();
}
~BarcodeHandler()
{
Dispose();
}
private long SetHook()
{
using (Process cp = Process.GetCurrentProcess())
using (ProcessModule cm = cp.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, _procHook,
GetModuleHandle(cm.ModuleName), 0);
}
}
private long HookHandleProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0 || wParam != (IntPtr)WM_KEYDOWN)
return CallNextHookEx(_hHook, nCode, wParam, lParam);
taglParam lp = (taglParam)Marshal.PtrToStructure(lParam, typeof(taglParam));
if (_hookFlag)
{
if ((Keys)lp._vkCode == HK_SUFF)
{
_hookFlag = false;
_hookValid = false;
//trigger event here
//use begininvoke instead of invoke ;)
InputEvent.Invoke(_buffer.ToString());
return -1;
}
_buffer.Append((char)lp._vkCode);
return -1;
}
else if ((Keys)lp._vkCode == HK_PRE)
{
_hookValid = true;
_lastKey = lp;
}
else if (_hookValid && (Keys)lp._vkCode == HK_PRE_VALID)
{
if (lp._time - _lastKey._time < 50)
{
_buffer.Clear();
_hookFlag = true;
return -1;
}
else
_hookValid = false;
}
return CallNextHookEx(_hHook, nCode, wParam, lParam);
}
private bool DeleteHook()
{
return UnhookWindowsHookEx(_hHook);
}
public void Dispose()
{
DeleteHook();
GC.SuppressFinalize(this);
}
}
}
The first Call to Launch Method Write Into file echo1, but I can't capture the standard output of the second line of the test, what I am doing wrong?
[TestMethod]
public void Launch()
{
var resp = ProcessAsUserTest.ProcessAsUser.Launch("cmd.exe /c \"echo 1\" >> c:\\temp\\echo1");
var resp1 = ProcessAsUserTest.ProcessAsUser.Launch("cmd.exe /c \"echo 1\"");
Assert.AreEqual("1", resp1);
}
I was follow this thread but It has not answer: Capture standard output from CreateProcessAsUser in C#
I get the implementation from https://social.msdn.microsoft.com/Forums/vstudio/en-US/0c0ca087-5e7b-4046-93cb-c7b3e48d0dfb/how-run-client-application-as-a-windows-service-in-c?forum=csharpgeneral
and I've edited the code to get standard output same as the first link without answer.
Here the implementation:
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ProcessAsUserTest
{
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SECURITY_ATTRIBUTES
{
public uint nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
internal enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
internal enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
[Flags]
enum HANDLE_FLAGS
{
INHERIT = 1,
}
public class ProcessAsUser
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx", SetLastError = true)]
private static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 ImpersonationLevel,
Int32 dwTokenType,
ref IntPtr phNewToken);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
IntPtr ProcessHandle,
UInt32 DesiredAccess,
ref IntPtr TokenHandle);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(
ref IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool DestroyEnvironmentBlock(
IntPtr lpEnvironment);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(
IntPtr hObject);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateNamedPipe(string name, int openMode, int pipeMode, int maxInstances, int outBufSize, int inBufSize, int timeout, IntPtr lpPipeAttributes);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, HandleRef hTemplateFile);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern IntPtr GetStdHandle(int whichHandle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetExitCodeProcess(IntPtr process, ref UInt32 exitCode);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetHandleInformation(IntPtr hObject, HANDLE_FLAGS dwMask, HANDLE_FLAGS dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetConsoleOutputCP();
[DllImport("kernel32.dll")]
static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
private const short SW_SHOW = 5;
private const short SW_HIDE = 0;
private const uint TOKEN_QUERY = 0x0008;
private const uint TOKEN_DUPLICATE = 0x0002;
private const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
private const int GENERIC_ALL_ACCESS = 0x10000000;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int STARTF_FORCEONFEEDBACK = 0x00000040;
private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
private const int STD_INPUT_HANDLE = -10;
private static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
private static readonly HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
private static string LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock)
{
bool result = false;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
saThread.nLength = (uint)Marshal.SizeOf(saThread);
IntPtr stdoutReadHandle = IntPtr.Zero;
SafeFileHandle safeHandle = null;
IntPtr stdoutWriteHandle = IntPtr.Zero;
IntPtr stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
try
{
CreatePipe(out stdoutReadHandle, out stdoutWriteHandle, false);
SetHandleInformation(stdoutReadHandle, HANDLE_FLAGS.INHERIT, 0);
STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(si);
//if this member is NULL, the new process inherits the desktop
//and window station of its parent process. If this member is
//an empty string, the process does not inherit the desktop and
//window station of its parent process; instead, the system
//determines if a new desktop and window station need to be created.
//If the impersonated user already has a desktop, the system uses the
//existing desktop.
si.lpDesktop = #"WinSta0\Default"; //Modify as needed
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
si.wShowWindow = SW_SHOW;
si.hStdInput = stdinHandle;
si.hStdOutput = stdoutWriteHandle;
si.hStdOutput = stdoutWriteHandle;
//Set other si properties as required.
result = CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi);
if (result == false)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
Debug.WriteLine(message);
}
var ret = WaitForSingleObject(pi.hProcess, 100000);
//Console.Write("WaitForSingleObject returned " + ret);
//ret==258 (0x102) - not signalled, ret==0 ok!
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(stdoutWriteHandle);
CloseHandle(stdinHandle);
safeHandle = new SafeFileHandle(stdoutReadHandle, true);
string outputData;
var encoding = Encoding.GetEncoding(GetConsoleOutputCP());
using (var fs = new FileStream(safeHandle, FileAccess.Read, 0x1000, true))
using (var reader = new StreamReader(fs, encoding))
{
outputData = reader.ReadToEnd();
}
return outputData;
}
finally
{
if (!safeHandle.IsClosed)
{
safeHandle.Close();
}
}
}
private static IntPtr GetPrimaryToken(int processId)
{
IntPtr token = IntPtr.Zero;
IntPtr primaryToken = IntPtr.Zero;
bool retVal = false;
Process p = null;
try
{
p = Process.GetProcessById(processId);
}
catch (ArgumentException ex)
{
string details = String.Format("ProcessID {0} Not Available, More: {1}", processId, ex.Message);
throw new ArgumentException(details);
}
//Gets impersonation token
retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, ref token);
if (retVal == true)
{
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.nLength = (uint)Marshal.SizeOf(sa);
//Convert the impersonation token into Primary token
retVal = DuplicateTokenEx(
token,
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref primaryToken);
//Close the Token that was previously opened.
CloseHandle(token);
if (retVal == false)
{
string message = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error());
throw new Exception(message);
}
}
else
{
string message = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
//We'll Close this token after it is used.
return primaryToken;
}
private static IntPtr GetEnvironmentBlock(IntPtr token)
{
IntPtr envBlock = IntPtr.Zero;
bool retVal = CreateEnvironmentBlock(ref envBlock, token, false);
if (retVal == false)
{
//Environment Block, things like common paths to My Documents etc.
//Will not be created if "false"
//It should not adversley affect CreateProcessAsUser.
string message = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
return envBlock;
}
public static string Launch(string appCmdLine /*,int processId*/)
{
string ret = "";
//Either specify the processID explicitly
//Or try to get it from a process owned by the user.
//In this case assuming there is only one explorer.exe
Process[] ps = Process.GetProcessesByName("explorer");
int processId = -1;//=processId
if (ps.Length > 0)
{
processId = ps[0].Id;
}
if (processId > 1)
{
IntPtr token = GetPrimaryToken(processId);
if (token != IntPtr.Zero)
{
IntPtr envBlock = GetEnvironmentBlock(token);
ret = LaunchProcessAsUser(appCmdLine, token, envBlock);
if (envBlock != IntPtr.Zero)
DestroyEnvironmentBlock(envBlock);
CloseHandle(token);
}
}
return ret;
}
private static void CreatePipe(out IntPtr parentHandle, out IntPtr childHandle, bool parentInputs)
{
string pipename = #"\\.\pipe\" + Guid.NewGuid().ToString();
parentHandle = CreateNamedPipe(pipename, 0x40000003, 0, 0xff, 0x1000, 0x1000, 0, IntPtr.Zero);
if (parentHandle == INVALID_HANDLE_VALUE)
{
throw new Exception("Invalid Handle Exception.");
}
int childAcc = 0x40000000;
if (parentInputs)
{
childAcc = -2147483648;
}
childHandle = CreateFile(pipename, childAcc, 3, IntPtr.Zero, 3, 0x40000080, NullHandleRef);
if (childHandle == INVALID_HANDLE_VALUE)
{
throw new Exception("Invalid Handle Exception.");
}
}
}
}
NOTE: It is a sample code only, In real code I want to take a screenshot of the desktop from Window Service using another process, In the context of explorer.exe, because windows service cannot access to desktop directly and need another context to do it.
Same thread:https://social.msdn.microsoft.com/Forums/vstudio/en-US/19ff0bb0-924f-4f9c-9b71-ff4ee4ccaf50/standard-output-from-createprocessasuser-always-empty-in-c?forum=csharpgeneral#19ff0bb0-924f-4f9c-9b71-ff4ee4ccaf50
If you need more information please tell me, thanks!
when I try to inject a DLL with C# into a java process (Minecraft specifically) I get an error "ERROR 6", I've been googling this error but couldnt find a solution.
The program is run in administrator mode, and it isnt trying to load from an admin path.
My code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace Launcher
{
internal class InjectionUtils
{
public struct CTX_PROCS
{
public Process[] procs;
}
private const int PROCESS_CREATE_THREAD = 2;
private const int PROCESS_QUERY_INFORMATION = 1024;
private const int PROCESS_VM_OPERATION = 8;
private const int PROCESS_VM_WRITE = 32;
private const int PROCESS_VM_READ = 16;
private const uint MEM_COMMIT = 4096u;
private const uint MEM_RESERVE = 8192u;
private const uint PAGE_READWRITE = 4u;
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int MessageBox(IntPtr hWnd, string text, string caption, uint option);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
private void MBox(string text)
{
InjectionUtils.MessageBox(IntPtr.Zero, text, "", 0u);
}
public void DoInjection(string dllPath)
{
InjectionUtils.CTX_PROCS cTX_PROCS = this.FindProcessByNameAndTitle("javaw", "Minecraft 1.7");
this.InjectDynamicLib(dllPath, cTX_PROCS.procs[0].Id);
}
public InjectionUtils.CTX_PROCS FindProcessByNameAndTitle(string processName, string title)
{
InjectionUtils.CTX_PROCS result = default(InjectionUtils.CTX_PROCS);
List<Process> list = new List<Process>();
Process[] processes = Process.GetProcesses();
for (int i = 0; i < processes.Length; i++)
{
Process process = processes[i];
if (process.ProcessName.Equals(processName) && process.MainWindowTitle.Contains(title))
{
list.Add(process);
}
}
result.procs = list.ToArray();
return result;
}
public void eject()
{
}
private bool InjectDynamicLib(string dllPath, int pId)
{
bool result = false;
IntPtr intPtr = InjectionUtils.OpenProcess(1082, false, pId);
uint num = (uint)((dllPath.Length + 1) * Marshal.SizeOf(typeof(char)));
if (intPtr != IntPtr.Zero)
{
IntPtr procAddress = InjectionUtils.GetProcAddress(InjectionUtils.GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr intPtr2 = InjectionUtils.VirtualAllocEx(intPtr, IntPtr.Zero, num, 12288u, 4u);
UIntPtr uIntPtr;
// Write path of dll to remote process
if (InjectionUtils.WriteProcessMemory(intPtr, intPtr2, Encoding.Default.GetBytes(dllPath), num, out uIntPtr))
{
InjectionUtils.CloseHandle(InjectionUtils.CreateRemoteThread(intPtr, IntPtr.Zero, 0u, procAddress, intPtr2, 0u, IntPtr.Zero));
result = true;
}
InjectionUtils.CloseHandle(intPtr);
}
if (InjectionUtils.GetLastError() != 0u)
{
this.MBox("ERROR " + InjectionUtils.GetLastError());
}
return result;
}
If anyone could help I would appreciate it dearly :)
Thanks in advance :D
From MSDN Error Code List:
ERROR_INVALID_HANDLE
0x6
Before you call GetLastError() you call CloseHandle() twice, once on the thread handle and on the process handle.
To find the problem just check the returns from OpenProcess() and CreateRemoteThread() and compare against the info you find in the functions documentation on MSDN.
For a simple no frills C# injector, this is the code I like to use which includes some error checking and uses the managed Process::Dispose() method instead of calling the native CloseHandle() at least on the process handle:
public static bool InjectDLL(string dllpath, string procname)
{
Process[] procs = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(procname));
if (procs.Length == 0)
{
return false;
}
Process proc = procs[0];
if (proc.Handle != IntPtr.Zero)
{
IntPtr loc = VirtualAllocEx(proc.Handle, IntPtr.Zero, MAX_PATH, AllocationType.Commit | AllocationType.Reserve,
MemoryProtection.ReadWrite);
if (loc.Equals(0))
{
return false;
}
IntPtr bytesRead = IntPtr.Zero;
bool result = WriteProcessMemory(proc.Handle, loc, dllpath.ToCharArray(), dllpath.Length, out bytesRead);
if (!result || bytesRead.Equals(0))
{
return false;
}
IntPtr loadlibAddy = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(proc.Handle, IntPtr.Zero, 0, loadlibAddy, loc, 0, out _);
if (!hThread.Equals(0))
{
CloseHandle(hThread);
}
else return false;
}
else return false;
//this will CloseHandle automatically using the managed method
proc.Dispose();
return true;
}
Make sure to run as admin and pinvoke any missing definitions.
Using this,
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern IntPtr GetForegroundWindow();
I retrieve handle for a process then,
IntPtr hwnd = GetForegroundWindow();
int pid = APIFuncs.GetWindowProcessID(hwnd);
Process p = Process.GetProcessById(pid);
string appName = p.ProcessName;
So whenever I find appName = "WINWORD", I would like to retrieve Word application object using hwnd
NOTE: I don't want to create new instance of word, just get running one.
Given a window handle, you get an automatable Word application instance using the AccessibleObjectFromWindow function from oleacc.dll.
Here is a sample program showing how to use it (add a reference to Microsoft.Office.Interop.Word.dll):
using Microsoft.Office.Interop.Word;
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
namespace WordLateBindingSample
{
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
public interface IDispatch
{
}
class Program
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("Oleacc.dll")]
static extern int AccessibleObjectFromWindow(int hwnd, uint dwObjectID, byte[] riid, out IDispatch ptr);
public delegate bool EnumChildCallback(int hwnd, ref int lParam);
[DllImport("User32.dll")]
public static extern bool EnumChildWindows(int hWndParent, EnumChildCallback lpEnumFunc, ref int lParam);
[DllImport("User32.dll")]
public static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount);
public static bool EnumChildProc(int hwndChild, ref int lParam)
{
StringBuilder buf = new StringBuilder(128);
GetClassName(hwndChild, buf, 128);
if (buf.ToString() == "_WwG")
{
lParam = hwndChild;
return false;
}
return true;
}
static void Main(string[] args)
{
// Use the window class name ("OpusApp") to retrieve a handle to Word's main window.
// Alternatively you can get the window handle via the process id:
// int hwnd = (int)Process.GetProcessById(wordPid).MainWindowHandle;
//
int hwnd = (int)FindWindow("OpusApp", null);
if (hwnd != 0)
{
int hwndChild = 0;
// Search the accessible child window (it has class name "_WwG")
// as described in http://msdn.microsoft.com/en-us/library/dd317978%28VS.85%29.aspx
//
EnumChildCallback cb = new EnumChildCallback(EnumChildProc);
EnumChildWindows(hwnd, cb, ref hwndChild);
if (hwndChild != 0)
{
// We call AccessibleObjectFromWindow, passing the constant OBJID_NATIVEOM (defined in winuser.h)
// and IID_IDispatch - we want an IDispatch pointer into the native object model.
//
const uint OBJID_NATIVEOM = 0xFFFFFFF0;
Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
IDispatch ptr;
int hr = AccessibleObjectFromWindow(hwndChild, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), out ptr);
if (hr >= 0)
{
var wordApp = (Application)ptr.GetType().InvokeMember("Application", BindingFlags.GetProperty, null, ptr, null);
var version = wordApp.Version;
Console.WriteLine(string.Format("Word version is: {0}", version));
}
}
}
}
}
}
I'd like to list out all CSP and CNG providers installed on a system, but I can't find a good method for doing so in C#. For CSP, I can enumerate a certain registry key (inelegant, but functional), but I've been unable to find any way to get a list of CNG providers.
Is there anything remotely like System.Security.Cryptography.Get[CSP/CNG]Providers() or similarly logical/straightforward in .NET that could be used? Thanks!
To my knowledge, there isn't anything like that in .NET Framework.
For CSP providers, enumerate the subkeys of:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider
For CNG providers, enumerate the subkeys of:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Cryptography\Providers
Use this to enumerate CSP providers and containers:
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
namespace CspSample
{
struct Provider
{
public string Name { get; set; }
public int Type { get; set; }
}
class CspUtils
{
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool CryptEnumProviderTypes(
uint dwIndex,
uint pdwReserved,
uint dwFlags,
[In] ref uint pdwProvType,
StringBuilder pszTypeName,
[In] ref uint pcbTypeName);
[DllImport("Advapi32.dll")]
private static extern bool CryptEnumProviders(
int dwIndex,
IntPtr pdwReserved,
int dwFlags,
ref int pdwProvType,
StringBuilder pszProvName,
ref int pcbProvName);
public static List<Provider> ListAllProviders()
{
List<Provider> installedCSPs = new List<Provider>();
int cbName;
int dwType;
int dwIndex;
StringBuilder pszName;
dwIndex = 0;
dwType = 1;
cbName = 0;
while (CryptEnumProviders(dwIndex, IntPtr.Zero, 0, ref dwType, null, ref cbName))
{
pszName = new StringBuilder(cbName);
if (CryptEnumProviders(dwIndex++, IntPtr.Zero, 0, ref dwType, pszName, ref cbName))
{
installedCSPs.Add(new Provider { Name = pszName.ToString(), Type = dwType });
}
}
return installedCSPs;
}
const int PP_ENUMCONTAINERS = 2;
const int PROV_RSA_FULL = 1;
const int ERROR_MORE_DATA = 234;
const int ERROR_NO_MORE_ITEMS = 259;
const int CRYPT_FIRST = 1;
const int CRYPT_NEXT = 2;
//TODO: Find how to disable this flag (not machine keystore)
const int CRYPT_MACHINE_KEYSET = 0x20;
const int CRYPT_VERIFYCONTEXT = unchecked((int)0xF0000000);
public static IList<string> EnumerateKeyContainers(string providerName, int providerType)
{
ProvHandle prov;
if (!CryptAcquireContext(out prov, null, providerName, providerType, CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT))
throw new Win32Exception(Marshal.GetLastWin32Error());
List<string> list = new List<string>();
IntPtr data = IntPtr.Zero;
try
{
int flag = CRYPT_FIRST;
int len = 0;
if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, IntPtr.Zero, ref len, flag))
{
if (Marshal.GetLastWin32Error() != ERROR_MORE_DATA)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
data = Marshal.AllocHGlobal(len);
do
{
if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, data, ref len, flag))
{
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS)
break;
//throw new Win32Exception(Marshal.GetLastWin32Error());
}
list.Add(Marshal.PtrToStringAnsi(data));
flag = CRYPT_NEXT;
}
while (true);
}
finally
{
if (data != IntPtr.Zero)
{
Marshal.FreeHGlobal(data);
}
prov.Dispose();
}
return list;
}
private sealed class ProvHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public ProvHandle()
: base(true)
{
}
protected override bool ReleaseHandle()
{
return CryptReleaseContext(handle, 0);
}
[DllImport("advapi32.dll")]
private static extern bool CryptReleaseContext(IntPtr hProv, int dwFlags);
}
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CryptAcquireContext(out ProvHandle phProv, string pszContainer, string pszProvider, int dwProvType, int dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CryptGetProvParam(ProvHandle hProv, int dwParam, IntPtr pbData, ref int pdwDataLen, int dwFlags);
}
}