<feed xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <title>Bruce Eitman</title>
    <link rel="self" type="application/xml" href="http://geekswithblogs.net/BruceEitman/Atom.aspx" />
    <subtitle type="html">Windows CE Musings</subtitle>
    <id>http://geekswithblogs.net/BruceEitman/Default.aspx</id>
    <author>
        <name>Bruce Eitman</name>
        <uri>http://geekswithblogs.net/BruceEitman/Default.aspx</uri>
    </author>
    <generator uri="http://subtextproject.com" version="Subtext Version 0.0.0.0">Subtext</generator>
    <updated>2011-06-28T09:44:12Z</updated>
    <entry>
        <title>Windows CE: C# Application to Format TFAT</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/30/windows-ce-c-application-to-format-tfat.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/30/windows-ce-c-application-to-format-tfat.aspx</id>
        <published>2010-08-30T22:34:37-04:00:00</published>
        <updated>2010-08-31T09:41:58Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;Windows CE: C# Application to Format TFAT&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;In &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/29/windows-ce-formatting-tfat.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Formatting TFAT&lt;/font&gt;&lt;/a&gt; I show how to format a disk with TFAT using C/C++ code. The customer that I wrote that for develops using C#, so I wrote a C# application to test the formatting code. To me, most formatting tools are just too difficult for the average user. In this case, the user will be someone working in the factory or field service. They just need to select a disk and request that it be formatted.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The application dialog look like:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;img width="329" height="167" alt="" src="/images/geekswithblogs_net/BruceEitman/8095/FormatTFAT/FormatTool.JPG" /&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;It has a drop down list which I populated with a list of disks, a format button and an exit button. It is simple, and easy to use.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The hard part of this application is populating the drop down list. I did some searching and found suggestion of using System.IO.DirectoryInfo to find the root folders and check the attributes for temporary folders. The following code demonstrates this approach, were DiskSelect is the drop down list:&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            System.IO.&lt;span style="color: #2b91af"&gt;DirectoryInfo&lt;/span&gt; DI = &lt;span style="color: blue"&gt;new&lt;/span&gt; System.IO.&lt;span style="color: #2b91af"&gt;DirectoryInfo&lt;/span&gt;(&lt;span style="color: #a31515"&gt;@"\"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;            System.IO.&lt;span style="color: #2b91af"&gt;DirectoryInfo&lt;/span&gt;[] Folders = DI.GetDirectories();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;foreach&lt;/span&gt; (System.IO.&lt;span style="color: #2b91af"&gt;DirectoryInfo&lt;/span&gt; FDI &lt;span style="color: blue"&gt;in&lt;/span&gt; Folders)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt; (FDI.Attributes.CompareTo(System.IO.&lt;span style="color: #2b91af"&gt;FileAttributes&lt;/span&gt;.Temporary) == 1)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    DiskSelect.Items.Add(FDI.Name);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt;( DiskSelect.Items.Count &amp;gt; 0 )&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;span&gt;              DiskSelect.SelectedIndex = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;This code works and can be effective on some systems. But it has a flaw which is that not all temprary folders are disks. If your OS includes the network redirector component, there will be a Network folder which is temporary but is not a disk. The Release folder which is used in debugging the OS using Platform Builder is also temporary, but not a disk.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The only alternative that I could find is to use FindFirstStore()/FindNextStore() and FindFirstPartition()/FindNextPartition() which are included in StoreAPI. The downside of this approach is that StoreAPI is not generaly included in the SDK and worse, it is not a DLL in the system so it cannot be P/Invoked. So if you don’t have access to the StoreAPI, you might as well stop reading now – the rest of this assumes that you do have access to StoreAPI. If you don’t have it, you might want to ask your OEM for it because it has some valuable functions for accessing disk information.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I could have simply wrapped the StoreAPI with a DLL, which would have been as simple as just linking StoreAPI.lib with a DllEntry() function. But I am not a good enough C# programmer to define the structures needed for C# and I felt that for a C# program the functions are just too clunky. Instead I made some assumptions before writing the code. The assumptions are:&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 27pt"&gt;&lt;span&gt;1.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;The functions that I will be writing will be used for populating a drop down list and nothing more sophisticated&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 10pt 27pt"&gt;&lt;span&gt;2.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;The disks have only one partition, if you are working with systems that have multiple partitions you can extend the code to handle that but I didn’t need it&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I realized that I needed to have some data that I could let the application track and pass into function calls. So I started by defining the structure that I needed:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;typedef&lt;/span&gt; &lt;span style="color: blue"&gt;struct __FindDiskInfo__&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                STOREINFO StoreInfo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                PARTINFO PartInfo;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;} FindDiskInfoT;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;STOREINFO and PARTINFO are defined in storemgr.h which is included in the SDK. I plan to create functions that populate the structure and then some functions to get the strings that I need. This should make the C# fairly easy to write. The first step is to initalize the structure and get a pointer/reference from the C/C++ code to the C# code. NewStoreInfo() will allocate the storage and initialize it and DeleteStoreInfo() will release the structure:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) FindDiskInfoT * APIENTRY NewStoreInfo()&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                FindDiskInfoT *FindDiskInfo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"NewStoreInfo\n"&lt;/span&gt;)));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                FindDiskInfo = (FindDiskInfoT *)malloc( &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(FindDiskInfoT) );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( FindDiskInfo == NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"StartFindStore: malloc failed\n"&lt;/span&gt;)));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;return&lt;/span&gt; NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                memset(FindDiskInfo, 0, &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(FindDiskInfoT));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                FindDiskInfo-&amp;gt;StoreInfo.cbSize = &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(STOREINFO);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                FindDiskInfo-&amp;gt;PartInfo.cbSize = &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(PARTINFO);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                wcscpy(FindDiskInfo-&amp;gt;PartInfo.szVolumeName, TEXT(&lt;span style="color: #a31515"&gt;"TEST VolName"&lt;/span&gt;));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"NewStoreInfo return %X\n"&lt;/span&gt;), FindDiskInfo));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; FindDiskInfo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) BOOL APIENTRY DeleteStoreInfo(HANDLE hFind, FindDiskInfoT *FindDiskInfo)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( FindDiskInfo != NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                free( FindDiskInfo );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( hFind )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                FindCloseStore( hFind );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; TRUE;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;And the C# call to these function is:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; StoreInfo;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;StoreInfo = NewStoreInfo();&lt;/div&gt;
