Inside and Out…

An attempt to understand technology better…

Archive for February, 2005

Download CERapi – the managed Windows CE Remote API

Posted by Gaurav Khanna on February 24, 2005

Windows CE Remote API (RAPI) is the mechanism via which desktop applications can talk with the Windows CE device over ActiveSync connection. However, since RAPI is not supported natively for managed code development, I have been working on an implementation for managed code, CERapi.

You can download CERapi from http://www.wintoolzone.com/showpage.aspx?url=dotnet.aspx

It comes with complete documentation, examples and currently supports:

1) Retrieving device and OS information

2) Retrieving Battery (main and backup) charge details

3) Retrieving Memory details of the device

4) Retrieving Special Folders, Storage details and more…

For more details on how it CERapi works, visit here and here.

Your comments and feedback are welcome. Send them from http://www.wintoolzone.com/showpage.aspx?url=feedback.aspx

Posted in .NET Framework, Development, Downloads, Windows API, Windows CE/Windows Mobile | Leave a Comment »

Global Memory and Battery Status Support in CERapi

Posted by Gaurav Khanna on February 15, 2005

I just finished implementing support for getting the global memory details and the battery charge details in CERapi – my managed RAPI implementation. To get these details, simply obtain the CESystemInformation instance and use the GlobalMemoryInformation and BatteryInformation properties to get the details, as shown in the code snippet below (si, in the snippet below, is reference to CESystemInformation object):

// Global Memory Details
CEGlobalMemory gm = si.GlobalMemoryInformation;
Console.WriteLine(“Memory Load: {0}”,gm.MemoryLoad);
Console.WriteLine(“Total Physical Memory: {0}”,gm.TotalPhysicalMemory);

// Battery Details
CEBattery bat = si.BatteryInformation;
Console.WriteLine(“ACLine: {0}”,bat.ACLine.ToString());
Console.WriteLine(“Main Battery Remain: {0}%”,bat.MainBatteryRemainLifePercent);
Console.WriteLine(“Main Battery Status: {0}”,bat.MainBatteryCharge);
Console.WriteLine(“Backup Battery Remain: {0}%”,bat.BackupBatteryRemainLifePercent);
Console.WriteLine(“Backup Battery Status: {0}”,bat.BackupBatteryCharge);

bat.Dispose();
gm.Dispose();

I just finished implementing support for getting the global memory details and the battery charge details in

Do you have any suggestions on what functionality you would like to see in CERAPI? If so, mail me.

Posted in .NET Framework, Development, Windows API, Windows CE/Windows Mobile | Leave a Comment »

Welcome Windows CE Remote API (RAPI) to the managed world

Posted by Gaurav Khanna on February 15, 2005

At the last Mobile and Embedded DevCon held at Bangalore, India, I spoke about the Windows CE Remote API, better known as RAPI.

RAPI is currently not available in the .NET Framework. To alleviate this issue, I have started working on a managed RAPI to get the functionality in the managed world – following is how the code looks like:

CERapi rapi = newCERapi();

if(rapi.Init(5000) != InitReturnCode.Success)
Console.WriteLine(“Unable to initialize RAPI”);
else
{
Console.WriteLine(“Initialized RAPI”);

CESystemInformation si = rapi.SystemInformation;

// Processor Details
Console.WriteLine(“Processor Architecture: {0}”,si.ProcessorType.ToString());
Console.WriteLine(“Processor Level: {0}”,si.ProcessorLevel);

// OS Details
Console.WriteLine(“OS: {0}”,si.OSPlatform.ToString());
Console.WriteLine(“Version: {0}.{1}.{2}”,si.MajorVersion,si.MinorVersion,si.BuildNumber);
Console.WriteLine(“CSD: {0}”,si.CSDVersion);

// Storage Details
Console.WriteLine(“Total Storage: {0} MB”,si.StoreTotalSize/(1024.0*1024.0));
Console.WriteLine(“Free Storage: {0} MB”,si.StoreFreeSize/(1024.0*1024.0));

Console.WriteLine(“Temp Folder: {0}”,si.TempFolderPath);
Console.WriteLine(“Programs Folder: {0}”,si.GetSpecialFolder(CESpecialFolder.Programs));

// shutdown RAPI
if(rapi.Shutdown() == false)
Console.WriteLine(“Unable to shutdown RAPI”);
}

At the last And heres’ the sample output:

Posted in .NET Compact Framework, Development, Downloads, Windows API, Windows CE/Windows Mobile | Leave a Comment »

Managed code impersonation: CLR ThreadPool and more…

Posted by Gaurav Khanna on February 9, 2005

Under managed code, once you impersonate your application’s thread using LogonUser and WindowsIdentity class’s Impersonate method, you can go ahead and perform tasks using the impersonated thread as you require. However, there are couple of catches to this:

1) If you launch a process using Process.Start method, the launched process will not execute under the impersonation context of your application. If you want to make that happen, you will have to launch the process using CreateProcessWithLogonW as I have discussed here.

2) If, from the impersonated thread, you schedule some task to execute using QueueUserWorkItem of ThreadPool class, even the ThreadPool threads do not get the impersonated context, as shown below:

However, once the ThreadPool thread is impersonated, results are as expected:

Below is the snippet to accomplish this:

private staticIntPtr LogUser(stringstrUsername, stringstrDomain, stringstrPassword)
{
IntPtr tokenHandle = newIntPtr(0);
IntPtr dupeTokenHandle = newIntPtr(0);

stringUserName, MachineName,passWord;
const intLOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const intLOGON32_LOGON_INTERACTIVE = 2;
const intSecurityImpersonation = 2;

tokenHandle = IntPtr.Zero;
dupeTokenHandle = IntPtr.Zero;

// Call LogonUser to obtain a handle to an access token.
boolreturnValue = LogonUser(strUsername, strDomain, strPassword,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
reftokenHandle);

if(false== returnValue)
{
intret = Marshal.GetLastWin32Error();
returnIntPtr.Zero;
}

WindowsIdentity mWI1 = WindowsIdentity.GetCurrent();
IntPtr token2 = newIntPtr(tokenHandle.ToInt32());

returntoken2;
}

///
///The main entry point for the application.
///
[STAThread]
static voidMain(string[] args)
{
// show current principal..
IIdentity curI = null;
curI = WindowsIdentity.GetCurrent();
Console.WriteLine(“Your current identity is {0}”,curI.Name);

// Impersonate
IntPtr token = LogUser(“username”,”domain”,”password!”);
WindowsIdentity mWI2 = newWindowsIdentity(token);
WindowsPrincipal winPrin = newWindowsPrincipal(mWI2);
System.Threading.Thread.CurrentPrincipal = winPrin;
WindowsImpersonationContext impersonatedUser = mWI2.Impersonate();

curI = WindowsIdentity.GetCurrent();
Console.WriteLine(“After impersonation in the main thread, you are {0}”,curI.Name);

ThreadPool.QueueUserWorkItem(newWaitCallback(callback));
Console.ReadLine();
}

static voidcallback(Object stateInfo)
{
// No state object was passed to QueueUserWorkItem, so
// stateInfo is null.
Console.WriteLine(“Hello from the thread pool.”);

IIdentity curI = null;
curI = WindowsIdentity.GetCurrent();
Console.WriteLine(“In ThreadPool Thread, you are {0}”,curI.Name);

IntPtr token = LogUser(“username”,”domain”,”password!”);
WindowsIdentity mWI2 = newWindowsIdentity(token);

WindowsPrincipal winPrin = newWindowsPrincipal(mWI2);
System.Threading.Thread.CurrentPrincipal = winPrin;
WindowsImpersonationContext impersonatedUser = mWI2.Impersonate();

curI = WindowsIdentity.GetCurrent();
Console.WriteLine(“After impersonation, in ThreadPool Thread, you are {0}”,curI.Name);
}

Posted in .NET Framework, Development, Tips | Leave a Comment »

Managed CreateProcessWithLogonW

Posted by Gaurav Khanna on February 9, 2005

I returned this past weekend after a family function. It had me very busy and thus, no blogging for sometime for me 🙂

That said, today I was working with one of my friends over email – she was stuck about getting to launch a process in a specific user context, using managed code. Since the .NET Framework doesn’t support such functionality out of the box, we tried different ways to do this:

1) LogonUser followed by WindowsIdentity impersonation using the obtained token – the token wasn’t getting down to the spawned process even after we attempted Impersonate method of WindowsIdentity.

2) WMI also tried – it works but needs to be slightly modified when running on a local machine compared to a remote machine (we cannot specify credentials for local machine in the options).

Finally, we thought about working on CreateProcessWithLogonW. It turned out to be rather simple and clean way of achieving our goal. For those who are interested, the following snippet uses CreateProcessWithLogonW via PInvoke and launches a process under the specified user context:

The following are the PInvoke declarations and data types required:

[Flags]
enumLogonFlags
{
LOGON_WITH_PROFILE = 0x00000001,
LOGON_NETCREDENTIALS_ONLY = 0x00000002
}

[Flags]
enumCreationFlags
{
CREATE_SUSPENDED = 0x00000004,
CREATE_NEW_CONSOLE = 0x00000010,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
CREATE_SEPARATE_WOW_VDM = 0x00000800,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
}

[StructLayout(LayoutKind.Sequential)]
structProcessInfo
{
publicIntPtr hProcess;
publicIntPtr hThread;
public uintdwProcessId;
public uintdwThreadId;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
structStartupInfo
{
public intcb;
public stringreserved1;
public stringdesktop;
public stringtitle;
public uintdwX;
public uintdwY;
public uintdwXSize;
public uintdwYSize;
public uintdwXCountChars;
public uintdwYCountChars;
public uintdwFillAttribute;
public uintdwFlags;
public ushortwShowWindow;
public shortreserved2;
public intreserved3;
publicIntPtr hStdInput;
publicIntPtr hStdOutput;
publicIntPtr hStdError;
}

[DllImport(“advapi32.dll”, CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
static extern boolCreateProcessWithLogonW(
stringprincipal,
stringauthority,
stringpassword,
LogonFlags logonFlags,
stringappName,
stringcmdLine,
CreationFlags creationFlags,
IntPtr environmentBlock,
stringcurrentDirectory,
refStartupInfo startupInfo,
outProcessInfo processInfo);

[DllImport(“kernel32.dll”)]
static extern boolCloseHandle(IntPtr h);

The following is the code snippet that does the PInvoke and spawns the process under a specific user context:

StartupInfo si = newStartupInfo();
si.cb = Marshal.SizeOf(typeof(StartupInfo));
si.title = “This is impersonated command prompt”;

ProcessInfo pi = newProcessInfo();
stringapp = Path.Combine(Environment.SystemDirectory, “cmd.exe”);

if(CreateProcessWithLogonW(“username”, “domain”, “password”,
LogonFlags.LOGON_WITH_PROFILE,
app, null,
0, IntPtr.Zero, null,
refsi, outpi))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
elseConsole.WriteLine(“Error code: {0}”, Marshal.GetLastWin32Error());

Posted in .NET Framework, Development, Tips, Windows API | 1 Comment »