Diskprep Availability

Diskprep.exe is a useful tool for making a bootable USB Disk with an OS but recently it seems to have disappeared from Microsoft’s downloads. I can’t say if it’s another one of those subtle hints on the future of Windows CE, an oversight due to the lack of resources dedicated to Windows CE, or just a simple mistake that will get corrected shortly.  Regardless of the cause, there are people who still find the tool useful, so I’m providing a download mirror of the tool here.

Raw Flash Access from a CF app?

A new customer came to me late last week with an interesting problem.  They have hundreds of Motorola/Symbol MC70 barcode scanners in the field and occasionally the flash memory on the devices gets corrupted.

The current “solution” these guys are using involves removing the flash chips from the board, reprogramming it in a separate device, re-balling the BGA pins, and re-soldering it to the board. That explains why they desperately want an application that can do it.

They know the range where the corruption occurs and wanted an application that would allow a user to read, update and rewrite the corrupted bytes in flash.  They had talked with five separate developers before they found me, and all 5 had agreed that it was impossible, so naturally I took that as a challenge.

First, there are lots of things to know about how flash access works.  Most importantly, it’s not like RAM.  You can’t just map to it, then go about your merry way doing 32-bit reads and writes.  You can read it that way, sure, but writing is a whole new game.  Flash is broken up into “blocks” (which aren’t even always the same size – in the case of the MC70, the first 4 blocks are 64k long, and the rest are 256k long.) and writes must be done following this general procedure:

  1. Read the *entire* block that contains the byte you want to change into RAM
  2. Change to flash to Lock mode (a flash register write)
  3. Unlock the block of flash (another register write)
  4. Change the flash to erase mode (register write)
  5. Erase the *entire* block of flash (which writes all FF’s to it)
  6. Change the flash to write mode (register write)
  7. Update the RAM buffer with your changes
  8. Write in the *entire* block block to flash
  9. Tell the flash to commit (register write)
  10. Wait for the flash to finish (register read)
  11. Put the flash back into read mode (register write)

Oh, and if you get any of this wrong, you’ve made yourself an expensive brick.  The only solution at that point is the de-soldering and reprogramming route, and I don’t have that kind of hardware in my office.

So I started writing the app Monday morning, using C# since I had to create a UI for the editor, and on Wednesday morning this is what I delivered:

FlashEdit

So, in just 2 days I did what was “impossible”. I not only wrote all of the flash access code, I also wrote a hex editor control and an app UI to make use of the flash library.

New home for zlib for Windows CE


Occasionally I’m surprised at how old software never seems to really die off.  Take for example an old port I did of the zlib compression library to Windows CE.  Back in probably ’05 I built the original sources for the Windows CE platform.  In ’07 I created a managed wrapper for the library and some samples on how to use that library.  I put it on the web and then pretty much forgot about it.


Well when we migrated our web site to a new server, some old links died and this just happened to be one of them (if you know of others, please let me know) and today I got an email from someone asking if I still had the code.  Sure, it wasn’t the day things went down, but it still means not only was someone looking for it, the cared enough to email me and ask.


For those looking for it, it’s got a new, hoipefully more permanent home on Codeplex:  http://zlibce.codeplex.com


 

I told you Windows CE wasn’t dead

There has been rampant speculation for some time that Windows CE was dead and that Microsoft was abandoning it.  The announcement that Windows 8 will run on ARM only added fuel to it, despite the fact that Win8 is undoubtedly going to have a large, desktop-style footprint and no capability for real-time operation.  Well, Microsoft finally decided to tell us what many of us suspected for some time.  Windows Embedded Compact (i.e. Windows CE) is still on their product roadmap.  It will have a v Next, and it will be supported in newer versions of Visual Studio (well native development will be anyway).  Read the full press release here.

splash.bmx – Take 2

