To successfully enumerate the available flash cards, we will need to implement a couple of APIs using DllImport. 
        [DllImport("coredll.dll", SetLastError = false)]
        public static extern bool FindClose(IntPtr hFindFile);
        [DllImport("note_prj.dll", SetLastError = false)]
        public static extern IntPtr FindFirstFlashCard(byte[] bFindFlashData);
        [DllImport("note_prj.dll", SetLastError = false)]
        public static extern bool FindNextFlashCard(IntPtr hFlashCard, byte[] bFindFlashData);
We also need to enum some of the FILE_ATTRIBUTE_xxx values available in Winbase.h. 
        public enum FILE_ATTRIBUTE
        {
            READONLY = 0x1
            , HIDDEN = 0x2
            , SYSTEM = 0x4
            , DIRECTORY = 0x10
            , ARCHIVE = 0x20
            , INROM = 0x40
            , NORMAL = 0x80
            , TEMPORARY = 0x100
            , SPARSE_FILE = 0x200
            , REPARSE_POINT = 0x400
            , COMPRESSED = 0x800
            , ROMSTATICREF = 0x1000
            , ROMMODULE = 0x2000
            , ENCRYPTED = 0x4000
        }
Next, we need to implement the WIN32_FIND_DATA structure. As you can see in our import of FindFirstFlashCard we don't actually pass an instance of the win32_find_data structure to the API, but instead we pass a byte buffer that are later converted to a win32_find_data structure. I've added a couple of properties to the structure to make working with file attributes a bit more .Net-ish. As you can see, the byte-to-structure-code is located in the constructur the same way as we did with the notification structures last week. 
        [StructLayout(LayoutKind.Sequential)]
        public class WIN32_FIND_DATA
        {
            public uint FileAttributes;
            private FILETIME ftCreationTime;
            private FILETIME ftLastAccessTime;
            private FILETIME ftLastWriteTime;
            public DateTime dtCreationTime;
            public DateTime dtLastAccessTime;
            public DateTime dtLastWriteTime;
            public uint nFileSizeHigh;
            public uint nFileSizeLow;
            public uint dwOID;
            public string FileName;
            public bool IsReadOnly;
            public bool IsHidden;
            public bool IsSystem;
            public bool IsDirectory;
            public bool IsArchive;
            public bool IsInRom;
            public bool IsNormal;
            public bool IsTemporary;
            public bool IsSparseFile;
            public bool HasReparsePoint;
            public bool IsCompressed;
            public bool HasRomStaticRef;
            public bool IsRomModule;
            public bool IsEncrypted;
            
            public WIN32_FIND_DATA()
            {
            }
            public WIN32_FIND_DATA(byte[] Buf, uint Size)
            {
                int Index = 0;
                int iEndOfString = 0;
                System.Text.UnicodeEncoding enc = new UnicodeEncoding();
                this.FileAttributes = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.ftCreationTime.dwLowDateTime = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.ftCreationTime.dwHighDateTime = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.ftLastAccessTime.dwLowDateTime = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.ftLastAccessTime.dwHighDateTime = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.ftLastWriteTime.dwLowDateTime = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.ftCreationTime.dwHighDateTime = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.nFileSizeHigh = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.nFileSizeLow = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                this.dwOID = BitConverter.ToUInt32(Buf, Index);
                Index += 4;
                iEndOfString = WinCE.findEndOfString(Buf, Index, (int)Size);
                this.FileName = enc.GetString(Buf, Index, iEndOfString - Index - 2);
                Index = iEndOfString;
                this.IsReadOnly = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.READONLY);
                this.IsHidden = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.HIDDEN);
                this.IsSystem = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.SYSTEM);
                this.IsDirectory = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.DIRECTORY);
                this.IsArchive = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ARCHIVE);
                this.IsInRom = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.INROM);
                this.IsNormal = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.NORMAL);
                this.IsTemporary = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.TEMPORARY);
                this.IsSparseFile = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.SPARSE_FILE);
                this.HasReparsePoint = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.REPARSE_POINT);
                this.IsCompressed = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.COMPRESSED);
                this.HasRomStaticRef = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ROMSTATICREF);
                this.IsRomModule = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ROMMODULE);
                this.IsEncrypted = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ENCRYPTED);
                this.dtCreationTime = DateTime.FromFileTime(this.ftCreationTime.GetAsLong());
                this.dtLastAccessTime = DateTime.FromFileTime(this.ftLastAccessTime.GetAsLong());
                this.dtLastWriteTime = DateTime.FromFileTime(this.ftLastWriteTime.GetAsLong());
            }
        }
Now that's a lot of code! 
The win32_find_data structure has a couple of instances of the FILETIME structure. This is a simple structure consisting of just two 32 bit unsigned integer values and a function that returns a 64 bit unsigned integer. 
    [StructLayout(LayoutKind.Sequential)]
    public struct FILETIME
    {
        public uint dwLowDateTime;
        public uint dwHighDateTime;
        public long GetAsLong()
        {
            long lRet;
            lRet = dwHighDateTime;    
            lRet = lRet << 32;
            lRet = dwLowDateTime;        
            return lRet;
        }
    }
Returning the filetime structure as a 64 bit integer value makes it possible for us to directly convert it to a .Net DateTime structure using the static DateTime.GetFromFileTime(long lFileTime) function. 
this.dtCreationTime = DateTime.FromFileTime(this.ftCreationTime.GetAsLong());
Next up is a simple function that enumerates all flash cards and outputs the path using System.Diagnostics.Trace.WriteLine(string sVal). 
            FileSystem.WIN32_FIND_DATA FindData;
            Byte[] Buf = new byte[295]; // Struct is 40 bytes + MAX_PATH (255 bytes) = 295 bytes
            IntPtr hFlashCard = WinCE.FileSystem.FileAppMgmt.FindFirstFlashCard(Buf);
            if (hFlashCard != IntPtr.Zero)
            {
                FindData = new FileSystem.WIN32_FIND_DATA(Buf, 295);
                System.Diagnostics.Trace.WriteLine("Filename:" + FindData.FileName);
                Buf = new byte[295];
                while (WinCE.FileSystem.FileAppMgmt.FindNextFlashCard(hFlashCard, Buf))
                {
                    FindData = new FileSystem.WIN32_FIND_DATA(Buf, 295);
                    System.Diagnostics.Trace.WriteLine("Filename:" + FindData.FileName);
                }
                WinCE.FileSystem.FindClose(hFlashCard);
                System.Diagnostics.Trace.WriteLine("Succeeded");
            }
            else
            {
                System.Diagnostics.Trace.WriteLine("Failed");
            }
And that's about it.. Check back tomorrow when we look closer on a couple other file system related APIs. 
 
Very nice. Can I use this code in my app?
SvaraRadera