&lt;div&gt;…&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;DeleteStoreInfo(hStore, StoreInfo);&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Note that DeleteStoreInfo() has an hStore passed into into it. hStore is HANDLE used for finding the disks. hStore is returned from StartFindDisk() which is called to start finding available disks. StartFindDisk() receives a pointer to the previously allocated FindDiskInfoT:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) HANDLE APIENTRY StartFindDisk( FindDiskInfoT *FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div style="text-indent: 0.5in"&gt;HANDLE hFind = INVALID_HANDLE_VALUE;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                hFind = FindFirstStore(&amp;amp;(FindDiskInfo-&amp;gt;StoreInfo));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( hFind != INVALID_HANDLE_VALUE )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                HANDLE hStore;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                hStore = OpenStore( FindDiskInfo-&amp;gt;StoreInfo.szDeviceName );                &lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;if&lt;/span&gt;( hStore )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                HANDLE hFind = INVALID_HANDLE_VALUE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                hFind = FindFirstPartition(hStore, &amp;amp;(FindDiskInfo-&amp;gt;PartInfo));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                &lt;span style="color: blue"&gt;if&lt;/span&gt;(INVALID_HANDLE_VALUE != hFind)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                FindClose(hFind);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"No Partitions Found\n"&lt;/span&gt;)));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                CloseHandle(hStore);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                RETAILMSG(1, (TEXT(&lt;span style="color: #a31515"&gt;"OpenSelectedStore failed\n"&lt;/span&gt;)));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"StartFindStore: FindFirstStore failed %d\n"&lt;/span&gt;), GetLastError()));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; hFind;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;And the C# call is:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;            hStore = StartFindDisk(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;StartFindDisk() finds the first available disk and the first partition on the disk and populates the FindDiskInfoT structure with the available information for use later. After calling this, to get the name of the folder, the device name and the partition name, the following functions can be used:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) TCHAR * APIENTRY GetStoreDeviceName( FindDiskInfoT *FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                TCHAR * RetVal = NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                RetVal = FindDiskInfo-&amp;gt;StoreInfo.szDeviceName;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; RetVal;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) TCHAR * APIENTRY GetStoreFolderName( FindDiskInfoT *FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                TCHAR * RetVal = NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                RetVal = FindDiskInfo-&amp;gt;PartInfo.szVolumeName;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; RetVal;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) TCHAR * APIENTRY GetStorePartitionName( FindDiskInfoT *FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                TCHAR * RetVal = NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                RetVal = FindDiskInfo-&amp;gt;PartInfo.szPartitionName;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; RetVal;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Then to get the rest of the disks, FindNextDisk() is used:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) BOOL APIENTRY FindNextDisk( HANDLE hFind, FindDiskInfoT *FindDiskInfo )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div style="text-indent: 0.5in"&gt;BOOL FindResult = FALSE;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( FindDiskInfo == NULL || hFind == INVALID_HANDLE_VALUE )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"FindNextDisk: invalid parameters\n"&lt;/span&gt;)));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                &lt;span style="color: blue"&gt;return&lt;/span&gt; FALSE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                FindResult = FindNextStore(hFind, &amp;amp;(FindDiskInfo-&amp;gt;StoreInfo));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( FindResult != FALSE )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                HANDLE hStore;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                hStore = OpenStore( FindDiskInfo-&amp;gt;StoreInfo.szDeviceName );                &lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;if&lt;/span&gt;( hStore )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                HANDLE hFind = INVALID_HANDLE_VALUE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                memset( &amp;amp;(FindDiskInfo-&amp;gt;PartInfo), 0, &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(PARTINFO));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                FindDiskInfo-&amp;gt;PartInfo.cbSize = &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;(PARTINFO);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                hFind = FindFirstPartition(hStore, &amp;amp;(FindDiskInfo-&amp;gt;PartInfo));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                &lt;span style="color: blue"&gt;if&lt;/span&gt;(INVALID_HANDLE_VALUE != hFind)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                FindClose(hFind);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"FindNextDisk: No Partitions Found %d\n"&lt;/span&gt;), GetLastError()));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                FindResult = FALSE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                CloseHandle(hStore);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                RETAILMSG(1, (TEXT(&lt;span style="color: #a31515"&gt;"FindNextDisk: OpenSelectedStore failed\n"&lt;/span&gt;)));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                FindResult = FALSE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"FindNextDisk: FindNextStore failed %d\n"&lt;/span&gt;), GetLastError()));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                FindResult = FALSE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; FindResult;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Similar to StartFindDisk() this finds the next disk and its first partition and populates the FindDiskInfoT with the available data, so that the strings can be retreived later.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The code for setting up the C# dialog looks like:&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: blue"&gt;bool&lt;/span&gt; FormatDiskTFAT(&lt;span style="color: #2b91af"&gt;String&lt;/span&gt; StoreName, &lt;span style="color: #2b91af"&gt;String&lt;/span&gt; PartitionName);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: blue"&gt;bool&lt;/span&gt; FormatDiskTFATEx(&lt;span style="color: #2b91af"&gt;String&lt;/span&gt; FolderName);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; StartFindDisk(&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; pStoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: blue"&gt;bool&lt;/span&gt; DeleteStoreInfo(&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; hStore, &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; FindDiskInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: blue"&gt;bool&lt;/span&gt; FindNextDisk(&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; hFind, &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; pStoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; GetStoreDeviceName(&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; pStoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; GetStoreFolderName(&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; pStoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; GetStorePartitionName(&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; pStoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        [&lt;span style="color: #2b91af"&gt;DllImport&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"FormatDLL.dll"&lt;/span&gt;, CharSet = &lt;span style="color: #2b91af"&gt;CharSet&lt;/span&gt;.Auto, SetLastError = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;extern&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; NewStoreInfo();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: #2b91af"&gt;DiskInfo&lt;/span&gt;[] Disks;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;public&lt;/span&gt; FormatTool()&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; StoreInfo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; hStore;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; ipName;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;int&lt;/span&gt; DiskCount = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;            InitializeComponent();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;           &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            StoreInfo = NewStoreInfo();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            hStore = StartFindDisk(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt; (hStore != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                Disks = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;DiskInfo&lt;/span&gt;[1];&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                Disks[DiskCount] = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;DiskInfo&lt;/span&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                ipName = GetStoreDeviceName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                Disks[DiskCount].DeviceName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                ipName = GetStoreFolderName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                Disks[DiskCount].FolderName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                ipName = GetStorePartitionName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                Disks[DiskCount].PartitionName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DiskSelect.Items.Add(Disks[DiskCount].FolderName);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DiskSelect.SelectedIndex = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DiskCount++;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;while&lt;/span&gt; (FindNextDisk(hStore, StoreInfo))&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    &lt;span style="color: #2b91af"&gt;DiskInfo&lt;/span&gt;[] NewDisks = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;DiskInfo&lt;/span&gt;[DiskCount+1];&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    Disks.CopyTo(NewDisks, 0);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    NewDisks[DiskCount] = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;DiskInfo&lt;/span&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    ipName = GetStoreDeviceName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    NewDisks[DiskCount].DeviceName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    ipName = GetStoreFolderName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    NewDisks[DiskCount].FolderName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    ipName = GetStorePartitionName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    NewDisks[DiskCount].PartitionName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    DiskSelect.Items.Add(NewDisks[DiskCount].FolderName);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    DiskCount++;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    Disks = NewDisks;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DeleteStoreInfo(hStore, StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt; (DiskSelect.Items.Count &amp;gt; 0)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    DiskSelect.SelectedIndex = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;             &lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I probably could have simplified this code, and if it were a long term project I would spend time on that.&lt;span&gt;   This cod uses a class for keeping track of the disk information for use in the call to FormatDiskTFAT:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    public class &lt;span style="color: #2b91af"&gt;DiskInfo&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        public &lt;span style="color: #2b91af"&gt;String&lt;/span&gt; FolderName;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        public &lt;span style="color: #2b91af"&gt;String&lt;/span&gt; DeviceName;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        public &lt;span style="color: #2b91af"&gt;String&lt;/span&gt; PartitionName;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;But in hindsight I wrote FormatDiskTFATEx() which doesn’t need all of that information. So the code can be simplified to:&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: #2b91af"&gt;String&lt;/span&gt; DiskName;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            StoreInfo = NewStoreInfo();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            hStore = StartFindDisk(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt; (hStore != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                ipName = GetStorePartitionName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DiskName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DiskSelect.Items.Add(DiskName);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DiskSelect.SelectedIndex = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;while&lt;/span&gt; (FindNextDisk(hStore, StoreInfo))&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    ipName = GetStorePartitionName(StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    DiskName = &lt;span style="color: #2b91af"&gt;Marshal&lt;/span&gt;.PtrToStringUni(ipName).ToString();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    DiskSelect.Items.Add(DiskName);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                DeleteStoreInfo(hStore, StoreInfo);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt; (DiskSelect.Items.Count &amp;gt; 0)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                    DiskSelect.SelectedIndex = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Finally, when the Format button is pressed we need to format the disk. The button handler is:&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        &lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; FormatButton_Click(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;int&lt;/span&gt; Index = DiskSelect.SelectedIndex;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;            Exitbutton.Visible = &lt;span style="color: blue"&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            FormatButton.Visible = &lt;span style="color: blue"&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            Formatinglabel.Text = &lt;span style="color: #a31515"&gt;"Formatting, Please Wait"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            Formatinglabel.Visible = &lt;span style="color: blue"&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;this&lt;/span&gt;.Refresh();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;            System.Threading.&lt;span style="color: #2b91af"&gt;Thread&lt;/span&gt;.Sleep(2000); &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            FormatDiskTFAT(Disks[Index].DeviceName, Disks[Index].PartitionName);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;            Exitbutton.Visible = &lt;span style="color: blue"&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            FormatButton.Visible = &lt;span style="color: blue"&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            Formatinglabel.Text = &lt;span style="color: #a31515"&gt;"Formatting Complete"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            Formatinglabel.Visible = &lt;span style="color: blue"&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;            &lt;span style="color: blue"&gt;this&lt;/span&gt;.Refresh();&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Which uses FormatDiskTFAT(), but FormatDiskTFATEx() can be used as:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;            FormatDiskTFATEx(DiskSelect.SelectedItem.ToString());&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;FormatButton_Click() hides the buttons and puts a message in a static text box to tell the user to wait then formats the disk. After the disk is formatted, it changes the text to Format Complete and puts the buttons back in. The problem that I found is that the format can be very quick, too quick so that the message isn’t displayed and the buttons aren’t removed. So I added a 2 second delay just to let the user know that something happened.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141557.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141557.aspx</wfw:comment>
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141557.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141557.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows CE: Formatting TFAT</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/29/windows-ce-formatting-tfat.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/29/windows-ce-formatting-tfat.aspx</id>
        <published>2010-08-29T22:42:25-04:00:00</published>
        <updated>2010-08-31T09:09:18Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;A customer came to me for assistance in formatting an SD card with TFAT. I did a quick look in the control panel code to find how it formats disks as TFAT and told the customer to use FormatVolume() and set the FORMAT_OPTIONS dwFlags FATUTIL_FORMAT_TFAT flag.   &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I assumed that it was that easy and left the customer to write the code. A few weeks later the customer came back to me and said that they just couldn’t get FormatVolume() to work, let alone format the disk as TFAT. So this time I dug deeper and write some code to test it out before getting back to the customer. The following is what I figured out including the code to format a disk as TFAT.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;What went wrong? When I first looked at how to format TFAT, I looked to see what happens when the Format button is selected. What I didn’t look for is what has to happen before the Format button is selectable. It turns out that before the Format button is selectable, the partition must first be dismounted.&lt;/div&gt;
&lt;div&gt;__declspec(dllexport) BOOL APIENTRY FormatDiskTFAT( TCHAR *&lt;span style="font-size: 10pt"&gt;StoreName&lt;/span&gt;, TCHAR *PartitionName )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                HANDLE hStore;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                HANDLE hPartition;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                hStore = OpenStore(&lt;/span&gt;&lt;span style="font-size: 10pt"&gt;StoreName&lt;/span&gt;);&lt;span&gt;           &lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                if( INVALID_HANDLE_VALUE != hStore )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                hPartition = OpenPartition( hStore, PartitionName );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                if( INVALID_HANDLE_VALUE != hPartition )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                if( DismountPartition(hPartition) )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                {    &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                FORMAT_OPTIONS fo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                // Get formating options&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                fo.dwClusSize = 4 * 1024;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                fo.dwFatVersion = 32;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                fo.dwNumFats = 2;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                fo.dwRootEntries = 512;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                fo.dwFlags = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                //fo.dwFlags |= FATUTIL_FULL_FORMAT;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                fo.dwFlags |= FATUTIL_FORMAT_TFAT;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                if( ERROR_SUCCESS != pfnFormatVolume( hPartition, NULL, &amp;amp;fo, HandleProgress, HandleMessage ))&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                                RETAILMSG( 1, (TEXT("Format Failed\n")));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                MountPartition(hPartition);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                else&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                RETAILMSG( 1, (TEXT("Failed to dismount Partition\n")));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                CloseHandle( hPartition );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                else&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                RETAILMSG(1, (TEXT("OpenPartition failed\n")));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                CloseHandle(hStore);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                else&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                RETAILMSG(1, (TEXT("OpenSelectedStore failed\n")));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                return TRUE;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;FormatDiskTFAT() takes two strings as arguments:&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;·&lt;span style="font: 7pt 'Times New Roman'"&gt;         &lt;/span&gt;&lt;/span&gt;StoreName which is the szDeviceName in the STOREINFO structure returned from FindFirstStore()/FindNextStore() or the szStoreName in the CE_VOLUME_INFO structure returned from CeGetVolumeInfo(). The value of the string will be somethings like “DSK1:”.&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 10pt 0.5in"&gt;&lt;span&gt;·&lt;span style="font: 7pt 'Times New Roman'"&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span style="line-height: 115%"&gt;PartitionName which is the szPartionName in PARTINFO and CE_VOLUME_INFO returned by FindFirstPartition()/FindNextPartition() and CeGetVolumeInfo(). The value of the string will be something like “PART00”.&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;FormatDiskTFAT() uses the strings to open the store and the partition. Then it dismounts the partition, formats the disk and re-mounts the partition.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I choose the function signature because I was thinking about using FindFirstStore()/FindNextStore(), so the device name and the partition name would be readily available. As an afterthought, I decided that it might be handy to have a function that simply takes the folder name of the disk, so I came up with FormatDiskTFATEx():&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;__declspec&lt;/span&gt;(&lt;span style="color: blue"&gt;dllexport) BOOL APIENTRY FormatDiskTFATEx( TCHAR *FolderName )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                CE_VOLUME_INFO VolInfo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                VolInfo.cbSize = &lt;span style="color: blue"&gt;sizeof&lt;/span&gt;( CE_VOLUME_INFO );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                CeGetVolumeInfo(FolderName, CeVolumeInfoLevelStandard, &amp;amp;VolInfo );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; FormatDiskTFAT( VolInfo.szStoreName, VolInfo.szPartitionName );&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;FormatDiskTFATEx() takes one string as an argument which is the name of the disk folder. This will be something like “Storage Card” or “\Storage Card” depending on how you obtain the string.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;One of the interesting problems that I ran into is that building this for Windows CE 5.0 (I have not tested yet with CE 6.0) the call to CeGetVolumeInfo() causes a linker error because CeGetVolumeInfoW() does not exist. The solution to this problem is to undefine CeGetVolumeInfo(). So I added:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;#ifdef&lt;/span&gt; CeGetVolumeInfo&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;#undef&lt;/span&gt; CeGetVolumeInfo&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;#endif&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Then next problem that I needed to solve is that while I can easily compile this code using Platform Builder, my customer who is using an SDK that I provided cannot. The problem is that FATUTIL.DLL is included in the OS, but FATUTIL.LIB is not included in the SDK and FormatVolume() is in FATUTIL. It would be easy enough to create a new SDK and release it, but that may be overkill for one function. So the solution that I came up with is to use LoadLibrary() and GetProcAddress().&lt;span&gt;   I am including these functions in a DLL, so I did the mapping in DllEntry():&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;HMODULE hFatUtil = NULL;&lt;/div&gt;
&lt;div&gt;DWORD (*pfnFormatVolume)(HANDLE hVolume,&lt;span style="color: blue"&gt;void *pdi,FORMAT_OPTIONS *pfo,&lt;span style="color: blue"&gt;void&lt;/span&gt; *pfnProgress,&lt;span style="color: blue"&gt;void&lt;/span&gt; *pfnMessage);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void *GetFormatVolume(HMODULE *hFatUtil);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;BOOL APIENTRY DllMain( HANDLE hModule,&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                       DWORD ul_reason_for_call, &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                       LPVOID lpReserved&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                                                 )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;switch&lt;/span&gt;( ul_reason_for_call )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;case&lt;/span&gt; DLL_PROCESS_ATTACH:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                pfnFormatVolume = GetFormatVolume(&amp;amp;hFatUtil);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                &lt;span style="color: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;case&lt;/span&gt; DLL_PROCESS_DETACH:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                FreeLibrary(hFatUtil);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                &lt;span style="color: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    &lt;span style="color: blue"&gt;return&lt;/span&gt; TRUE;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The last problem is that FORMAT_OPTIONS needed by FormatVolume() is also not available in the SDK, or more accuratly the header file that they are included in doesn’t compile cleanly, so I included them in the C code:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;#define&lt;/span&gt; FATUTIL_FULL_FORMAT&lt;span&gt;                 0x1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;#define&lt;/span&gt; FATUTIL_FORMAT_TFAT&lt;span&gt;                 0x2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;typedef&lt;/span&gt; &lt;span style="color: blue"&gt;struct _FORMAT_OPTIONS {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    DWORD   dwClusSize;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    DWORD   dwRootEntries;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    DWORD   dwFatVersion;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    DWORD   dwNumFats;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;    DWORD   dwFlags;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;} FORMAT_OPTIONS;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span style="font-family: &amp;quot;Calibri&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 11pt; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;In my next article (see &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/30/windows-ce-c-application-to-format-tfat.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: C# Application to Format TFAT&lt;/font&gt;&lt;/a&gt;), &lt;/span&gt;I will show how to use these functions from C#. As for using them from C/C++, you may want to review &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/06/25/windows-ce-displaying-disk-information.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Displaying Disk Information&lt;/font&gt;&lt;/a&gt; for example code that uses FindFirstStore()/FindNextStore() and FindFirstPartition()/FindNextPartition() to enumerate the mounted disks.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;b&gt;NOTE 1: &lt;/b&gt;In FormatDiskTFAT() I have commented out the line “&lt;span style="line-height: 115%"&gt;//fo.dwFlags |= FATUTIL_FULL_FORMAT;” because in my testing with both this code and the Storage Manager control panel applet, the full format would not complete.&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span style="line-height: 115%"&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;b&gt;&lt;span style="line-height: 115%"&gt;NOTE 2: &lt;/span&gt;&lt;/b&gt;&lt;span style="line-height: 115%"&gt;I made a conscious choice to hardcode the formatting options in FormatDiskTFAT() because while these options are interesting, they just shouldn’t be user options in an embedded system. I could have pushed them up to the caller function, but that opens the door for a confusing user interface.&lt;/span&gt;&lt;/div&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141545.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141545.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141545.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141545.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows Compact: Discussion Forums</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/18/windows-compact-discussion-forums.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/18/windows-compact-discussion-forums.aspx</id>
        <published>2010-08-18T19:53:38-04:00:00</published>
        <updated>2011-06-28T09:44:12Z</updated>
        <content type="html">&lt;div style="line-height: normal; margin: 0in 0in 10pt"&gt;I monitor some Windows Compact (the new name for Windows CE) Forums for a few reasons:&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;I learn a lot from others working on Windows CE, so many of you are running into the same issues that I run into.  Sometimes you run into them before I do, other times I have already run into the issue.&lt;/li&gt;
    &lt;li&gt;I learn a lot from answering questions.  You might be surprised to find that sometimes I don't already know the answer, so I do some investigation to get the answer.  Sometimes I am wrong, or there is a better way, with my answer, and there is always someone to point that out.&lt;/li&gt;
    &lt;li&gt;I get satisfaction from helping others by answering their questions&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="line-height: normal; margin: 0in 0in 10pt"&gt;I monitor the following Forums:&lt;/div&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;span style="color: #3a3e43"&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/winembmngdapp/threads"&gt;Windows Embedded Compact Managed Application Development&lt;/a&gt; which discusses C# and VB .NET managed application development&lt;/span&gt;&lt;/li&gt;
    &lt;li&gt;&lt;span style="color: #3a3e43"&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/winembnatapp/threads"&gt;Windows Embedded Compact Native Application Development&lt;/a&gt; is a forum for discussing C/C++ application development&lt;/span&gt;&lt;/li&gt;
    &lt;li&gt;&lt;span style="color: #3a3e43"&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/winembplatdev/threads"&gt;&lt;font color="#800080"&gt;Windows Embedded Compact Platform Development&lt;/font&gt;&lt;/a&gt; a forum for discussing issues related to use of Platform Builder for Windows Compact OS development&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="color: #3a3e43"&gt;I use Internet Explorer to monitor and answer questions. &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/category/windowsembeddedcompact"&gt;&lt;font color="#800080"&gt;Windows Embedded Compact Category&lt;/font&gt;&lt;/a&gt; is a page which lists all three of the Windows Compact forums.&lt;/span&gt;&lt;/p&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141374.aspx" width="1" height="1" /&gt;</content>
    </entry>
    <entry>
        <title>Platform Builder: Write, Debug, Fix, Debug…</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/17/platform-builder-write-debug-fix-debug.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/17/platform-builder-write-debug-fix-debug.aspx</id>
        <published>2010-08-17T20:28:27-04:00:00</published>
        <updated>2010-08-17T20:28:27Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;The question came up again about how to quickly test an application or driver using Platform Builder and KITL. This article will show how this test cycle can be done quickly without building a new OS and downloading it.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Of course Platform Builder is a tool for developing an operating system, so if you use its default behavior it will build an operating system. So that means that a small change to source code means building the operating system and deploying it to your device. But we will look at how we can do things a little differently and speed up the process. &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The basic steps are:&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;1.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Add KITL support&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;2.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Add Target Control Support (Shell.exe)&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;3.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Leave your app out of the OS, but leave in the registry settings&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;4.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Build your OS&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;5.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Start the OS and connect KITL&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;6.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;When your run the app, it will load over your KITL connection&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;7.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Update your app&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;8.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Build your app&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 10pt 0.5in"&gt;&lt;span&gt;9.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Repeat starting at step 6&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;For this article I am not going to show you everything, but I will describe what I did to write an application and test it using KITL without rebuilding the OS. I am writing this while sitting in an airport, so I am using the emulator but these techniques work just as well with a real device, maybe better.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I started by creating a new project, not that this is important but I didn’t have one to work with. I wanted to keep it simple so I chose the Emulator BSP and the Thin Client template. I left out anything that I didn’t need for this article, like the .NET CompactFramework. I double checked that KITL was enabled and that Target Control Support was included. Target Control Support is important to this because it adds support for the \Release folder which links back to the _FLATRELEASEDIR on the development PC. I change the shell from the Thin Client shell to the standard shell, honestly I am not familiar with the Thin Client shell and felt more comfortable with the standard shell for a quick test.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Next I added a subproject. I am adding it now, before building the OS, so that it more closely simulates a real world project. The project is a WCE Application and I selected a simple Hello World template. This template doesn’t provide a menu with an option to Exit, so using code from &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/06/windows-ce-setting-an-application-to-display-full-screen-in.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Setting an Application to Display Full Screen in C/C++&lt;/font&gt;&lt;/a&gt; I added an exit button. Being able to exit the application being tested will be very important for speeding up the test cycle.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;We are almost ready to build and test, but first, and this is important for speeding up the test cycle, remove the subproject application from the OS image.   If you are testing a driver, the same thing applies. There are a couple of ways to remove the application from the image:&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;span&gt;1.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;In the OSDesign Properties, select Configuration Properties\Subproject Image Settings. Double click on the subproject that you are working on, and then select Exclude from Image.&lt;br /&gt;
 &lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt; &lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 0pt 0.5in"&gt;&lt;img width="689" height="422" alt="" src="/images/geekswithblogs_net/BruceEitman/8095/WriteDebugFixDebug/Properties.JPG" /&gt;&lt;br /&gt;
&lt;br /&gt;
It took me a long time to find this property. In prior versions of Platform Builder it was much easier to exclude a file from the OS. For that reason, my first test I used option 2.&lt;/div&gt;
&lt;div style="text-indent: -0.25in; margin: 0in 0in 10pt 0.5in"&gt;&lt;span&gt;2.&lt;span style="font: 7pt 'Times New Roman'"&gt;       &lt;/span&gt;&lt;/span&gt;Comment out the file in the bib file.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;It is finally time to build the OS and run the first test. For this, run Sysgen and attach to the device.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Once the OS is running, you can start your application by using Start\Run. Looking at the debug output you will see that the application was loaded by RelFSD, which is the \Release folder.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;img width="760" height="196" alt="" src="/images/geekswithblogs_net/BruceEitman/8095/WriteDebugFixDebug/RelfsdDownload.JPG" /&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;That means that the application was downloaded from your _FLATRELEASEDIR and was not in the OS image. If it isn’t in the OS image, which means that we can change it without changing the OS image, or for that matter restarting the device and downloading the image. The application looks like this when I run it:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;img width="246" height="372" alt="" src="/images/geekswithblogs_net/BruceEitman/8095/WriteDebugFixDebug/Subproject1.JPG" /&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The next step is to modify the application. In this case, I want to app to say “The App is running” instead of “Hello World!” So I changed the string table to modify the string that is displayed.  I also fixed the location of the button so that it doesn't sit on top of the text.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Now we need to build the application, not the whole OS. I am a command line kind of engineer, so I would open a build window, change directories to the subproject folder and run build. If you like to use Visual Studio, then start by unchecking Build\Targeted Build Settings\Make Run-Time Image After Build, which is important because we don’t need to make the run-time image and the process takes considerable time.   Now you can right click on your subproject in the Solution Explorer and select Build (for this to work well, set the environment variable WINCEREL to 1).&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Finally, run the application again, now it looks like:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;img width="246" height="372" alt="" src="/images/geekswithblogs_net/BruceEitman/8095/WriteDebugFixDebug/Subproject1Changed.JPG" /&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;To use this same technique to test a stream interface driver, leave the driver and its registry settings out of the OS. Then call ActivateDevice() and DeactivateDevice() from your application as shown in &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/07/14/windows-ce-loading-a-driver-with-activatedeviceex.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Loading a Driver with ActivateDeviceEx&lt;/font&gt;&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141361.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141361.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141361.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141361.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows CE: Disable the Taskbar for Full Screen Applications</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/15/windows-ce-disable-the-taskbar-for-full-screen-applications.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/15/windows-ce-disable-the-taskbar-for-full-screen-applications.aspx</id>
        <published>2010-08-15T22:59:00-04:00:00</published>
        <updated>2010-08-15T22:59:00Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;In the article &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/06/windows-ce-setting-an-application-to-display-full-screen-in.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Setting an Application to Display Full Screen in C/C++&lt;/font&gt;&lt;/a&gt; I discussed how to show an application full screen using C++. I discussed that for a kiosk application that the easiest way to disable the Explorer shell taskbar is to simply not have the Explorer shell launch when the system starts up. But there are cases where having the Explorer shell run underneath the kiosk app has value in some cases. The trouble is that the taskbar will still respond to special keys like the Windows key and suddenly the user has access to the full system. In this article, we will explore disabling the taskbar.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The first step to disable the taskbar is to get a handle to the taskbar window. To do this we will use FindWindow() and the class name of the taskbar which is “HHTaskBar”. We know that the name is HHTaskBar because the code for the taskbar is available in Platform Builder and a review of the code tells us the name. So to get a handle to the taskbar window:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;                HWND TaskBar = FindWindow(TEXT(&lt;span style="color: #a31515"&gt;"HHTaskBar"&lt;/span&gt;), NULL );&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Now that we have a handle to the taskbar window, we can send it messages. We could send it a WM_CLOSE message:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;                SendMessage(TaskBar, WM_CLOSE, NULL, NULL );&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;But, that will close the Explore shell, which defeats the purpose which is to keep the Explorer shell running and have access to the APIs that it provides.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Better is to hide the taskbar, not in the sense of setting its auto hide feature which leaves it usable but minimized. Instead we will disable it with a call to EnableWindow():&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;                EnableWindow( TaskBar, FALSE );&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Which also allows us to reenable the taskbar if and when we need to do so.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;In the modified full screen application from &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/06/windows-ce-setting-an-application-to-display-full-screen-in.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Setting an Application to Display Full Screen in C/C++&lt;/font&gt;&lt;/a&gt;, the WinMain() is now:&lt;/div&gt;
&lt;div&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; WINAPI WinMain(HINSTANCE hInstance,&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                   HINSTANCE hPrevInstance,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                   LPTSTR    lpCmdLine,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                   &lt;span style="color: blue"&gt;int&lt;/span&gt;       nCmdShow)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                MSG msg;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( lpCmdLine )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                SignalStarted( _wtol(lpCmdLine) );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                HWND TaskBar = FindWindow(TEXT(&lt;span style="color: #a31515"&gt;"HHTaskBar"&lt;/span&gt;), NULL );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( TaskBar != NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                EnableWindow( TaskBar, FALSE );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: green"&gt;// Perform application initialization:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt; (!InitInstance(hInstance, nCmdShow)) &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;if&lt;/span&gt;( TaskBar != NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                EnableWindow( TaskBar, TRUE );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;return&lt;/span&gt; FALSE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                HACCEL hAccelTable;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DELETEMENEXT));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: green"&gt;// Main message loop:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;while&lt;/span&gt; (GetMessage(&amp;amp;msg, NULL, 0, 0)) &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                &lt;span style="color: blue"&gt;if&lt;/span&gt; (!TranslateAccelerator(msg.hwnd, hAccelTable, &amp;amp;msg)) &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                TranslateMessage(&amp;amp;msg);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                                DispatchMessage(&amp;amp;msg);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                TaskBar = FindWindow(TEXT(&lt;span style="color: #a31515"&gt;"HHTaskBar"&lt;/span&gt;), NULL );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;if&lt;/span&gt;( TaskBar != NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                                EnableWindow( TaskBar, TRUE );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                &lt;span style="color: blue"&gt;return&lt;/span&gt; (&lt;span style="color: blue"&gt;int&lt;/span&gt;) msg.wParam;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Which not only disables the taskbar when the application starts, but reenables it when the application exits.&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141326.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141326.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141326.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141326.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows CE: Setting an Application to Display Full Screen in C/C++</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/06/windows-ce-setting-an-application-to-display-full-screen-in.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/06/windows-ce-setting-an-application-to-display-full-screen-in.aspx</id>
        <published>2010-08-06T22:47:16-04:00:00</published>
        <updated>2010-08-06T22:58:37Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;Many, maybe even most, Windows CE devices are single purpose devices that have an application that fills the entire screen. So of course setting the application to entirely fill the display is important. In this article we will explore setting an application to display full screen using C/C++.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;My plan is to create a simple application that fills the screen with white and displays two buttons, exit and explore. Those may be odd buttons for a kiosk application, but they will come in handy while working on this application. The exit button will exit the application and the explore button will start the Explorer shell and then exit the application.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Working in Visual Studio 2005, I started by creating a new C++ Win32 Smart Device Application and let the wizard create the starting source code. I then deleted the code for the menu and the about dialog since I don’t need them. If we run the application now we will find two things about it; we can’t exit (now you know why I am going to add the exit button) and the Explorer shell’s task bar is filling part of the screen.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The application almost fills the screen. This is because the CreateWindow() call that was added by Visual Studio set the location and size using &lt;span style="line-height: 115%; font-size: 10pt"&gt;CW_USEDEFAULT&lt;/span&gt;. This causes the application size to be full screen, minus the task bar area.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Next let’s add the exit button. To do that, I added a global HWND and create the button with CreateWindow() in InitInstance():&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;HWND ExitButton;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; …&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      ExitButton = CreateWindow(TEXT(&lt;span style="color: #a31515"&gt;"Button"&lt;/span&gt;),TEXT(&lt;span style="color: #a31515"&gt;"Exit"&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            20,20,100,40,hWnd,(HMENU)IDM_FILE_EXIT,g_hInst,0);    &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;( ExitButton == NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            DWORD Error = GetLastError();&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"ExitButton failed %d\r\n"&lt;/span&gt;), Error));&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;return&lt;/span&gt; FALSE;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;…&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                              DestroyWindow(ExitButton);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Note that the button size and location are hardcoded, we will look at that later. When the button is pressed, the existing action for closing the application will be called, with the edition of a call to DestroyWindow() for the button. If you test the application now, the exit button will be placed in the top left corner and pressing the button will exit the application.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Let’s step back for little bit, this application is going to run in kiosk mode. That is the application will be full screen and we don’t need the Explorer shell. I discussed how to do this in a previous article, &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/06/30/windows-ce-starting-an-application-when-the-system-boots.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Starting an Application when the System Boots&lt;/font&gt;&lt;/a&gt;. My next step is to add the application to the OS and change the registry so that the Explorer shell doesn’t start and instead this applciation does start. The effect of this change is that the applciation now is full screen. We must add a call to SignalStarted():&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;( lpCmdLine )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            SignalStarted( _wtol(lpCmdLine) );&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;My work here is done. But I will continue.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Now if we test the application by pressing the Exit button, what we will find is that the application stops, but it doesn’t look like it stops because there is nothing to draw on the display. Since we don’t expect this condition in the real world, I am not going to do anything about it. But what I would like to do is start the explorer shell for testing and debugging purposes. To do that lets’s add the Explore button now. The explore button is similar to the exit button, but we will need to add more handling code to support it.&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;HWND ExplorerShellButton;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;…&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      ExplorerShellButton = CreateWindow(TEXT(&lt;span style="color: #a31515"&gt;"Button"&lt;/span&gt;),TEXT(&lt;span style="color: #a31515"&gt;"Explore"&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            20 + 10 + 100,20,100,40,hWnd,(HMENU)IDM_EXPLORER_BUTTON,g_hInst,0);     &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;( ExplorerShellButton == NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            DWORD Error = GetLastError();&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"ExplorerShellButton failed %d\r\n"&lt;/span&gt;), Error));&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;return&lt;/span&gt; FALSE;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;…&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;case&lt;/span&gt; IDM_EXPLORER_BUTTON:&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            TCHAR *AppName = TEXT(&lt;span style="color: #a31515"&gt;"Explorer.exe"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            TCHAR *CommandLine = NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            PROCESS_INFORMATION pi;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt;( CreateProcess( AppName, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &amp;amp;pi))&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  CloseHandle(pi.hProcess);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  CloseHandle(pi.hThread);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"Failed to start app: %s error %d\n"&lt;/span&gt;), AppName, GetLastError() ));&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: green"&gt;//Fall through and exit&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;&lt;span style="color: green"&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: #000000"&gt;&lt;span style="font-size: 10pt"&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: #000000"&gt;&lt;span style="font-size: 10pt"&gt;      DestroyWindow(ExplorerShellButton);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;And in resource.h:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span style="color: blue"&gt;#define&lt;/span&gt; IDM_EXPLORER_BUTTON&lt;span&gt;                   40003&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Now when we test the application, the exit button works like it did before, but we can now use the Explore button to start up the Explorer shell before exiting. If you are testing with the Explorer shell already running, you will find that Windows Explorer starts.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Some of you are problably thinking that for some reason or another you need the Explorer shell running under your application. So you need the application to run full screen even when the task bar is available. To solve this, modify InitInstance() to find out the dimensions of the display and set the application to be top most and use the dimension of the display. The application can find the dimensions of the display using GetDeviceCaps(), and then use the dimensions in a call to SetWindowPosition():&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      HDC hDC;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      DWORD Width;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      DWORD Height;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;…&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      hDC = GetDC(NULL);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      Width = GetDeviceCaps( hDC, HORZRES );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      Height = GetDeviceCaps( hDC, VERTRES );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;span&gt;                SetWindowPos(hWnd, HWND_TOPMOST,0, 0, Width, Height, 0 );&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Now that we have the screen dimensions, I can move the buttons down to the bottom right where I think that they will be better placed:&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      ExitButton = CreateWindow(TEXT(&lt;span style="color: #a31515"&gt;"Button"&lt;/span&gt;),TEXT(&lt;span style="color: #a31515"&gt;"Exit"&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            Width - 200 - 20 - 10, Height - 40 - 20,100,40,hWnd,(HMENU)IDM_FILE_EXIT,g_hInst,0); &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;…&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      ExplorerShellButton = CreateWindow(TEXT(&lt;span style="color: #a31515"&gt;"Button"&lt;/span&gt;),TEXT(&lt;span style="color: #a31515"&gt;"Explore"&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            Width - 100 - 20, Height - 40 - 20,100,40,hWnd,(HMENU)IDM_EXPLORER_BUTTON,g_hInst,0);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;
&lt;div style="line-height: normal"&gt;Now we have an application that displays full screen. &lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;As you test the application with the Explorer shell still running, you will find that there is still a problem if the user has a full keyboard and can use hot keys like the Windows key. I would strongly urge you to consider running your kiosk application without the Explorer shell, so I won’t go into solving that problem now. If your application isn’t a kiosk application, but needs to be full screen, then you should consider leaving support for the hot keys, but I do know that sometimes that isn’t practical.&lt;/div&gt;
 &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141233.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141233.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141233.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141233.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows CE: Launching an Application when a Network Connects </title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/05/windows-ce-launching-an-application-when-a-network-connects.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/05/windows-ce-launching-an-application-when-a-network-connects.aspx</id>
        <published>2010-08-05T21:07:06-04:00:00</published>
        <updated>2010-08-05T21:07:06Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;I was working on a headless system recently and wanted to run cemgrc.exe when a network connection was made. That inspired me to write a little application to do it.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I decided to make the application flexible, so I added a few requirements; be able to run from HKEY_LOCAL_MACHINE\Init, and read the application name and command line from the registry.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Working backward, I wrote a function to read the registry to get the application name and command line and then start the application using CreateProcess(). Regular readers of this blog will recognize most of this code from &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/06/11/windows-ce-reading-a-string-from-the-registry.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Reading a String from the Registry&lt;/font&gt;&lt;/a&gt;.&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;void&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; StartApp()&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      TCHAR *AppName = NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      TCHAR *CommandLine = NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      DWORD Result;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      HKEY hKey;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      DWORD NumBytes = 0;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      DWORD Type;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      PROCESS_INFORMATION pi;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: green"&gt;// Open the Registry Key&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      Result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_START_APP_KEY, 0, 0, &amp;amp;hKey);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;( ERROR_SUCCESS == Result )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// This is a fake read, all it does is fill in NumBytes with the number of&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// bytes in the string value plus the null character.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            Result = RegQueryValueEx( hKey, NETWORK_START_APP_NAME, NULL, &amp;amp;Type, NULL, &amp;amp;NumBytes );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt;( NumBytes &amp;gt; 0 )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  &lt;span style="color: green"&gt;// Now we know how big the string is allocate and read it&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  AppName = (TCHAR *)malloc( NumBytes );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  &lt;span style="color: blue"&gt;if&lt;/span&gt;( AppName != NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  Result = RegQueryValueEx( hKey, NETWORK_START_APP_NAME, NULL, &amp;amp;Type, &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                                                            (LPBYTE)AppName, &amp;amp;NumBytes );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// This is a fake read, all it does is fill in NumBytes with the number of&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// bytes in the string value plus the null character.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            Result = RegQueryValueEx( hKey, NETWORK_START_APP_COMMANDLINE, NULL, &amp;amp;Type, NULL, &amp;amp;NumBytes );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt;( NumBytes &amp;gt; 0 )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  &lt;span style="color: green"&gt;// Now we know how big the string is allocate and read it&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  CommandLine = (TCHAR *)malloc( NumBytes );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  &lt;span style="color: blue"&gt;if&lt;/span&gt;( CommandLine != NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  Result = RegQueryValueEx( hKey, NETWORK_START_APP_COMMANDLINE, NULL, &amp;amp;Type, &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                                                            (LPBYTE)CommandLine, &amp;amp;NumBytes );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            RegCloseKey( hKey );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt;( CreateProcess( AppName, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &amp;amp;pi))&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  CloseHandle(pi.hProcess);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  CloseHandle(pi.hThread);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  RETAILMSG( 1, (TEXT(&lt;span style="color: #a31515"&gt;"Failed to start app: %s error %d\n"&lt;/span&gt;), AppName, GetLastError() ));&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            free( AppName );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            free( CommandLine );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      }&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;StartApp() is really the meat of this application, now we just need to determine if we are running because of a network connection or not and we need to register for network notifications. I do all of this in WinMain():&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;int&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; WINAPI WinMain( HINSTANCE hInstance,&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                    HINSTANCE hPrevInstance,&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                    LPTSTR    lpCmdLine,&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                    &lt;span style="color: blue"&gt;int&lt;/span&gt;       nCmdShow)&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;    TCHAR Path[MAX_PATH];&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      HANDLE hMutex;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;    GetModuleFileName( hInstance, Path, MAX_PATH );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      hMutex = CreateMutex(NULL, TRUE, Path);&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt; (GetLastError() == ERROR_ALREADY_EXISTS){&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            RETAILMSG(1, (TEXT(&lt;span style="color: #a31515"&gt;"%s is running already\r\n"&lt;/span&gt;), Path));&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;return&lt;/span&gt; 0;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;if&lt;/span&gt;( lpCmdLine &amp;amp;&amp;amp; 0 != wcscmp(lpCmdLine, TEXT(&lt;span style="color: #a31515"&gt;"AppRunAtNetConnect"&lt;/span&gt;)) ) &lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: blue"&gt;if&lt;/span&gt;( !CeRunAppAtEvent(Path, NOTIFICATION_EVENT_NET_CONNECT) )&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;                  RETAILMSG(1, (TEXT(&lt;span style="color: #a31515"&gt;"Could not register for notifications\r\n"&lt;/span&gt;)));&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            SignalStarted( _wtol(lpCmdLine) );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      {&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            StartApp();&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// Okay this is maybe wrong, but it prevents running again if we &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            &lt;span style="color: green"&gt;// are run more than once on a network connection&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;            Sleep( 5000 );&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      }&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="font-size: 10pt"&gt;      &lt;span style="color: blue"&gt;return&lt;/span&gt; 1;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Note that if this isn’t a network connection, then the code calls CeRunAppAtEvent() to register for network notifications and calls SignalStarted() in case the application was started from HKEY_LOCAL_MACHINE\Init.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;This file includes and defines the following:&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;#include&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: #a31515"&gt;&amp;lt;windows.h&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;#include&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: #a31515"&gt;&amp;lt;commctrl.h&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;#include&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; &lt;span style="color: #a31515"&gt;&amp;lt;notify.h&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt; &lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;#define&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; NETWORK_START_APP_KEY (TEXT(&lt;span style="color: #a31515"&gt;"Software\\NetworkLauncher"&lt;/span&gt;))&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;#define&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; NETWORK_START_APP_NAME      (TEXT(&lt;span style="color: #a31515"&gt;"AppName"&lt;/span&gt;))&lt;/span&gt;&lt;/div&gt;
&lt;div style="line-height: normal"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;#define&lt;/span&gt;&lt;span style="font-size: 10pt"&gt; NETWORK_START_APP_COMMANDLINE     (TEXT(&lt;span style="color: #a31515"&gt;"CommandLine"&lt;/span&gt;))&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;And now when a network connection is made, I can start cemgrc.exe.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141207.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141207.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141207.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141207.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows CE: Writing an Application to Test GPIO Pins</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-writing-an-application-to-test-gpio-pins.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-writing-an-application-to-test-gpio-pins.aspx</id>
        <published>2010-08-01T19:33:25-04:00:00</published>
        <updated>2010-08-01T20:46:33Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; background: #d9d9d9; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="172" style="border-bottom: gray 2.25pt solid; border-left: #d9d9d9 2.25pt solid; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 200.35pt; padding-right: 5.4pt; border-top: #d9d9d9 2.25pt solid; border-right: gray 2.25pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal; margin: 0in 0in 0pt"&gt;   &lt;a href="http://eurotech-inc.com/Wince-code/GPIO_Example.asp"&gt;&lt;font color="#800080"&gt;&lt;strong&gt;Download GPIO Example driver and appplication source code&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;In previous articles I have developed a driver to access GPIO Pins, &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-using-a-driver-to-readwrite-hardware-registers.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Using a Driver to Read/Write Hardware Registers&lt;/font&gt;&lt;/a&gt;, and a wrapper API for the driver, &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-developing-an-api-to-access-a-driver.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Developing an API to Access a Driver&lt;/font&gt;&lt;/a&gt;. Now it is time to use them from an application.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Because the real work is done in the driver, and because we have some simple to use wrapper functions, this application is very simple. It starts by calling the InitGPIOAPI() function, then it sets GPIO Pin 30 to be an output and then toggles the pin high and low.&lt;/div&gt;
&lt;div&gt;#include &amp;lt;Windows.h&amp;gt;&lt;/div&gt;
&lt;div&gt;#include &amp;lt;GPIO_API.h&amp;gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;int WINAPI WinMain(     HINSTANCE hInstance,&lt;/div&gt;
&lt;div&gt;                                                                                HINSTANCE hPrevInstance,&lt;/div&gt;
&lt;div&gt;                                                                                LPTSTR    lpCmdLine,&lt;/div&gt;
&lt;div&gt;                                                                                int       nCmdShow)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                HANDLE hGPIO_API;     &lt;/div&gt;
&lt;div&gt;                DWORD count;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                RETAILMSG( 1, (TEXT("Testing GPIO\n")));&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                hGPIO_API = InitGPIOAPI();&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                if( hGPIO_API != INVALID_HANDLE_VALUE )&lt;/div&gt;
&lt;div&gt;                {&lt;/div&gt;
&lt;div&gt;                                SetOutputGPIOPin( hGPIO_API, 30 );&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                                for( count = 0; count &amp;lt; 20; count++ )&lt;/div&gt;
&lt;div&gt;                                {&lt;/div&gt;
&lt;div&gt;                                                SetGPIOPin( hGPIO_API, 30 );&lt;/div&gt;
&lt;div&gt;                                                RETAILMSG( 1, (TEXT( "set GPIO 30 is %s\r\n"), ReadGPIOPin(hGPIO_API, 30)?TEXT("Set"):TEXT("Clear")));&lt;/div&gt;
&lt;div&gt;                                                Sleep( 1000 );&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                                                ClearGPIOPin( hGPIO_API, 30 );&lt;/div&gt;
&lt;div&gt;                                                RETAILMSG( 1, (TEXT( "clear GPIO 30 is %s\r\n"), ReadGPIOPin(hGPIO_API, 30)?TEXT("Set"):TEXT("Clear")));&lt;/div&gt;
&lt;div&gt;                                                Sleep( 1000 );&lt;/div&gt;
&lt;div&gt;                                }&lt;/div&gt;
&lt;div&gt;                                DeinitGPIOAPI( hGPIO_API );&lt;/div&gt;
&lt;div&gt;                }&lt;/div&gt;
&lt;div&gt;                RETAILMSG(1,(TEXT("Done\n")));&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                return 0;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; 
&lt;div style="margin: 0in 0in 10pt"&gt;Also see the articles in this series at: &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-developing-an-api-to-access-a-driver.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Developing an API to Access a Driver&lt;/font&gt;&lt;/a&gt; and  &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-using-a-driver-to-readwrite-hardware-registers.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Using a Driver to Read/Write Hardware Registers&lt;/font&gt;&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141148.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141148.aspx</wfw:comment>
        <slash:comments>14</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141148.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141148.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows CE: Developing an API to Access a Driver</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-developing-an-api-to-access-a-driver.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-developing-an-api-to-access-a-driver.aspx</id>
        <published>2010-08-01T17:48:25-04:00:00</published>
        <updated>2010-08-01T20:42:36Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; background: #d9d9d9; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="172" style="border-bottom: gray 2.25pt solid; border-left: #d9d9d9 2.25pt solid; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 200.35pt; padding-right: 5.4pt; border-top: #d9d9d9 2.25pt solid; border-right: gray 2.25pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal; margin: 0in 0in 0pt"&gt;   &lt;a href="http://eurotech-inc.com/Wince-code/GPIO_Example.asp"&gt;&lt;font color="#800080"&gt;&lt;strong&gt;Download GPIO Example driver and appplication source code&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;In my article on reading and writing GPIO pins from a driver (see &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-using-a-driver-to-readwrite-hardware-registers.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Using a Driver to Read/Write Hardware Registers&lt;/font&gt;&lt;/a&gt;) I developed a driver that exposes GPIO pins through DeviceIoControl() calls to the driver’s XXX_IOControl() function.   Using DeviceIoControl() can be messy, so developing wrapper functions helps clean that up, but if the driver developer also created the wrapper and provided it as an API that would help.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;An API is really just a lib file, or DLL, that exposes some functions.   In this case, we will expose the functions from a statically linked library, but it would be a very minor change to provide them as a DLL included in the OS.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;To start, this API will provide a init and deinit functions that will gain access to the driver through CreateFile() and then clean up with CloseHandle():&lt;/div&gt;
&lt;div&gt;HANDLE InitGPIOAPI()&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                HANDLE hDriver;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                // Get a handle to the driver. Which causes the driver's XXX_Open function to be called&lt;/div&gt;
&lt;div&gt;                hDriver = CreateFile( TEXT("XXX1:"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );&lt;/div&gt;
&lt;div&gt;               &lt;/div&gt;
&lt;div&gt;                return hDriver;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;void DeinitGPIOAPI( HANDLE hDriver )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                CloseHandle( hDriver );&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Now we wrapper each of the IOCTL calls:&lt;/div&gt;
&lt;div&gt;BOOL SetGPIOPin( HANDLE hDriver, DWORD PinNumber )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                DWORD BytesHandled;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                return DeviceIoControl( hDriver,&lt;/div&gt;
&lt;div&gt;                                IOCTL_SET_GPIO,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;PinNumber,&lt;/div&gt;
&lt;div&gt;                                sizeof( PinNumber ),&lt;/div&gt;
&lt;div&gt;                                NULL,&lt;/div&gt;
&lt;div&gt;                                0,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;BytesHandled,&lt;/div&gt;
&lt;div&gt;                                NULL );&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;BOOL ClearGPIOPin( HANDLE hDriver, DWORD PinNumber )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                DWORD BytesHandled;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                return DeviceIoControl( hDriver,&lt;/div&gt;
&lt;div&gt;                                IOCTL_CLEAR_GPIO,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;PinNumber,&lt;/div&gt;
&lt;div&gt;                                sizeof( PinNumber ),&lt;/div&gt;
&lt;div&gt;                                NULL,&lt;/div&gt;
&lt;div&gt;                                0,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;BytesHandled,&lt;/div&gt;
&lt;div&gt;                                NULL );&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;BOOL SetInputGPIOPin( HANDLE hDriver, DWORD PinNumber )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                DWORD BytesHandled;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                return DeviceIoControl( hDriver,&lt;/div&gt;
&lt;div&gt;                                IOCTL_SET_INPUT_GPIO,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;PinNumber,&lt;/div&gt;
&lt;div&gt;                                sizeof( PinNumber ),&lt;/div&gt;
&lt;div&gt;                                NULL,&lt;/div&gt;
&lt;div&gt;                                0,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;BytesHandled,&lt;/div&gt;
&lt;div&gt;                                NULL );&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;BOOL SetOutputGPIOPin( HANDLE hDriver, DWORD PinNumber )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                DWORD BytesHandled;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                return DeviceIoControl( hDriver,&lt;/div&gt;
&lt;div&gt;                                IOCTL_SET_OUTPUT_GPIO,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;PinNumber,&lt;/div&gt;
&lt;div&gt;                                sizeof( PinNumber ),&lt;/div&gt;
&lt;div&gt;                                NULL,&lt;/div&gt;
&lt;div&gt;                                0,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;BytesHandled,&lt;/div&gt;
&lt;div&gt;                                NULL );&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;BOOL ReadGPIOPin( HANDLE hDriver, DWORD PinNumber )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                DWORD BytesHandled;&lt;/div&gt;
&lt;div&gt;                DWORD GPIOValue;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                DeviceIoControl( hDriver,&lt;/div&gt;
&lt;div&gt;                                IOCTL_READ_GPIO,&lt;/div&gt;
&lt;div&gt;                                &amp;amp;PinNumber,&lt;/div&gt;
&lt;div&gt;                                sizeof( PinNumber ),&lt;/div&gt;
&lt;div&gt;                                &amp;amp;GPIOValue,&lt;/div&gt;
&lt;div&gt;                                sizeof(GPIOValue),&lt;/div&gt;
&lt;div&gt;                                &amp;amp;BytesHandled,&lt;/div&gt;
&lt;div&gt;                                NULL );&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                return GPIOValue &amp;amp; 1;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;See how simple that was? And our application developers will love us for it because their code can be very simple. This code will even be easy for them to use from C# with a simple P/Invoke.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The sources file is straight forward for those of you using Platform Builder:&lt;/div&gt;
&lt;div&gt;TARGETNAME=GPIO_API&lt;/div&gt;
&lt;div&gt;TARGETTYPE=LIBRARY&lt;/div&gt;
&lt;div&gt;RELEASETYPE=PLATFORM&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;SOURCES= \&lt;/div&gt;
&lt;div&gt;                GPIO_API.c&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;INCLUDES=$(INCLUDES);..\Inc&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;To turn this into a DLL, simply change the TARGETTYPE to DYNLINK and add a def file.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; 
&lt;div style="margin: 0in 0in 10pt"&gt;Also see the articles in this series at: &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-writing-an-application-to-test-gpio-pins.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Writing an Application to Test GPIO Pins&lt;/font&gt;&lt;/a&gt; and &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-using-a-driver-to-readwrite-hardware-registers.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Using a Driver to Read/Write Hardware Registers&lt;/font&gt;&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141145.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141145.aspx</wfw:comment>
        <slash:comments>4</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141145.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141145.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Windows CE: Using a Driver to Read/Write Hardware Registers</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-using-a-driver-to-readwrite-hardware-registers.aspx" />
        <id>http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-using-a-driver-to-readwrite-hardware-registers.aspx</id>
        <published>2010-08-01T16:21:10-04:00:00</published>
        <updated>2011-06-10T11:25:16Z</updated>
        <content type="html">&lt;div style="margin: 0in 0in 10pt"&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; background: #d9d9d9; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="172" style="border-bottom: gray 2.25pt solid; border-left: #d9d9d9 2.25pt solid; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 200.35pt; padding-right: 5.4pt; border-top: #d9d9d9 2.25pt solid; border-right: gray 2.25pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal; margin: 0in 0in 0pt"&gt;   &lt;a href="http://eurotech-inc.com/Wince-code/GPIO_Example.asp"&gt;&lt;font color="#800080"&gt;&lt;strong&gt;Download GPIO Example driver and appplication source code&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;A recent discussion thread in the &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/winembplatdev/threads"&gt;&lt;font color="#800080"&gt;Windows Embedded Compact Platform Development&lt;/font&gt;&lt;/a&gt; forum made it clear to me that for new Windows CE Software Engineers doing something as simple as accessing a hardware register can be very difficult. In the old days, Windows CE 5.0 and before, it was very easy; write an application that allocates a virtual address and then read or write a register. The problem with that is that allowing applications to access registers is a serious security and system stability problem. So in Windows CE 6.0 Microsoft fixed that and now only the kernel or kernel mode drivers can access hardware registers.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;In the discussion thread, I suggested that the solution is to use my Driver Shell as a starting point to added code to access the CPU GPIO registers. In this article, I will do just that and then follow up with a series of articles that show how to use the driver to read and write GPIO pins using an set of wrapper APIs and an application.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I have discussed stream interface drivers in previous articles (see &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/06/09/windows-ce-a-stream-interface-shell.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: A Stream Interface Driver Shell&lt;/font&gt;&lt;/a&gt;, &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/07/07/windows-ce-stream-interface-driver-dllentry.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Stream Interface Driver, DllEntry()&lt;/font&gt;&lt;/a&gt;, &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/08/07/windows-ce-stream-interface-driver-xxx_init.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Stream Interface Driver, XXX_Init()&lt;/font&gt;&lt;/a&gt;, and &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2008/08/13/windows-ce-stream-interface-driver-power-management.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Stream Interface Driver Power Management&lt;/font&gt;&lt;/a&gt;). In those articles I developed a driver that doesn’t actually do anything that I call Driver Shell. Driver Shell is a handy starting point for developing a stream interface driver because it includes the necessary functions, bib and reg files for creating a driver that will successfully be loaded by the device manager. I started by downloading the Driver Shell source code from this blog’s &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2009/10/09/downloads.aspx"&gt;&lt;font color="#800080"&gt;Downloads&lt;/font&gt;&lt;/a&gt; page and modify the driver to add control of reading pin state, writing pin state, and setting pin direction.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;But I am getting ahead of myself; we need some hardware to use. For this example, I will use some (almost) imaginary CPU because I don’t want this discussion to be about any specific CPU, but about the driver. Although I have tested the driver on a specific CPU.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The imaginary CPU has 32 GPIO pins. All of the GPIO pins can be used as input or output, and therefore can be read and written as well as the direction of the pin can be set. The following is a brief description of the registers:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;b&gt;&lt;span style="line-height: 115%; font-size: 12pt"&gt;ReadReg&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Physical Address: 40E0_0008
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; margin: auto auto auto 20.25pt; border-collapse: collapse; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="42" style="border-bottom: #d4d0c8; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 31.8pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: #d4d0c8; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt; &lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img alt="" width="706" height="115" src="/images/geekswithblogs_net/BruceEitman/8095/GPIO_Example/ReadReg.JPG" /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Bits&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Access&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Pin Name&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&amp;lt;0..31&amp;gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;R&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;LEVELx&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;GPIO Pin Level ‘x’ (where x = 0 to 31)&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;This read-only field indicates the current value of each GPIO.&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;0 = Pin state is low.&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;1 = Pin state is high.&lt;/span&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;b&gt;&lt;span style="line-height: 115%; font-size: 14pt"&gt;DirectionReg &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Physical Address: 40E0_0010&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img alt="" width="694" height="116" src="/images/geekswithblogs_net/BruceEitman/8095/GPIO_Example/DirectionReg.JPG" /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Bits&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Access&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Pin Name&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&amp;lt;0..31&amp;gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;R/W&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;DIRx&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;GPIO Pin Direction ‘x’ (where x = 0 to 31)&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;This field defines the direction of the GPIO pins.&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;0 = Pin is an input.&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;1 = Pin is an output&lt;/span&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;b&gt;&lt;span style="line-height: 115%; font-size: 14pt"&gt;SetReg &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Physical Address: 40E0_0018&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img alt="" width="690" height="113" src="/images/geekswithblogs_net/BruceEitman/8095/GPIO_Example/SetReg.JPG" /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Bits&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Access&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Pin Name&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&amp;lt;0..31&amp;gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;W&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;SETx&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;GPIO Pin SEt ‘x’ (where x = 0 to 31)&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;This field sets the output level of GPIO pins&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;0 = no change to pin state&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;1 = Pin state is driven high&lt;/span&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;&lt;b&gt;&lt;span style="line-height: 115%; font-size: 14pt"&gt;ClearReg &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Physical Address: 40E0_0020&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img alt="" width="707" height="120" src="/images/geekswithblogs_net/BruceEitman/8095/GPIO_Example/ClearReg.JPG" /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="0" style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Bits&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Access&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Pin Name&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; background: #cccccc; border-top: black 1pt solid; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td valign="top" width="83" style="border-bottom: black 1pt solid; border-left: black 1pt solid; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 62.6pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&amp;lt;0..31&amp;gt;&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="90" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 67.5pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;W&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="120" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 1.25in; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;CLEARx&lt;/div&gt;
            &lt;/td&gt;
            &lt;td valign="top" width="345" style="border-bottom: black 1pt solid; border-left: #d4d0c8; padding-bottom: 0in; background-color: transparent; padding-left: 5.4pt; width: 258.7pt; padding-right: 5.4pt; border-top: #d4d0c8; border-right: black 1pt solid; padding-top: 0in"&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;GPIO Pin CLEAR ‘x’ (where x = 0 to 31)&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;This field clears the output level of GPIO pins&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;0 = no change to pin state&lt;/span&gt;&lt;/div&gt;
            &lt;div style="line-height: normal"&gt;&lt;span style="font-size: 8pt"&gt;1 = Pin state is driven low&lt;/span&gt;&lt;/div&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;So the first step in developing code in the Driver Shell to access these registers is to define a data structure that matches the registers. The following GPIO_REGISTERS does that.&lt;/div&gt;
&lt;div&gt;typedef struct _GPIO_REGISTERS_&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;    volatile DWORD ReadReg;&lt;/div&gt;
&lt;div&gt;    DWORD Reserved2[2];&lt;/div&gt;
&lt;div&gt;    volatile DWORD DirectionReg;&lt;/div&gt;
&lt;div&gt;    DWORD Reserved3[2];&lt;/div&gt;
&lt;div&gt;    volatile DWORD SetReg;&lt;/div&gt;
&lt;div&gt;    DWORD Reserved4[2];&lt;/div&gt;
&lt;div&gt;    volatile DWORD ClearReg;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;} GPIO_REGISTERS;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Note that the registers are in the structure ordered by their physical addresses, and that some filler variables have been added to place the registers at the correct offset from the address of the first register.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;To access the registers, what we need is a pointer to BPIO_REGISTERS that points to the address of the ReadReg. Well that isn’t exactly true is it? We need it to point to a virtual address that maps to the physical address of ReadReg. I started by adding the pointer to the DRIVERSHELL_CONTEXT structure. The DRIVERSHELL_CONTEXT structure is used by the driver to keep track of instance data and is returned to the device manager by XXX_Init().&lt;/div&gt;
&lt;div&gt;typedef struct _DRIVERSHELL_CONTEXT&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                DWORD Instance;&lt;/div&gt;
&lt;div&gt;                CEDEVICE_POWER_STATE CurrentPowerState;&lt;/div&gt;
&lt;div&gt;                HANDLE hDDKPower;&lt;/div&gt;
&lt;div&gt;                GPIO_REGISTERS *pGPIO;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;} DRIVERSHELL_CONTEXT;&lt;/div&gt;
&lt;div&gt;Then the next step is to allocate a virtual address for the GPIO_REGISTERS structure. This is done in XXX_Init() using MmMapIoSpace(), the chages are in green below:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;DWORD XXX_Init(ULONG   RegistryPath)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                HKEY hKey;&lt;/div&gt;
&lt;div&gt;                DRIVERSHELL_CONTEXT *pDriverContext;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                PHYSICAL_ADDRESS physicalAddress;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                RETAILMSG( 1, (TEXT("XXX_Init\n")));&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                pDriverContext = LocalAlloc( LMEM_FIXED, sizeof( DRIVERSHELL_CONTEXT ));&lt;/div&gt;
&lt;div&gt;                if( pDriverContext == NULL )&lt;/div&gt;
&lt;div&gt;                {&lt;/div&gt;
&lt;div&gt;                                RETAILMSG( 1, (TEXT("XXX_Init failed, unable to allocate driver context\n")));&lt;/div&gt;
&lt;div&gt;                                return FALSE;&lt;/div&gt;
&lt;div&gt;                }&lt;/div&gt;
&lt;div&gt;               &lt;/div&gt;
&lt;div&gt;                hKey = OpenDeviceKey((LPCTSTR)RegistryPath);&lt;/div&gt;
&lt;div&gt;                if ( !hKey ) {&lt;/div&gt;
&lt;div&gt;                                RETAILMSG(1, (TEXT("Failed to open devkeypath,\r\n")));&lt;/div&gt;
&lt;div&gt;                }&lt;/div&gt;
&lt;div&gt;                else&lt;/div&gt;
&lt;div&gt;                {&lt;/div&gt;
&lt;div&gt;                                DWORD Type = REG_DWORD;&lt;/div&gt;
&lt;div&gt;                                DWORD Data;&lt;/div&gt;
&lt;div&gt;                                DWORD DataSize = sizeof( DWORD );&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                                // Read values from registry if needed&lt;/div&gt;
&lt;div&gt;                                if( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("DeviceArrayIndex"), NULL, &amp;amp;Type, (LPBYTE)&amp;amp;Data, &amp;amp;DataSize ) )&lt;/div&gt;
&lt;div&gt;                                                pDriverContext-&amp;gt;Instance = Data;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                                RETAILMSG( 1, (TEXT("pDriverContext-&amp;gt;Instance %d\n"), pDriverContext-&amp;gt;Instance));&lt;/div&gt;
&lt;div&gt;                                RegCloseKey (hKey);&lt;/div&gt;
&lt;div&gt;                }&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                // Init Power management&lt;/div&gt;
&lt;div&gt;                pDriverContext-&amp;gt;CurrentPowerState = D0;&lt;/div&gt;
&lt;div&gt;                pDriverContext-&amp;gt;hDDKPower = DDKPwr_Initialize(XXX_SetPowerState, (DWORD)pDriverContext , TRUE, 1000 );&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                physicalAddress.QuadPart = GPIO_REGISTERS_BASE_PHYSICAL;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                pDriverContext-&amp;gt;pGPIO = (GPIO_REGISTERS *)MmMapIoSpace(physicalAddress, sizeof(GPIO_REGISTERS), FALSE);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                if (pDriverContext-&amp;gt;pGPIO == NULL )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                                RETAILMSG(TRUE, (_T("XXX_Init failed to allocate pGPIO (%d)\r\n"), GetLastError()));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                                XXX_Deinit( pDriverContext );&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                                return (DWORD)NULL;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;                return (DWORD)pDriverContext;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;The address used to initialize the physical address is the address of the ReadReg, which is defined to as:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;#define GPIO_REGISTERS_BASE_PHYSICAL (0x40E00008)&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;I suppose that you probably want to jump in now and start reading and writing registers, but we have some more to do first, we need to update XXX_Deinit() to free the virtual addresses that we just allocated – no nasty memory leaks here. The changes to XXX_Deinit() are in green below:&lt;/div&gt;
&lt;div&gt;BOOL XXX_Deinit( DWORD hDeviceContext )&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;                DRIVERSHELL_CONTEXT *pDriverContext = (DRIVERSHELL_CONTEXT *)hDeviceContext;&lt;/div&gt;
&lt;div&gt;                if( pDriverContext )&lt;/div&gt;
&lt;div&gt;                {&lt;/div&gt;
&lt;div&gt;                    if( pDriverContext-&amp;gt;hDDKPower != INVALID_HANDLE_VALUE )&lt;/div&gt;
&lt;div&gt;                                                DDKPwr_Deinitialize(pDriverContext-&amp;gt;hDDKPower);&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                                if( pDriverContext-&amp;gt;pGPIO )&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="color: #00b050"&gt;                                                MmUnmapIoSpace( pDriverContext-&amp;gt;pGPIO, sizeof(GPIO_REGISTERS) ); &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;                                LocalFree( pDriverContext );&lt;/div&gt;
&lt;div&gt;                }&lt;/div&gt;
&lt;div&gt;                return TRUE;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;}&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;So now we have the pointer to a data structure that is mapped to the GPIO registers. To access the registers we just use the pointer, like this:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;DWORD State;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;State = pDriverContext-&amp;gt;pGPIO-&amp;gt;ReadReg;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;XXX_Read() and XXX_Write() might seem like good candidates for developing code to read and write the registers, but to me they would be awkward. Instead I am going to use XXX_IOControl(). I have also decided that having IOCTLS to handle pins makes more sense than accessing the entire registers.   One reason to handle pins is that the API can be used without change even if the number of pins increases to greater than 32 on other processors. This way transitioning from one board/CPU to another will be easier, although not pain free.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;To start with, add some code to read the state of a pin. We know from the code above how to read the ReadReg, we just need to add some error handling and mask off the pin that was requested:&lt;/div&gt;
&lt;div&gt;                                case IOCTL_READ_GPIO:&lt;/div&gt;
&lt;div&gt;                                                if( pBufOut &amp;amp;&amp;amp; pBufIn &amp;amp;&amp;amp; *pBufIn &amp;lt; 32 )&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                DWORD *pPinNumber = (DWORD *)pBufIn;&lt;/div&gt;
&lt;div&gt;                                                                DWORD *pPinValue = (DWORD *)pBufOut;&lt;/div&gt;
&lt;div&gt;                                                                RETAILMSG( 1, (TEXT("Read GPIO pin %d\r\n"), *pPinNumber ));&lt;/div&gt;
&lt;div&gt;                                                                *pPinValue = (pDriverContext-&amp;gt;pGPIO-&amp;gt;ReadReg &amp;amp; ( 1 &amp;lt;&amp;lt; *pPinNumber )) &amp;gt;&amp;gt; *pPinNumber;&lt;/div&gt;
&lt;div&gt;                                                                RetVal = TRUE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                else&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                SetLastError(ERROR_INVALID_PARAMETER);&lt;/div&gt;
&lt;div&gt;                                                                RetVal = FALSE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;                                                break;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;That is very simple, read the register, mask off the pin requested, then shit the result down so that we can return zero or one. The other IOCLTS are similar:&lt;/div&gt;
&lt;div&gt;                                case IOCTL_SET_GPIO:&lt;/div&gt;
&lt;div&gt;                                                if( pBufIn &amp;amp;&amp;amp; *pBufIn &amp;lt; 32 )&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                DWORD *pPinNumber = (DWORD *)pBufIn;&lt;/div&gt;
&lt;div&gt;                                                                RETAILMSG( 1, (TEXT("Set GPIO pin %d\r\n"), *pPinNumber ));&lt;/div&gt;
&lt;div&gt;                                                                pDriverContext-&amp;gt;pGPIO-&amp;gt;SetReg = ( 1 &amp;lt;&amp;lt; *pPinNumber );&lt;/div&gt;
&lt;div&gt;                                                                RetVal = TRUE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                else&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                SetLastError(ERROR_INVALID_PARAMETER);&lt;/div&gt;
&lt;div&gt;                                                                RetVal = FALSE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                break;&lt;/div&gt;
&lt;div&gt;                                case IOCTL_CLEAR_GPIO:&lt;/div&gt;
&lt;div&gt;                                                if( pBufIn &amp;amp;&amp;amp; *pBufIn &amp;lt; 32 )&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                DWORD *pPinNumber = (DWORD *)pBufIn;&lt;/div&gt;
&lt;div&gt;                                                                RETAILMSG( 1, (TEXT("Clear GPIO pin %d\r\n"), *pPinNumber ));&lt;/div&gt;
&lt;div&gt;                                                                pDriverContext-&amp;gt;pGPIO-&amp;gt;ClearReg = ( 1 &amp;lt;&amp;lt; *pPinNumber );&lt;/div&gt;
&lt;div&gt;                                                                RetVal = TRUE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                else&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                SetLastError(ERROR_INVALID_PARAMETER);&lt;/div&gt;
&lt;div&gt;                                                                RetVal = FALSE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                break;&lt;/div&gt;
&lt;div&gt;                                case IOCTL_SET_OUTPUT_GPIO:&lt;/div&gt;
&lt;div&gt;                                                if( pBufIn &amp;amp;&amp;amp; *pBufIn &amp;lt; 32 )&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                DWORD *pPinNumber = (DWORD *)pBufIn;&lt;/div&gt;
&lt;div&gt;                                                                RETAILMSG( 1, (TEXT("Set Output GPIO pin %d\r\n"), *pPinNumber ));&lt;/div&gt;
&lt;div&gt;                                                                pDriverContext-&amp;gt;pGPIO-&amp;gt;DirectionReg |= ( 1 &amp;lt;&amp;lt; *pPinNumber );&lt;/div&gt;
&lt;div&gt;                                                                RetVal = TRUE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                else&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                SetLastError(ERROR_INVALID_PARAMETER);&lt;/div&gt;
&lt;div&gt;                                                                RetVal = FALSE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                break;&lt;/div&gt;
&lt;div&gt;                                case IOCTL_SET_INPUT_GPIO:&lt;/div&gt;
&lt;div&gt;                                                if( pBufIn &amp;amp;&amp;amp; *pBufIn &amp;lt; 32 )&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                DWORD *pPinNumber = (DWORD *)pBufIn;&lt;/div&gt;
&lt;div&gt;                                                                RETAILMSG( 1, (TEXT("Set Input GPIO pin %d\r\n"), *pPinNumber ));&lt;/div&gt;
&lt;div&gt;                                                                pDriverContext-&amp;gt;pGPIO-&amp;gt;DirectionReg &amp;amp;= ~( 1 &amp;lt;&amp;lt; *pPinNumber );&lt;/div&gt;
&lt;div&gt;                                                                RetVal = TRUE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div&gt;                                                else&lt;/div&gt;
&lt;div&gt;                                                {&lt;/div&gt;
&lt;div&gt;                                                                SetLastError(ERROR_INVALID_PARAMETER);&lt;/div&gt;
&lt;div&gt;                                                                RetVal = FALSE;&lt;/div&gt;
&lt;div&gt;                                                }&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;                                                break;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Now we have a driver that can read, write and change direction of the GPIO pins. You could certainly go from here and write code to use this driver (see &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2009/03/21/windows-ce-accessing-a-stream-interface-driver-from-an-application.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Accessing a Stream Interface Driver from an Application&lt;/font&gt;&lt;/a&gt;) but instead of having applications directly access the driver, the next article will develop an API to wrapper the driver and simplify application development.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; 
&lt;div style="margin: 0in 0in 10pt"&gt;Also see the articles in this series at: &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-developing-an-api-to-access-a-driver.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Developing an API to Access a Driver&lt;/font&gt;&lt;/a&gt; and &lt;a href="http://geekswithblogs.net/BruceEitman/archive/2010/08/01/windows-ce-writing-an-application-to-test-gpio-pins.aspx"&gt;&lt;font color="#800080"&gt;Windows CE: Writing an Application to Test GPIO Pins&lt;/font&gt;&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal" align="center"&gt;&lt;span style="font-size: 9pt"&gt;Copyright © 2010 – Bruce Eitman&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center; line-height: normal; margin: 0in 0in 10pt" align="center"&gt;&lt;span style="font-size: 9pt"&gt;All Rights Reserved&lt;/span&gt;&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;&lt;img src="http://geekswithblogs.net/BruceEitman/aggbug/141144.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/BruceEitman/comments/141144.aspx</wfw:comment>
        <slash:comments>11</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/BruceEitman/comments/commentRss/141144.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/BruceEitman/services/trackbacks/141144.aspx</trackback:ping>
    </entry>
</feed>