Earlier today I published a tool for creating CE splash images. Well I already hit a limitation, so I’ve updated the tool.  It now supports all common image formats (PNG, JPG, GIF and BMP) instead of just BMP.  BIOSLoader also limits your image to 64k – anything larger might actually hand the device.  The tool now detects when the result will be larger than 64k and will offer to resize it before compressing as well.


The latest binary and source are up in Codeplex.

Creating a Boot Splash Image (splash.bmx) for Windows CE

If you’re booting an OS on a device that supports the BIOSLoader, an option is to display a “splash screen” image while the OS loads from disk.  The file is, by default, called ‘splash.bmx’, which is expected to be a compressed binary file, *not* an image.  The compressed binary file can be generated from a bitmap using bincompress.exe (which ships with Platform Builder).


While that seems all well and good, there are also some other limitations.  For example the source bitmap (pre compression) must be 256-color, and I believe there is likely a maximum file size as well (I’m sure the loader allocates a static block of RAM to hold the image).  Well my image editor of choice (Paint.NET) doesn’t have a simple mechanism to save as a 256-color bitmap, not all of my PCs have Platform Builder (and thereforebincompress) installed, and I’m a fan of simplifying multistep processes in general.


So I created a very simply Windows app that you use to browse to an image, then click a button and it converts it to 256-color and generates the splash.bmx file for you.  It was just a couple hours of playing around, so it’s not overly robust (it could probably use a command-line interface for automation, and a “preview” of the conversion would be nice) but it’s functional for what I needed to get done this week.  Here’s what it looks like:



 


I’ve published the work (source and binary) up on Codeplex.

AutorunMgr moved to Codeplex

Autorun Manager


Occasionally I need to have an application auto-run on a Windows CE platform (when I plug in a USB disk or CF card).  I wrote a simple utility called Autorun Manager several years ago that gives a lot of flexibility for auto-running apps.  Well someone just asked me about adding the capability to their platform, which tells me it’s not easy enough to find.  In hopes of making it a little more discoverable, I’ve moved it over to Codeplex.

Getting Native File Info in the Compact Framework

Getting file version info in the Compact Framework is pretty simple – provided the file you want info on is a managed assembly.  But what if you want to get the version info for a native file?  Well it’s not quite so nice.  As usual, you have to drop down and P/Invoke several Win32 APIs.  In this case we need to call GetFileVersionInfoSize, GetFileVersionInfo, and VerQueryValue.  We then have to parse the results from these files which, if you’re a beginner or not familar or comfortable with raw memory access (i.e. pointer fun), can be really challenging.


I put together a quick example class that extracts not only the file version, but the entire string table, so you can get things like the Company Name and Copyright info as well.  Here’s the code:

public static class NativeFile
{
public struct NativeFileInfo
{
public Version Version;
public NameValueCollection StringTable;
}
public unsafe static NativeFileInfo GetFileInfo(string path)
{
if (!File.Exists(path))
{
throw new FileNotFoundException();
}

IntPtr handle;

var size = GetFileVersionInfoSize(path, out handle);
var buffer = Marshal.AllocHGlobal(size);
try
{
if (!GetFileVersionInfo(path, handle, size, buffer))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}

IntPtr pVersion;
int versionLength;
VerQueryValue(buffer, “\”, out pVersion, out versionLength);

var versionInfo = (VS_FIXEDFILEINFO)Marshal.PtrToStructure(pVersion, typeof(VS_FIXEDFILEINFO));

var version = new Version((int)versionInfo.dwFileVersionMS >> 16,
(int)versionInfo.dwFileVersionMS & 0xFFFF,
(int)versionInfo.dwFileVersionLS >> 16,
(int)versionInfo.dwFileVersionLS & 0xFFFF);

// move to the string table and parse
var pStringTable = ((byte*)pVersion.ToPointer()) + versionLength;
var strings = ParseStringTable(pStringTable, size – versionLength);

return new NativeFileInfo
{
Version = version,
StringTable = strings
};
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}

private unsafe static NameValueCollection ParseStringTable(byte *pStringTable, int length)
{
NameValueCollection nvc = new NameValueCollection();

byte *p = pStringTable;
short stringFileInfoLength = (short)*p;
byte* end = pStringTable + length;

p += (2 + 2 + 2); // length + valuelength + type
// verify key
var key = Marshal.PtrToStringUni(new IntPtr(p), 14);
if (key != “StringFileInfo”) throw new ArgumentException();

// move past the key to the first string table
p += 30;
short stringTableLength = (short)*p;
p += (2 + 2 + 2); // length + valuelength + type
// get locale info
key = Marshal.PtrToStringUni(new IntPtr(p), 8);

// move to the first string
p += 18;

while (p < end)
{
short stringLength = (short)*p;
p += 2;
short valueChars = (short)*p;
p += 2;
short type = (short)*p;
p += 2;

if (stringLength == 0) break;

if ((valueChars == 0) || (type != 1))
{
p += stringLength;
continue;
}

var keyLength = stringLength – (valueChars * 2) – 6;
key = Marshal.PtrToStringUni(new IntPtr(p), keyLength / 2).TrimEnd(”);
p += keyLength;
var value = Marshal.PtrToStringUni(new IntPtr(p), valueChars).TrimEnd(”);
p += valueChars * 2;

if ((int)p % 4 != 0) p += 2;

nvc.Add(key, value);
}
return nvc;
}

private const string COREDLL = “coredll.dll”;

[DllImport(COREDLL, SetLastError = true)]
private static extern int GetFileVersionInfoSize(string lptstrFilename, out IntPtr lpdwHandle);

[DllImport(COREDLL, SetLastError = true)]
private static extern bool GetFileVersionInfo(string lptstrFilename, IntPtr dwHandle, int dwLen, IntPtr lpData);

[DllImport(COREDLL, SetLastError = true)]
private static extern bool VerQueryValue(IntPtr pBlock, string lpSubBlock, out IntPtr lplpBuffer, out int puLen);

[StructLayout(LayoutKind.Sequential)]
private struct VS_FIXEDFILEINFO
{
public DWORD dwSignature;
public DWORD dwStrucVersion;
public DWORD dwFileVersionMS;
public DWORD dwFileVersionLS;
public DWORD dwProductVersionMS;
public DWORD dwProductVersionLS;
public DWORD dwFileFlagsMask;
public DWORD dwFileFlags;
public FileOS dwFileOS;
public FileType dwFileType;
public DWORD dwFileSubtype;
public DWORD dwFileDateMS;
public DWORD dwFileDateLS;
};

public enum FileOS : uint
{
Unknown = 0x00000000,
DOS = 0x00010000,
OS2_16 = 0x00020000,
OS2_32 = 0x00030000,
NT = 0x00040000,
WindowsCE = 0x00050000,
}

public enum FileType : uint
{
Unknown = 0x00,
Application = 0x01,
DLL = 0x02,
Driver = 0x03,
Font = 0x04,
VXD = 0x05,
StaticLib = 0x07
}
}


One item that might not be intuitive is that I’m using an alias for the DWORD type, so up at the top of the code page add this:

using DWORD = System.UInt32;

I then created a quick sample app that pulled the info from the corecon file on my device:

class Program
{
static void Main(string[] args)
{
string target = “\FlashFX Disk\ARMv4i\conmanclient2.exe”;
var version = NativeFile.GetFileInfo(target);

Console.WriteLine(string.Format(“File: {0}”, Path.GetFileName(target)));
Console.WriteLine(string.Format(“Version: {0}”, version.Version.ToString(4)));
foreach (var key in version.StringTable.AllKeys)
{
Console.WriteLine(string.Format(“{0}: {1}”, key, version.StringTable[key]));
}

Console.ReadLine();
}

}


And this is the output: