*** empty log message ***
authorcharles <charles>
Fri, 8 Nov 2002 07:30:00 +0000 (07:30 +0000)
committercharles <charles>
Fri, 8 Nov 2002 07:30:00 +0000 (07:30 +0000)
wince/sources [new file with mode: 0644]
wince/yaffsfsd.c [new file with mode: 0644]
wince/yfsd.def [new file with mode: 0644]
wince/ynandif.c [new file with mode: 0644]
wince/ynandif.h [new file with mode: 0644]

diff --git a/wince/sources b/wince/sources
new file mode 100644 (file)
index 0000000..86ca4d2
--- /dev/null
@@ -0,0 +1,26 @@
+!IF 0\r
+\r
+The YAFFS FSD for WinCE\r
+\r
+\r
+!ENDIF\r
+\r
+!if "$(ODO_NODISPLAY)" == "1"\r
+SKIPBUILD=1\r
+!endif\r
+\r
+RELEASETYPE=PLATFORM\r
+\r
+TARGETNAME=YFSD\r
+TARGETTYPE=DYNLINK\r
+TARGETLIBS=                                             \\r
+    C:\WINCE300\PUBLIC\COMMON\OAK\lib\arm\Sa1100\ce\retail\fsdmgr.lib \\r
+    $(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib    \\r
+\r
+CDEFINES=  $(CDEFINES) -DCONFIG_YAFFS_WINCE -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM \r
+\r
+\r
+SOURCES=  yaffs_guts.c nand_ecc.c yaffsfsd.c ynandif.c \r
+\r
+    \r
+\r
diff --git a/wince/yaffsfsd.c b/wince/yaffsfsd.c
new file mode 100644 (file)
index 0000000..dc64c1a
--- /dev/null
@@ -0,0 +1,2442 @@
+/*\r
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.\r
+ * yaffsfsd.c: The FSD layer for the WinCE version of YAFFS.\r
+ *\r
+ * Copyright (C) 2002 Trimble Navigation Ltd.\r
+ *\r
+ * Created by Charles Manning <charles.manning@trimble.co.nz>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 as\r
+ * published by the Free Software Foundation.\r
+ *\r
+ * This program is distributed in the hope that it will be useful, \r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of \r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \r
+ * General Public License for more details. You should have received a \r
+ * copy of the GNU General Public License along with this program; \r
+ * if not, write to the Free Software Foundation, Inc., \r
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \r
+ *\r
+ * $Id: yaffsfsd.c,v 1.1 2002-11-08 07:30:00 charles Exp $\r
+ */
+#include <windows.h>
+#include <extfile.h>
+#include <yaffs_guts.h>
+#include <ynandif.h>
+
+#define MAX_WIN_FILE   200
+#define YFSD_NAME_LENGTH 128
+#define YFSD_FULL_PATH_NAME_SIZE 500
+
+
+#define YFSD_DISK_NAME L"Disk"
+#define YFSD_BOOT_NAME L"Boot"
+
+#define PARTITION_START_NUMBER (1280)          
+
+#define MSGSTATE 1
+//#define DISABLE_BOOT_PARTITION\r
+\r
+unsigned yaffs_traceMask=0xffffffff;
+
+
+typedef struct
+{
+       yaffs_Device dev;
+       DWORD   hdsk;
+       DWORD    mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
+       BOOL    isMounted;
+       BOOL    configured;
+//     DWORD   guard0[100];
+//     DWORD   guard1[100];
+       SHELLFILECHANGEFUNC_t shellFunction;
+       PWSTR volName;
+} yfsd_Volume;
+
+typedef struct 
+{
+       yaffs_Object *obj;
+       DWORD offset;
+       BOOL isopen;
+       BOOL writePermitted;
+       BOOL dirty;
+       WCHAR *fullName;
+       yfsd_Volume *myVolume;
+
+}      yfsd_WinFile;
+
+struct yfsd_FoundObjectStruct
+{
+  yaffs_Object *obj;
+  struct yfsd_FoundObjectStruct *next;
+};
+
+typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
+
+typedef struct 
+{
+       yaffs_Object *dir;
+       char pattern[YFSD_NAME_LENGTH+1];
+       yaffs_FoundObject *foundObjects;
+}      yfsd_WinFind;
+
+
+
+#define PSEARCH yfsd_WinFind*
+
+#define PVOLUME yfsd_Volume*
+#define PFILE   yfsd_WinFile*
+
+#define FSD_API        YFSD
+
+#include <fsdmgr.h>
+
+
+static yfsd_Volume disk_volume;
+static yfsd_Volume boot_volume;
+
+static CRITICAL_SECTION yaffsLock;
+static CRITICAL_SECTION winFileLock;
+
+static int yaffsLockInited = 0;
+
+static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
+
+#if 0
+static yfsd_SetGuards(void)
+{
+       int i;
+       for(i = 0; i < 100; i++)
+       {
+               yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
+       }
+}
+
+static void yfsd_CheckGuards(void)
+{
+       int i;
+       int found;
+       for(i = found = 0; i < 100 && !found; i++)
+       {
+                       if(yfsd_volume.guard0[i] != i)
+                       {
+                                       RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
+                                       found = 1;
+                       }
+                       if(yfsd_volume.guard1[i] != i)
+                       {
+                                       RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
+                                       found = 1;
+                       }
+       }
+}
+#endif
+
+void yfsd_LockWinFiles(void)
+{
+       //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
+       EnterCriticalSection(&winFileLock);
+}
+void yfsd_UnlockWinFiles(void)
+{
+       //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
+       LeaveCriticalSection(&winFileLock);
+}
+
+int lockwaits;
+
+void yfsd_LockYAFFS(void)
+{
+       //yfsd_CheckGuards();
+       //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
+       lockwaits++;
+       EnterCriticalSection(&yaffsLock);
+       //RETAILMSG (MSGSTATE, (L" locked\r\n"));
+}
+void yfsd_UnlockYAFFS(void)
+{
+       //yfsd_CheckGuards();
+       //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
+       LeaveCriticalSection(&yaffsLock);
+       lockwaits--;
+       //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
+}
+
+
+void yfsd_InitialiseWinFiles(void)
+{
+       int i;
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
+
+       InitializeCriticalSection(&winFileLock);
+
+       yfsd_LockWinFiles();
+       for(i = 0; i < MAX_WIN_FILE; i++)
+       {
+                       yfsd_winFile[i].isopen = 0;
+       }
+       yfsd_UnlockWinFiles();
+}
+
+yfsd_WinFile * yfsd_GetWinFile(void)
+{
+       int i;
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
+
+       yfsd_LockWinFiles();
+
+       for(i = 0; i < MAX_WIN_FILE; i++)
+       {
+               if(!yfsd_winFile[i].isopen)
+               {
+                       yfsd_winFile[i].isopen = 1;
+                       yfsd_winFile[i].writePermitted = 0;
+                       yfsd_winFile[i].dirty = 0;
+                       yfsd_winFile[i].fullName = NULL;
+                       yfsd_winFile[i].obj = NULL;
+
+                       yfsd_UnlockWinFiles();
+                       return &yfsd_winFile[i];
+               }
+       }
+
+       yfsd_UnlockWinFiles();
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
+
+       return NULL;
+}
+
+void yfsd_PutWinFile(yfsd_WinFile *f)
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
+       yfsd_LockWinFiles();
+       f->isopen = 0;
+       f->obj = NULL;
+       if(f->fullName)
+       {
+               free(f->fullName);
+               f->fullName = NULL;
+       }
+
+       yfsd_UnlockWinFiles();
+}
+
+
+
+void yfsd_FlushAllFiles(void)
+{
+       int i;
+       RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
+
+       yfsd_LockYAFFS();
+       yfsd_LockWinFiles();
+       for(i = 0; i < MAX_WIN_FILE; i++)
+       {
+               if(yfsd_winFile[i].isopen &&
+                  yfsd_winFile[i].obj)
+               {
+                       yaffs_FlushFile(yfsd_winFile[i].obj);
+               }
+       }
+       yfsd_UnlockWinFiles();
+       yfsd_UnlockYAFFS();
+}
+
+PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
+{
+
+       // todo check for bounds
+       wcscpy(fpn,L"\\");
+       wcscat(fpn,vol->volName);
+       if(pathName[0] != '\\')
+       {
+               wcscat(fpn,L"\\");
+       }
+       wcscat(fpn,pathName);
+
+       return fpn;
+
+}
+
+
+// FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
+\r
+void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
+{
+       
+       wft->dwLowDateTime = target[0];
+       wft->dwHighDateTime = target[1];
+
+}
+
+void yfsd_NullWinFileTime(FILETIME *wft)
+{
+       wft->dwLowDateTime = 0;
+       wft->dwHighDateTime = 0;
+}
+
+void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
+{
+       target[0] = wft->dwLowDateTime;
+       target[1] = wft->dwHighDateTime;
+}
+
+void  yfsd_WinFileTimeNow(__u32 target[2])
+{
+       SYSTEMTIME st;
+       FILETIME ft;
+
+       GetSystemTime(&st);
+       SystemTimeToFileTime(&st,&ft);
+       yfsd_WinFileTimeToU32s(&ft,target);
+}
+
+// Cut down the name to the parent directory, then inform the shell of
+// a change to the directory.
+void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
+{
+       WCHAR str[500];
+       int i;
+       wcscpy(str,fullPathName);
+
+       i = wcslen(str) - 1;
+       
+       if(i > 0)
+       {
+               str[i] = 0;
+               i--;
+       }
+
+       // Curveball if the name is a directory (ie. we're doing an update of
+       // a directory because we added a directory item). , then it might end in a \
+       // which we must toss first
+       if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
+       {
+               str[i] = 0;
+               i--;
+       }
+
+       // Ok, now strip back...
+
+       while(i >= 0 && str[i] != '\\' && str[i] != '/')
+       {
+               str[i] = 0;
+               i--;
+       }
+
+       if(pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_UPDATEDIR;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)str;
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = 0;
+                       yfsd_NullWinFileTime(&fc.ftModified);
+                       fc.nFileSize = 0;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
+
+       }
+
+
+}
+\r
+\r
+// Minimal name test for now\r
+BOOL yfsd_NameIsValid (const char *name)\r
+{\r
+       int length = strlen(name);\r
+\r
+       return (length > 0 && length <= YFSD_NAME_LENGTH);\r
+\r
+}
+
+// File attributes:
+// Wince understands the following attributes of any use to YAFFS:
+//  
+//   ARCHIVE
+//   HIDDEN
+//   READONLY
+//   SYSTEM
+//   TEMPORARY
+//
+//      Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
+//
+//   It also understands NORMAL. If no other flag is set, then set NORMAL.
+//   If any of the above are set, then NORMAL must **not** be set.
+//      Ignore this and the WinCE Explorer barfs the file.
+//
+//
+// in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
+\r
+// The following are valid ones we get presented with,\r
+// but must filter out the stuff we don't unserstand\r
+//#define FILE_ATTRIBUTE_READONLY             0x00000001  \r
+//#define FILE_ATTRIBUTE_HIDDEN               0x00000002  \r
+//#define FILE_ATTRIBUTE_SYSTEM               0x00000004  \r
+//#define FILE_ATTRIBUTE_DIRECTORY            0x00000010  \r
+//#define FILE_ATTRIBUTE_ARCHIVE              0x00000020  \r
+//#define FILE_ATTRIBUTE_INROM                           0x00000040\r
+//#define FILE_ATTRIBUTE_ENCRYPTED            0x00000040  \r
+//#define FILE_ATTRIBUTE_NORMAL               0x00000080  \r
+//#define FILE_ATTRIBUTE_TEMPORARY            0x00000100  \r
+//#define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200  \r
+//#define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400  \r
+//#define FILE_ATTRIBUTE_COMPRESSED           0x00000800  \r
+//#define FILE_ATTRIBUTE_OFFLINE              0x00001000  \r
+//#define FILE_ATTRIBUTE_ROMSTATICREF            0x00001000\r
+//#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000  \r
+//#define FILE_ATTRIBUTE_ROMMODULE                       0x00002000\r
+\r
+\r
+BOOL yfsd_CheckValidAttributes(DWORD attribs)\r
+{\r
+\r
+       RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));\r
+\r
+#if 0\r
+               // If NORMAL, then nothing else\r
+               if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)\r
+                       return FALSE;\r
+               if(attribs == FILE_ATTRIBUTE_NORMAL) \r
+                       return TRUE;\r
+#endif\r
+               // Check that the bits are in the valid set\r
+               if(attribs & ~(0x3FE7))\r
+                       return FALSE;\r
+\r
+               return TRUE;\r
+\r
+}
+DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
+{
+
+               DWORD result;
+               
+               result = obj->st_mode & \r
+                                       (FILE_ATTRIBUTE_READONLY | \r
+                                        FILE_ATTRIBUTE_ARCHIVE | \r
+                                        FILE_ATTRIBUTE_HIDDEN |\r
+                                        FILE_ATTRIBUTE_SYSTEM);
+\r
+               if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;\r
+
+               if(result & ~FILE_ATTRIBUTE_NORMAL)
+               { 
+                       result &= ~FILE_ATTRIBUTE_NORMAL;
+               }
+               else 
+               {
+                       result = FILE_ATTRIBUTE_NORMAL;
+               }
+\r
+
+               return result;
+}
+
+
+
+/*
+*      Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
+*      reached.  Characters are copied from input into output until the above stop
+*      condition is reached - output is then given a '\0'.  output must be at least
+*      as large as outSize
+*/
+static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
+{
+       int counter = 0;
+       char *t = output;
+       /* strip any starting \'s */
+       //RETAILMSG(1, (L"\r\nParsing.. "));
+       while (*input == '\\' || *input == '/') input++, counter++;
+
+       for (; counter < outSize - 1; counter++)
+       {
+               if (*input == '\0' ||
+                       ((*input == '\\' || *input == '/') && input[1] == '\0'))   // special case: if the string ends in a '\', then toss the '\'
+               {
+                       counter = -1;   // break & tell people we've run to the end
+                       break;
+               }
+               if (*input == '\\' || *input == '/')
+                       break;
+               //RETAILMSG(1, (L"%c", *input));
+               *output = (char) (*input);
+               input++;
+               output++;
+       }
+       *output++ = '\0';
+       *output  = '\0';
+//     RETAILMSG(1, (L"\r\nOut %a\r\n", t));
+       
+       return counter;
+}
+
+/*
+*      Since the notion of paths as WinCE sees them and as YAFFS sees them
+*      is different, we needed a helper function to search from the root of
+*      device along the string in path.  The processed pointer is set to where
+*      abouts in the string the function was able to search up to.
+*/
+yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
+{
+       // a buffer to keep the current chunk of path we're talking about it
+       char pathChunk[255];
+       int chunkSize;
+       int counter;
+       // the current object we are at
+       yaffs_Object *current;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
+       // start at the root of this device
+       current = yaffs_Root(device);\r
+       *processed = '\0';
+
+       do
+       {
+       //      parse chunks until we run out
+               chunkSize = parseToNextSlash(path, pathChunk, 255);
+//             RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
+               if (chunkSize == -1)
+                       break;
+       //      move the path pointer along
+               path += chunkSize;
+       //      try and find the next yaffs object by chunkname 
+               current = yaffs_FindObjectByName(current, pathChunk);
+               if (current == 0)
+               {
+                       processed[0] = '\0';
+                       return 0;
+               }
+       } while (1);
+
+       for (counter = 0; counter < length; counter++)
+       {
+               // Get the rest of the string
+               processed[counter] = pathChunk[counter];
+               if (pathChunk[counter] == '\0')
+                       break;
+       }
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
+
+       return current;
+}
+
+
+yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
+{
+       yaffs_Object *obj = NULL;
+       yaffs_Object *parent = NULL;
+       char name[YFSD_NAME_LENGTH+1];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
+
+       parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
+
+       if(parent && yfsd_NameIsValid(name))
+       {
+               obj = yaffs_FindObjectByName(parent,name);
+       }
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
+
+       return obj;
+}
+
+BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
+       vol->volName = volName;
+
+
+       yfsd_LockYAFFS();
+       
+       //Mount/initialise YAFFs here
+       ynandif_InitialiseNAND(&vol->dev);
+       
+       vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;
+       vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;
+       vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;
+       vol->dev.initialiseNAND = ynandif_InitialiseNAND;
+       vol->dev.startBlock = startBlock;
+       if (endBlock != -1)
+               vol->dev.endBlock = endBlock;
+
+       // nBlocks is set the total size of the disk, not the partition
+//     vol->dev.nBlocks = endBlock - startBlock + 1;
+
+//     qnand_EraseAllBlocks(&vol->dev);
+
+       yaffs_GutsInitialise(&vol->dev);
+       RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
+
+       RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",
+                           vol->dev.startBlock,vol->dev.endBlock,
+                                       vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));
+
+
+#if 0
+       for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
+       {
+                       switch(vol->dev.blockInfo[i].blockState)
+                       {
+                               case YAFFS_BLOCK_STATE_DEAD:
+               
+                                       RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
+                                       deadBlox++;
+                                       break;
+                               case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
+                               case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
+                               case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
+                               case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
+                               default:
+                                       RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
+                                       break;
+                       }
+       }
+
+       RETAILMSG(1, (L"Blocks dead  %d empty %d full %d allocating %d dirty %d\r\n",
+                           deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
+
+#endif
+
+       yfsd_UnlockYAFFS();
+
+       vol->isMounted = 1;
+       
+       vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
+
+       if(vol->mgrVolume)
+       {
+               return TRUE;
+       }
+       else
+       {
+               vol->isMounted = 0;
+               SetLastError(ERROR_OUTOFMEMORY);
+               return FALSE;
+       }       
+}
+
+
+BOOL YFSD_MountDisk(HDSK hdsk)
+{
+       int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
+       //int i;
+       // Called to mount a disk.
+       // NB THis call might happen redundantly.
+       //
+       //
+       // If yaffs is not initialised, then call the 
+       // initialisation function
+       //
+       RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
+
+       if (!yaffsLockInited)
+       {
+               InitializeCriticalSection(&yaffsLock);
+               yfsd_InitialiseWinFiles();
+               yaffsLockInited = 1;
+       }
+
+#ifdef DISABLE_BOOT_PARTITION
+       // Only want disk volume
+       YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
+
+       
+       if(disk_volume.isMounted)
+       {
+               return TRUE;
+       }
+#else
+       // Want both boot and disk
+       YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
+       YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
+
+       
+       if(disk_volume.isMounted && boot_volume.isMounted)
+       {
+               return TRUE;
+       }
+#endif
+
+       return FALSE;
+
+//     yfsd_SetGuards();
+
+       // todo - get name from registry
+
+}
+
+
+BOOL YFSD_UnmountDisk(HDSK hdsk)
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
+       
+       yfsd_FlushAllFiles();
+
+       yfsd_LockYAFFS();
+       yaffs_Deinitialise(&disk_volume.dev);
+       yaffs_Deinitialise(&boot_volume.dev);
+       yfsd_UnlockYAFFS();
+
+       FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
+       FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
+       return TRUE;
+}
+
+
+BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
+{
+       // security attributes are ignored (should be NULL)
+
+       yaffs_Object *newDir = NULL;
+       yaffs_Object *parent = NULL;
+       char name[YFSD_NAME_LENGTH+1];
+       ULONG objSize;
+       DWORD attribs;
+       unsigned modifiedTime[2];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
+
+       yfsd_LockYAFFS();
+
+       parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
+
+       if(parent && yfsd_NameIsValid(name))
+       {
+               newDir = yaffs_MknodDirectory(parent,name,0,0,0);
+       }
+       
+       if(newDir)
+       {
+               objSize = yaffs_GetObjectFileLength(newDir);
+               attribs = yfsd_GetObjectWinAttributes(newDir);
+               modifiedTime[0] = newDir->win_mtime[0];\r
+               modifiedTime[1] = newDir->win_mtime[1];\r
+       }
+       else
+       {
+               SetLastError(ERROR_PATH_NOT_FOUND);
+       }
+
+       yfsd_UnlockYAFFS();
+
+       // Call shell function to tell of new directory
+       if(newDir && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_MKDIR;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = attribs; 
+                       yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       //yfsd_ShellDirectoryChanged(pVolume,fpn);
+
+       }
+
+       if(parent && !newDir)
+       {
+                       SetLastError(ERROR_DISK_FULL);
+       }
+
+       return newDir ? TRUE : FALSE;
+}
+
+
+BOOL yfsd_RemoveObjectW(PVOLUME pVolume, PCWSTR pathName)
+{
+       // Fails if directory is not empty
+       int result = FALSE;
+       yaffs_Object *parent = NULL;
+       yaffs_Object *obj;
+       char name[YFSD_NAME_LENGTH+1];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::RemoveObjectW (%s)\r\n", pathName));
+
+       yfsd_LockYAFFS();
+
+       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
+       if(!obj)
+       {
+               SetLastError(ERROR_FILE_NOT_FOUND);
+               result = FALSE;
+       }
+       else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
+       {
+               SetLastError(ERROR_ACCESS_DENIED);
+               result = FALSE;
+       }
+       else if(obj->inUse)
+       {
+               SetLastError(ERROR_ACCESS_DENIED);
+               result = FALSE;
+       }
+       else
+       {
+
+               parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
+
+               if(parent && yfsd_NameIsValid(name))
+               {
+                       result = yaffs_Unlink(parent,name);
+                       if(!result)
+                               SetLastError(ERROR_ACCESS_DENIED);
+               }
+       }
+
+       yfsd_UnlockYAFFS();
+
+       return result ? TRUE : FALSE;
+}
+
+
+BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
+{
+       BOOL result;
+       RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory\r\n"));
+       
+       result =  yfsd_RemoveObjectW(pVolume, pathName);
+
+       if(result && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_RMDIR;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = 0;
+                       yfsd_NullWinFileTime(&fc.ftModified);
+                       fc.nFileSize = 0;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+       
+       return result;
+
+}
+
+
+DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
+{
+       yaffs_Object *obj = NULL;
+
+       DWORD result = 0xFFFFFFFF;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
+
+       yfsd_LockYAFFS();
+
+       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+
+       if(obj)
+       {
+               result = yfsd_GetObjectWinAttributes(obj);
+       }
+       else
+       {
+               SetLastError(ERROR_FILE_NOT_FOUND);
+       }
+
+       yfsd_UnlockYAFFS();
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
+       return result;
+
+       
+}
+
+BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
+{
+       yaffs_Object *obj = NULL;\r
+       DWORD mtime[2];\r
+       DWORD attribs;\r
+       DWORD objSize;
+
+       int result = 0;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));\r
+\r
+       if(!yfsd_CheckValidAttributes(dwFileAttributes))\r
+       {\r
+                       SetLastError(ERROR_INVALID_PARAMETER);\r
+                       return FALSE;\r
+       }
+
+       yfsd_LockYAFFS();
+
+       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+
+       if(obj)
+       {
+               obj->st_mode = dwFileAttributes;
+               obj->dirty = 1;
+               result = yaffs_FlushFile(obj);\r
+               attribs = yfsd_GetObjectWinAttributes(obj);\r
+               objSize = yaffs_GetObjectFileLength(obj);\r
+               mtime[0] = obj->win_mtime[0];\r
+               mtime[1] = obj->win_mtime[1];\r
+       }
+       else
+       {
+               SetLastError(ERROR_FILE_NOT_FOUND);
+       }
+
+       yfsd_UnlockYAFFS();
+
+       if(result && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_ATTRIBUTES;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes =  attribs;
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       //yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+       
+
+       return result;
+
+}
+
+BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
+{
+       BOOL result;
+       RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
+
+       result =  yfsd_RemoveObjectW(pVolume, pwsFileName);
+       if(result && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_DELETE;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = -1;
+                       yfsd_NullWinFileTime(&fc.ftModified);
+                       fc.nFileSize = 0;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+
+       return result;
+}
+
+BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
+{
+       yaffs_Object *newParent = NULL;
+       yaffs_Object *oldParent = NULL;
+       yaffs_Object *obj = NULL;
+       char oldName[YFSD_NAME_LENGTH+1];
+       char newName[YFSD_NAME_LENGTH+1];
+       int result = 0;
+       int objIsDir = 0;
+       DWORD attribs;
+       DWORD objSize;\r
+       DWORD mtime[2];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
+
+       yfsd_LockYAFFS();
+
+       oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
+       newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
+
+       if(oldParent  && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
+       {
+               result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
+               if(!result)
+               {
+                       SetLastError(ERROR_FILE_NOT_FOUND);
+               }
+
+               obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
+               if(obj)
+               {
+                       objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
+                       attribs = yfsd_GetObjectWinAttributes(obj);
+                       objSize = yaffs_GetObjectFileLength(obj);\r
+                       mtime[0] = obj->win_mtime[0];\r
+                       mtime[1] = obj->win_mtime[1];\r
+               }
+       }
+       else
+       {
+               SetLastError(ERROR_PATH_NOT_FOUND);
+       }
+
+       yfsd_UnlockYAFFS();
+
+
+       if(result && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
+                       WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
+                       fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
+                       fc.dwAttributes = attribs;
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn1);
+                       yfsd_ShellDirectoryChanged(pVolume,fpn2);
+       }
+
+
+       return result ? TRUE : FALSE;
+
+}
+
+BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
+       return FALSE;
+}
+
+BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
+{
+
+       int nChunks;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
+
+       yfsd_LockYAFFS();
+       nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
+       yfsd_UnlockYAFFS();
+
+       if(nChunks >= 0)
+       {
+               // Let's pretentd our clusters are the same size as eraseable blocks...
+               *pBytesPerSector = 512;
+               *pSectorsPerCluster  =32;
+               *pFreeClusters = nChunks/32;
+               *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
+       }
+
+       return (nChunks >= 0)? TRUE : FALSE;
+
+
+
+}
+
+void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
+{
+       // Flags can be one of:
+       // FSNOTIFY_POWER_ON: no action required
+       // FSNOTIFY_POWER_OFF: flush all files
+       // FSNOTIFY_DEVICE_ON: no action required
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
+       if(dwFlags == FSNOTIFY_POWER_OFF)
+       {
+               yfsd_FlushAllFiles();
+       }
+
+}
+
+
+BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
+       
+       pVolume->shellFunction = pfn;
+
+       return TRUE;
+}
+
+
+
+
+
+int iMatch(const char a, const char b)
+{
+       if (a == '?' || b == '?')
+               return 1;
+       return (toupper(a) == toupper(b));
+}
+
+void pString(const char *inp)
+{
+       while (*inp) RETAILMSG(1, (L"%c", *inp++));
+}
+
+int regularMatch(const char *regexp, const char *str)
+{
+//     pString(regexp);
+//     RETAILMSG(1, (L" "));
+//     pString(str);
+//     RETAILMSG(1, (L"\r\n"));
+
+       if (*regexp == 0 && *str == 0)
+       {
+               //RETAILMSG(1, (L"Match!\r\n"));
+               return 1;
+       }
+       if (*regexp == '*')                     
+       {
+               regexp++;
+               if (*regexp == 0)   // end of the expression is a *, we must match
+               {
+                       //RETAILMSG(1, (L"Match!\r\n"));
+                       return 1;
+               }
+               while (!iMatch(*regexp, *str)) // throw away chars from str until we match
+               {
+                       if (*str == 0)  // if we're not at the end
+                       {
+                               // if we have .* left to match, but the str is finished then match it OK
+                               if (regexp[0] == '.' && regexp[1] == '*')
+                               {
+                                       //RETAILMSG(1, (L"Match!\r\n"));
+                                       return 1;
+                               }
+                               else
+                               {
+                               // the extension failed the match
+                                       //RETAILMSG(1, (L"No Match!\r\n"));
+                                       return 0;
+                               }
+                       }
+                       str++;
+               } 
+               // right now we should either eat more characters, or try to match
+               return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
+       }
+//  compare chars until we hit another *, or we fail
+       while (iMatch(*regexp, *str))
+       {
+               if (*regexp == 0 && *str == 0)
+               {
+                       //RETAILMSG(1, (L"Match!\r\n"));
+                       return 1;
+               }
+               regexp++;
+               str++;
+       }
+
+       if (*regexp == 0 && *str == 0)
+       {
+               //RETAILMSG(1, (L"Match!\r\n"));
+               return 1;
+       }
+
+       if (*regexp == '*')
+               return regularMatch(regexp, str);
+
+       //RETAILMSG(1, (L"No Match!\r\n"));
+       return 0;
+}
+
+
+void yfsd_DeleteFinder(PSEARCH pSearch)
+{
+  if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
+  {
+    yaffs_FoundObject *it;
+    yaffs_FoundObject *temp;
+
+    it = pSearch->foundObjects;
+
+    while(it != NULL)
+    {
+      temp = it;
+      it = it->next;
+      
+      free(temp);
+    }
+
+    pSearch->foundObjects = NULL;
+  }
+
+               pSearch->dir->inUse--;
+               free(pSearch);
+}
+
+BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
+{
+  //Iterate through the current list of objs already found and return true if already exists.
+  //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
+  BOOL found = FALSE;
+
+  yaffs_FoundObject *it;
+  it = pSearch->foundObjects;
+
+  
+  while(it->next != NULL) //iterate through singly linked list.
+  {
+    if(it->obj == l)
+    {
+      found = TRUE;
+      break;
+    }
+    it = it->next;
+  }
+
+  if(!found)
+  {
+    //Add the item to the list.
+    //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
+    it->next = malloc(sizeof(yaffs_FoundObject));
+    it->next->next = NULL;
+    it->next->obj = 0;
+
+    it->obj = l;
+  }
+
+  return found;
+}
+\r
+#if 0\r
+// slower one
+BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
+{
+
+       struct list_head *i;
+       int pos;
+       yaffs_Object *l;
+       BOOL found = 0;
+
+       char name[YAFFS_MAX_NAME_LENGTH+1];
+
+  if(!pSearch->foundObjects)
+  {
+    pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
+    pSearch->foundObjects->next = NULL;
+    pSearch->foundObjects->obj = 0;
+  }
+
+
+       yfsd_LockYAFFS();
+
+       pos = 0;
+       list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
+       {
+
+               l = list_entry(i, yaffs_Object,siblings);
+
+               yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
+
+               if(regularMatch(pSearch->pattern,name))
+               {
+                       if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
+                       {               
+
+                               
+                               found = 1;
+                               //pSearch->currentPos++;
+
+                               // fill out find data
+
+                               pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
+
+                               yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
+                               yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
+                               yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
+
+                               pfd->nFileSizeHigh = 0;
+                               pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
+                               pfd->dwOID = 0; // wtf is this???
+
+                               MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
+
+                               RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
+                                                       pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
+                                                       l->variant.fileVariant.scannedFileSize));
+                               goto out_of_here;
+                       }
+                       else
+                       {
+                               pos++;
+                       }
+               }
+       }
+
+out_of_here:
+       yfsd_UnlockYAFFS();
+
+
+       if(!found)
+       {
+               SetLastError(ERROR_NO_MORE_FILES);
+       }
+       return found;
+       
+}
+\r
+#else\r
+// faster one\r
+BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)\r
+{\r
+\r
+       struct list_head *i;\r
+       yaffs_Object *l;\r
+       BOOL found = 0;\r
+\r
+       char name[YAFFS_MAX_NAME_LENGTH+1];\r
+\r
+  if(!pSearch->foundObjects)\r
+  {\r
+    pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));\r
+    pSearch->foundObjects->next = NULL;\r
+    pSearch->foundObjects->obj = 0;\r
+  }\r
+\r
+\r
+       yfsd_LockYAFFS();\r
+\r
+       list_for_each(i,&pSearch->dir->variant.directoryVariant.children)\r
+       {\r
+\r
+               l = list_entry(i, yaffs_Object,siblings);\r
+               if(!yfsd_ObjectAlreadyFound(pSearch,l))\r
+               {\r
+                       // Only look at things we have not looked at already\r
+                       yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);\r
+\r
+                       if(regularMatch(pSearch->pattern,name))\r
+                       {\r
+                               found = 1;\r
+                               // fill out find data\r
+\r
+                               pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);\r
+\r
+                               yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);\r
+                               yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);\r
+                               yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);\r
+\r
+                               pfd->nFileSizeHigh = 0;\r
+                               pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);\r
+                               pfd->dwOID = 0; // wtf is this???\r
+\r
+                               MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);\r
+\r
+                               RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",\r
+                                                       pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,\r
+                                                       l->variant.fileVariant.scannedFileSize));\r
+                               goto out_of_here;\r
+                       }\r
+\r
+               }\r
+\r
+\r
+       }\r
+\r
+out_of_here:\r
+       yfsd_UnlockYAFFS();\r
+\r
+\r
+       if(!found)\r
+       {\r
+               SetLastError(ERROR_NO_MORE_FILES);\r
+       }\r
+       return found;\r
+       \r
+}\r
+#endif\r
+
+HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
+{
+
+       // Create a search context, register it, and do the first search
+
+       PSEARCH pSearch;
+       HANDLE h = INVALID_HANDLE_VALUE;
+       BOOL found = 0;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
+
+       pSearch = malloc(sizeof(yfsd_WinFind));
+       if(!pSearch)
+       {
+               SetLastError(ERROR_OUTOFMEMORY);
+       }
+
+       yfsd_LockYAFFS();
+
+       if(pSearch)
+       {
+               pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
+               pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
+               if(pSearch->dir)
+               {
+                               pSearch->dir->inUse++;
+               }
+               else
+               {
+                       free(pSearch);
+                       pSearch = NULL;
+               }
+       }
+
+       yfsd_UnlockYAFFS();
+
+
+
+       if(pSearch)
+       {
+               found = yfsd_DoFindFile(pSearch,pfd);
+       }
+
+       if(found)
+       {
+               h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
+       }
+
+       if(h == INVALID_HANDLE_VALUE && pSearch)
+       {
+               yfsd_DeleteFinder(pSearch);
+               SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
+       }
+
+
+
+       return h;
+}
+
+BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
+       if(!pSearch)
+       {
+               return FALSE;
+       }
+       return yfsd_DoFindFile(pSearch,pfd);
+}
+
+BOOL YFSD_FindClose( PSEARCH pSearch )
+{      
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
+       if(!pSearch)
+       {
+               return FALSE;
+       }
+       yfsd_DeleteFinder(pSearch);
+       return TRUE;
+}
+
+
+HANDLE YFSD_CreateFileW( 
+       PVOLUME pVolume, 
+       HANDLE hProc, 
+       PCWSTR pwsFileName, 
+       DWORD dwAccess, 
+       DWORD dwShareMode,
+       PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
+       DWORD dwCreate,
+       DWORD dwFlagsAndAttributes, 
+       HANDLE hTemplateFile ) // ignore
+{
+
+
+       yaffs_Object *parent = NULL;
+       yaffs_Object *obj = NULL;
+       char name[YFSD_NAME_LENGTH+1];
+       int mode;
+       yfsd_WinFile *f = NULL;
+       HANDLE handle = INVALID_HANDLE_VALUE;
+       unsigned modifiedTime[2];
+       unsigned objSize;
+
+       BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
+
+       BOOL fileCreated = FALSE;
+
+
+       mode = dwFlagsAndAttributes & 0x00FFFFFF;  // ding off the flags
+
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));
+       if(writePermitted)
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
+       }
+
+       if(!yfsd_CheckValidAttributes(mode))\r
+       {\r
+                       SetLastError(ERROR_INVALID_PARAMETER);\r
+                       return FALSE;\r
+       }\r
+
+       yfsd_LockYAFFS();
+
+
+       parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
+
+
+       if(parent && yfsd_NameIsValid(name))
+       {
+\r
+
+               obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
+               if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
+               {\r
+                       // Naughty, naughty. Don't do file ops on directories\r
+                       SetLastError(ERROR_ACCESS_DENIED);\r
+                       fileCreated = FALSE;\r
+                       obj = NULL;\r
+               }\r
+               else if(dwCreate == CREATE_NEW)
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
+
+                       obj = yaffs_MknodFile(parent,name,mode,0,0);
+                       if(!obj)
+                               SetLastError(ERROR_DISK_FULL);
+                       fileCreated = TRUE;
+               }
+               else if( dwCreate == OPEN_ALWAYS)
+               {
+                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       if(!obj)
+                       {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
+                               obj = yaffs_MknodFile(parent,name,mode,0,0);
+                               if(!obj)
+                                       SetLastError(ERROR_DISK_FULL);
+                               fileCreated = TRUE;
+
+                       }
+                       else
+                       {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
+                       }
+               }
+               else if(dwCreate == OPEN_EXISTING)
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
+                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       if(!obj)
+                               SetLastError(ERROR_FILE_NOT_FOUND);
+               }
+               else if(dwCreate == TRUNCATE_EXISTING)
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));
+                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       if(obj)
+                       {
+                               yaffs_ResizeFile(obj,0);
+                       }
+                       else
+                       {
+                               SetLastError(ERROR_FILE_NOT_FOUND);
+                       }
+               }
+               else if(dwCreate == CREATE_ALWAYS)
+               {
+                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+
+                       if(!obj)
+                       {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
+                               obj = yaffs_MknodFile(parent,name,mode,0,0);
+                               if(!obj)
+                                       SetLastError(ERROR_DISK_FULL);
+                               fileCreated = TRUE;
+                       }
+                       else
+                       {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));
+                               obj->st_mode = mode;
+                               obj->dirty = 1;
+                               yaffs_ResizeFile(obj,0);
+                               yaffs_FlushFile(obj);
+                       }
+               }
+               else
+               {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
+                               SetLastError(ERROR_INVALID_PARAMETER);
+               }
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
+               SetLastError(ERROR_PATH_NOT_FOUND);
+       }
+
+       if(obj)
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
+               f = yfsd_GetWinFile();
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
+       }
+
+       if(f)
+       {
+
+               handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
+
+               if(handle != INVALID_HANDLE_VALUE)
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
+                       f->obj = obj;
+                       f->offset = 0;
+                       f->writePermitted = writePermitted;
+                       f->myVolume = pVolume;
+                       obj->inUse++;
+
+                       modifiedTime[0] = obj->win_mtime[0];\r
+                       modifiedTime[1] = obj->win_mtime[1];\r
+                       objSize = yaffs_GetObjectFileLength(obj);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
+               }
+               else
+               {
+                       yfsd_PutWinFile(f);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
+               }
+
+       }
+
+       yfsd_UnlockYAFFS();
+
+       if(handle != INVALID_HANDLE_VALUE && 
+          fileCreated &&
+          pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_CREATE;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = mode;
+                       yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+
+       if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
+       {
+                       // Remember the name
+
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+                       int slen;
+
+                       yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       slen = wcslen(fpn);
+                       f->fullName = malloc((slen+1)* sizeof(WCHAR));
+                       if(f->fullName)
+                       {
+                               wcscpy(f->fullName,fpn);
+                       }
+
+       }
+
+
+       return handle;
+
+}
+
+BOOL yfsd_DoReadFile( 
+       PFILE pFile, 
+       PVOID pBuffer, 
+       DWORD cbRead, 
+       PDWORD pcbRead)
+{
+       
+       DWORD maxRead;
+       int nread = 0;
+       yaffs_Object *obj = NULL;
+
+
+       if(pcbRead)
+       {
+               *pcbRead = 0;
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
+       }
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+       
+       obj = pFile->obj;
+
+       if(yaffs_GetObjectFileLength(obj) > pFile->offset)
+       {
+               maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
+       }
+       else
+       {
+               maxRead = 0;
+       }
+
+       if(cbRead > maxRead)
+       {
+               cbRead = maxRead;
+       }
+       
+       if(maxRead > 0)
+       {
+               nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
+               if(nread > 0)
+               {\r
+                       pFile->offset += nread;\r
+
+                       if(pcbRead)
+                       {
+                               *pcbRead = nread;
+                       }
+               }
+       }
+       else
+       {
+               if(pcbRead) \r
+               {\r
+                       *pcbRead = maxRead;\r
+               }
+       }
+
+
+       return nread < 0? FALSE : TRUE; 
+
+}
+
+BOOL YFSD_ReadFile( 
+       PFILE pFile, 
+       PVOID pBuffer, 
+       DWORD cbRead, 
+       PDWORD pcbRead, 
+       OVERLAPPED *pOverlapped ) //ignore
+{
+       BOOL result;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+       result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+}
+
+BOOL YFSD_ReadFileWithSeek( 
+       PFILE pFile, 
+       PVOID pBuffer, 
+       DWORD cbRead, 
+       PDWORD pcbRead, 
+       OVERLAPPED *pOverlapped, 
+       DWORD dwLowOffset, 
+       DWORD dwHighOffset )
+{
+       BOOL result;\r
+       DWORD rememberedOffset;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
+
+       // To determine if paging is supported, the kernel calls this with all parameters except pFile
+       // being zero.
+       if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
+       {
+               return TRUE; // paging suppported
+               //return FALSE; // paging not supported
+       }
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();\r
+\r
+       rememberedOffset = pFile->offset;
+
+       pFile->offset = dwLowOffset;
+       // ignore high offset for now
+
+       result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
+\r
+       //pFile->offset = rememberedOffset;\r
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+
+
+}
+
+
+BOOL yfsd_DoWriteFile( 
+       PFILE pFile, 
+       PCVOID pBuffer, 
+       DWORD cbWrite, 
+       PDWORD pcbWritten)
+{
+       int nwritten = 0;
+       yaffs_Object *obj = NULL;
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
+       
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if(!pFile->writePermitted)
+       {
+                       *pcbWritten = 0;
+                       SetLastError(ERROR_ACCESS_DENIED);
+                       return FALSE;
+       }
+
+       obj = pFile->obj;
+
+       *pcbWritten = 0;
+
+
+               nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
+               if(nwritten >= 0)
+               {
+                       pFile->offset += nwritten;
+                       *pcbWritten = nwritten;
+               }
+               if(nwritten != cbWrite)
+               {
+                       SetLastError(ERROR_DISK_FULL);
+               }
+
+
+       return nwritten != cbWrite? FALSE : TRUE; 
+}
+
+
+BOOL YFSD_WriteFile( 
+       PFILE pFile, 
+       PCVOID pBuffer, 
+       DWORD cbWrite, 
+       PDWORD pcbWritten, 
+       OVERLAPPED *pOverlapped )
+{
+       BOOL result;
+
+       yfsd_LockYAFFS();
+       RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
+
+       result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+}
+
+BOOL YFSD_WriteFileWithSeek( 
+       PFILE pFile, 
+       PCVOID pBuffer, 
+       DWORD cbWrite, 
+       PDWORD pcbWritten, 
+       OVERLAPPED *pOverlapped,
+       DWORD dwLowOffset, 
+       DWORD dwHighOffset )
+{
+       BOOL result;
+       DWORD rememberedOffset;
+       RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
+
+       \r
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+\r
+       rememberedOffset = pFile->offset;\r
+
+       pFile->offset = dwLowOffset;
+       // ignore high offset for now
+
+       result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
+\r
+       //pFile->offset = rememberedOffset;\r
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+}
+
+DWORD YFSD_SetFilePointer( 
+       PFILE pFile, 
+       LONG lDistanceToMove, 
+       PLONG pDistanceToMoveHigh, 
+       DWORD dwMoveMethod )
+{
+       // ignore high offset for now
+
+       DWORD offset = 0xFFFFFFFF;
+       DWORD oldPos;
+       int fileSize;
+       int seekNegative = 0;
+
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return offset;
+       }
+
+       yfsd_LockYAFFS();\r
+\r
+
+       oldPos = pFile->offset;
+
+       if(dwMoveMethod == FILE_BEGIN)
+       {
+               if(lDistanceToMove >= 0)
+               {       
+                       offset = pFile->offset = lDistanceToMove;
+               }
+               else
+               {
+                       seekNegative = 1;
+               }
+       }
+       else if(dwMoveMethod == FILE_END)
+       {
+               fileSize = yaffs_GetObjectFileLength(pFile->obj);
+               if(fileSize >= 0 &&
+                  (fileSize + lDistanceToMove) >= 0)
+               {
+                       offset = pFile->offset = fileSize + lDistanceToMove;
+               }
+               else
+               {
+                       seekNegative = 1;
+               }
+       }
+       else if(dwMoveMethod == FILE_CURRENT)
+       {
+               if(pFile->offset + lDistanceToMove >= 0)
+               {
+                       offset = pFile->offset = pFile->offset + lDistanceToMove;               
+               }
+               else
+               {
+                               seekNegative = 1;
+               }
+       }
+
+       if(seekNegative)
+       {
+                       SetLastError(ERROR_NEGATIVE_SEEK);
+                       
+       }
+
+       yfsd_UnlockYAFFS();
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
+                                 dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
+
+       return offset;
+
+}
+
+DWORD YFSD_GetFileSize( 
+       PFILE pFile, 
+       PDWORD pFileSizeHigh )
+{
+       int fileSize;
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
+       
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return -1;
+       }
+
+       yfsd_LockYAFFS();
+
+       fileSize = yaffs_GetObjectFileLength(pFile->obj);
+
+       yfsd_UnlockYAFFS();\r
+       if(pFileSizeHigh)\r
+                *pFileSizeHigh = 0;
+
+       return fileSize;
+
+}
+
+
+BOOL YFSD_GetFileInformationByHandle( 
+       PFILE pFile,
+       PBY_HANDLE_FILE_INFORMATION pFileInfo )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
+
+       if(!pFile || !pFile->obj || !pFileInfo)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }\r
+\r
+       yfsd_LockYAFFS();\r
+\r
+       pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);\r
+       yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);\r
+       yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);\r
+       yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);\r
+       pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK? \r
+       pFileInfo->nFileSizeHigh = 0;\r
+       pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj); \r
+       pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT\r
+       pFileInfo->nFileIndexHigh = 0; \r
+       pFileInfo->nFileIndexLow = pFile->obj->objectId; \r
+\r
+       yfsd_UnlockYAFFS();
+
+       return TRUE;
+}
+
+BOOL YFSD_FlushFileBuffers(PFILE pFile )
+{\r
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
+       int nameExists = 0;\r
+       yfsd_Volume *vol = NULL;\r
+       DWORD attribs = 0;\r
+       DWORD objSize = 0;\r
+       DWORD mtime[2];\r
+\r
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();\r
+
+       yaffs_FlushFile(pFile->obj);\r
+       attribs = yfsd_GetObjectWinAttributes(pFile->obj);\r
+       objSize = yaffs_GetObjectFileLength(pFile->obj);\r
+       mtime[0] = pFile->obj->win_mtime[0];\r
+       mtime[1] = pFile->obj->win_mtime[1];\r
+       if(pFile->fullName)\r
+       {\r
+               wcscpy(fpn,pFile->fullName);\r
+               nameExists = 1;\r
+       }\r
+       vol = pFile->myVolume;\r
+\r
+       yfsd_UnlockYAFFS();
+       \r
+       if(vol && vol->shellFunction && nameExists)\r
+       {\r
+                       FILECHANGEINFO fc;\r
+               \r
+                       fc.cbSize = sizeof(FILECHANGEINFO);\r
+                       fc.wEventId = SHCNE_UPDATEITEM;\r
+                       fc.uFlags = SHCNF_PATH;\r
+                       fc.dwItem1 = (DWORD)fpn;\r
+                       fc.dwItem2 = 0;\r
+                       fc.dwAttributes = attribs;\r
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
+                       fc.nFileSize = objSize;\r
+\r
+                       vol->shellFunction(&fc);\r
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
+                       //yfsd_ShellDirectoryChanged(vol,fpn);\r
+       }\r
+\r
+       
+       return TRUE;
+}
+
+BOOL YFSD_GetFileTime( 
+       PFILE pFile, 
+       FILETIME *pCreation, 
+       FILETIME *pLastAccess, 
+       FILETIME *pLastWrite )
+{
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+       if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
+       if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
+       if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
+
+       yfsd_UnlockYAFFS();
+
+       return TRUE;
+}
+
+BOOL YFSD_SetFileTime( 
+       PFILE pFile, 
+       CONST FILETIME *pCreation, 
+       CONST FILETIME *pLastAccess, 
+       CONST FILETIME *pLastWrite )
+{
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
+       int nameExists = 0;\r
+       int result = FALSE;
+       yfsd_Volume *vol = NULL;\r
+       DWORD attribs = 0;\r
+       DWORD objSize = 0;\r
+       DWORD mtime[2];\r
+\r
+       \r
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+       
+       
+       yfsd_LockYAFFS();
+
+       if(pCreation) \r
+       {\r
+                yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);\r
+               pFile->obj->dirty = 1;\r
+       }
+       if(pLastAccess)\r
+       {\r
+               yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);\r
+               pFile->obj->dirty = 1;\r
+       }
+       if(pLastWrite)\r
+       {\r
+               yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);\r
+               pFile->obj->dirty = 1;
+       }
+       if(pCreation || pLastAccess || pLastWrite)
+       {
+               result = yaffs_FlushFile(pFile->obj);
+       }
+\r
+       if(result)\r
+       {
+               attribs = yfsd_GetObjectWinAttributes(pFile->obj);\r
+               objSize = yaffs_GetObjectFileLength(pFile->obj);\r
+               mtime[0] = pFile->obj->win_mtime[0];\r
+               mtime[1] = pFile->obj->win_mtime[1];\r
+               if(pFile->fullName)\r
+               {\r
+                       wcscpy(fpn,pFile->fullName);\r
+                       nameExists = 1;\r
+               }\r
+               vol = pFile->myVolume;\r
+       }\r
+\r
+       yfsd_UnlockYAFFS();
+
+       // Call shell function
+       if(nameExists && result && vol && vol->shellFunction)\r
+       {\r
+                       FILECHANGEINFO fc;\r
+               \r
+                       fc.cbSize = sizeof(FILECHANGEINFO);\r
+                       fc.wEventId = SHCNE_UPDATEITEM;\r
+                       fc.uFlags = SHCNF_PATH;\r
+                       fc.dwItem1 = (DWORD)fpn;\r
+                       fc.dwItem2 = 0;\r
+                       fc.dwAttributes = attribs;\r
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
+                       fc.nFileSize = objSize;\r
+\r
+                       vol->shellFunction(&fc);\r
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
+                       //yfsd_ShellDirectoryChanged(vol,fpn);\r
+       }\r
+
+       return TRUE;
+}
+   
+BOOL YFSD_SetEndOfFile( 
+PFILE pFile )
+{
+
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
+       int nameExists = 0;\r
+       yfsd_Volume *vol = NULL;\r
+       DWORD attribs = 0;\r
+       DWORD objSize = 0;\r
+       DWORD mtime[2];\r
+       static unsigned char zeros[512];
+
+       int result;
+       BOOL retVal = FALSE;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+       result = yaffs_ResizeFile(pFile->obj,pFile->offset);
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
+
+       // Resize only works if we're shortening the file.
+       // If the result is shorter than the offset, then we need to write zeros....
+       // 
+       if(result != pFile->offset)
+       {
+               if(result < pFile->offset)
+               {
+
+                       int nBytes = pFile->offset - result;
+                       int thisWriteSize;
+                       int written;
+                       BOOL ok = TRUE;
+
+                       memset(zeros,0,512);
+
+                       pFile->offset = result;
+                       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
+                       while(nBytes > 0 && ok)
+                       {
+                               thisWriteSize = (nBytes > 512) ? 512  : nBytes;
+
+                               ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);      
+                               if(written != thisWriteSize)
+                               {
+                                       ok = FALSE;
+                               }
+
+                               nBytes -= thisWriteSize;
+                       }
+
+                       retVal = ok;
+               }
+               else
+               {
+
+                       SetLastError(ERROR_ACCESS_DENIED);
+                       retVal = FALSE;
+               }
+       }
+       else
+       {
+               retVal = TRUE;
+       }
+       if(retVal)\r
+       {\r
+               attribs = yfsd_GetObjectWinAttributes(pFile->obj);\r
+               objSize = yaffs_GetObjectFileLength(pFile->obj);\r
+               mtime[0] = pFile->obj->win_mtime[0];\r
+               mtime[1] = pFile->obj->win_mtime[1];\r
+               if(pFile->fullName)\r
+               {\r
+                       wcscpy(fpn,pFile->fullName);\r
+                       nameExists = 1;\r
+               }\r
+               vol = pFile->myVolume;\r
+       }\r
+\r
+\r
+       yfsd_UnlockYAFFS();\r
+\r
+       if(nameExists && retVal && vol && vol->shellFunction)\r
+       {\r
+                       FILECHANGEINFO fc;\r
+               \r
+                       fc.cbSize = sizeof(FILECHANGEINFO);\r
+                       fc.wEventId = SHCNE_UPDATEITEM;\r
+                       fc.uFlags = SHCNF_PATH;\r
+                       fc.dwItem1 = (DWORD)fpn;\r
+                       fc.dwItem2 = 0;\r
+                       fc.dwAttributes = attribs;\r
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
+                       fc.nFileSize = objSize;\r
+\r
+                       vol->shellFunction(&fc);\r
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
+                       //yfsd_ShellDirectoryChanged(vol,fpn);\r
+       }\r
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
+
+
+       
+       return retVal;
+}
+
+BOOL YFSD_DeviceIoControl( 
+       PFILE pFile, 
+       DWORD dwIoControlCode, 
+       PVOID pInBuf, 
+       DWORD nInBufSize, 
+       PVOID pOutBuf, 
+       DWORD nOutBufSize, 
+       PDWORD pBytesReturned, 
+       OVERLAPPED *pOverlapped )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
+
+       return FALSE;
+}
+
+BOOL YFSD_CloseFile( PFILE pFile )
+{
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];\r
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
+
+       yfsd_LockYAFFS();
+
+       if(!pFile)
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
+       }
+       else
+       {
+               if(pFile->obj)
+               {
+                       pFile->obj->inUse--;
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
+                       yaffs_FlushFile(pFile->obj);
+                       attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+                       objSize = yaffs_GetObjectFileLength(pFile->obj);
+                       mtime[0] = pFile->obj->win_mtime[0];\r
+                       mtime[1] = pFile->obj->win_mtime[1];\r
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
+                       if(pFile->fullName)
+                       {
+                               wcscpy(fpn,pFile->fullName);
+                               nameExists = 1;
+                       }
+                       vol = pFile->myVolume;
+                       yfsd_PutWinFile(pFile);
+               }
+               else
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
+               }
+
+       }
+       yfsd_UnlockYAFFS();
+
+
+       if(nameExists && vol && vol->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+               
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_UPDATEITEM;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)fpn;
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = attribs;
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       vol->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+                       //yfsd_ShellDirectoryChanged(vol,fpn);
+       }
+
+       
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
+
+       return TRUE;
+
+}
+
+
+BOOL YFSD_CloseVolume(PVOLUME pVolume )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
+       yfsd_FlushAllFiles();
+       return TRUE;
+}
+
diff --git a/wince/yfsd.def b/wince/yfsd.def
new file mode 100644 (file)
index 0000000..46bff9a
--- /dev/null
@@ -0,0 +1,37 @@
+LIBRARY      YFSD\r
+   DESCRIPTION      'YAFFS for Windows CE'\r
+\r
+EXPORTS\r
+   YFSD_MountDisk\r
+   YFSD_UnmountDisk\r
+   FSD_MountDisk=YFSD_MountDisk\r
+   FSD_UnmountDisk=YFSD_UnmountDisk\r
+   YFSD_CreateDirectoryW\r
+   YFSD_RemoveDirectoryW\r
+   YFSD_GetFileAttributesW\r
+   YFSD_SetFileAttributesW\r
+   YFSD_DeleteFileW\r
+   YFSD_MoveFileW\r
+   YFSD_DeleteAndRenameFileW\r
+   YFSD_GetDiskFreeSpaceW\r
+   YFSD_Notify\r
+   YFSD_RegisterFileSystemFunction\r
+   YFSD_FindFirstFileW\r
+   YFSD_FindNextFileW\r
+   YFSD_FindClose\r
+   YFSD_CreateFileW\r
+   YFSD_ReadFile\r
+   YFSD_ReadFileWithSeek\r
+   YFSD_WriteFile\r
+   YFSD_WriteFileWithSeek\r
+   YFSD_SetFilePointer\r
+   YFSD_GetFileSize\r
+   YFSD_GetFileInformationByHandle\r
+   YFSD_FlushFileBuffers\r
+   YFSD_GetFileTime\r
+   YFSD_SetFileTime\r
+   YFSD_SetEndOfFile\r
+   YFSD_DeviceIoControl\r
+   YFSD_CloseFile\r
+   YFSD_CloseVolume\r
+\r
diff --git a/wince/ynandif.c b/wince/ynandif.c
new file mode 100644 (file)
index 0000000..5e982b5
--- /dev/null
@@ -0,0 +1,179 @@
+/*\r
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.\r
+ * ynandif.c: NAND interface functions for the WinCE port of YAFFS.\r
+ *\r
+ * Copyright (C) 2002 Trimble Navigation Ltd.\r
+ *\r
+ * Created by Brad Beveridge <brad.beveridge@trimble.co.nz>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 as\r
+ * published by the Free Software Foundation.\r
+ *\r
+ * This program is distributed in the hope that it will be useful, \r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of \r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \r
+ * General Public License for more details. You should have received a \r
+ * copy of the GNU General Public License along with this program; \r
+ * if not, write to the Free Software Foundation, Inc., \r
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \r
+ *\r
+ * $Id: ynandif.c,v 1.1 2002-11-08 07:30:00 charles Exp $\r
+ */\r
+#include "ynandif.h"\r
+#include <windows.h>\r
+\r
+HANDLE devHandle = 0;\r
+\r
+/*\r
+*      Functions that need to be provided for YAFFS\r
+*/\r
+int ynandif_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND,const __u8 *data, yaffs_Spare *spare)\r
+{\r
+       if (devHandle)\r
+       {\r
+               ynandif_data writeData;\r
+               int result;\r
+\r
+               writeData.chunk = chunkInNAND;\r
+               writeData.data = (__u8 *)data;\r
+               writeData.spare = (char *)spare;\r
+               \r
+               if (!DeviceIoControl(devHandle,\r
+                                                    YNANDIF_WRITE,\r
+                                                    &writeData,\r
+                                                    sizeof(ynandif_data),\r
+                                                    &result,\r
+                                                    sizeof(result),\r
+                                                    NULL,\r
+                                                        NULL))\r
+                       return YAFFS_FAIL;\r
+\r
+               return result;\r
+       }\r
+\r
+       return YAFFS_FAIL;\r
+}\r
+\r
+int ynandif_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)\r
+{\r
+       if (devHandle)\r
+       {\r
+               ynandif_data readData;\r
+               int result;\r
+\r
+               readData.chunk = chunkInNAND;\r
+               readData.data = data;\r
+               readData.spare = (char *)spare;\r
+               \r
+               if (!DeviceIoControl(devHandle,\r
+                                                    YNANDIF_READ,\r
+                                                    &readData,\r
+                                                    sizeof(ynandif_data),\r
+                                                    &result,\r
+                                                    sizeof(result),\r
+                                                    NULL,\r
+                                                        NULL))\r
+                       return YAFFS_FAIL;\r
+\r
+               return result;\r
+       }\r
+\r
+       return YAFFS_FAIL;\r
+}\r
+\r
+int ynandif_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)\r
+{\r
+       if (devHandle)\r
+       {\r
+               int result;\r
+               \r
+               if (!DeviceIoControl(devHandle,\r
+                                                    YNANDIF_ERASE,\r
+                                                    &blockNumber,\r
+                                                    sizeof(int),\r
+                                                    &result,\r
+                                                    sizeof(result),\r
+                                                    NULL,\r
+                                                        NULL))\r
+                       return YAFFS_FAIL;\r
+\r
+               return result;\r
+       }\r
+\r
+// if we return YAFFS_FAIL, then yaffs will retire this block & mark it bad, not exactly\r
+// what we want to do by default.\r
+       return YAFFS_OK;\r
+}\r
+\r
+int ynandif_InitialiseNAND(yaffs_Device *dev)\r
+{\r
+       RETAILMSG(1, (L"ynandif_InitialiseNAND\r\n"));\r
+       devHandle = CreateFile(L"YND1:",\r
+                                                  GENERIC_READ|GENERIC_WRITE,\r
+                                                  0,\r
+                                                  NULL,\r
+                                                  OPEN_EXISTING,\r
+                                                  0,\r
+                                                  0);\r
+\r
+       if (!devHandle)\r
+               return 0;\r
+\r
+       RETAILMSG(1, (L"devhandle open\r\n"));\r
+\r
+       RETAILMSG(1, (L"DeviceIo INIT\r\n"));\r
+       if (!DeviceIoControl(devHandle,\r
+                                                YNANDIF_INIT,\r
+                                                NULL,\r
+                                                0,\r
+                                                NULL,\r
+                                                0,\r
+                                                NULL,\r
+                                                NULL))\r
+               return 0;\r
+\r
+\r
+       if (dev)\r
+       {\r
+               int nBlocks = ynandif_GetChipSize(0xFF) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);\r
+               dev->startBlock = 1;  // Don't use block 0\r
+               dev->endBlock = nBlocks - 1;\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+int ynandif_EraseAllBlocks(yaffs_Device *dev)\r
+{\r
+       int numBlocks, counter;\r
+       numBlocks = ynandif_GetChipSize(0xFF) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);\r
+       for (counter = 0; counter < numBlocks; counter++)\r
+       {\r
+               ynandif_EraseBlockInNAND(dev, counter);\r
+       }\r
+       return YAFFS_OK;\r
+}\r
+\r
+int ynandif_GetChipSize(unsigned char chipNumber)\r
+{\r
+       int ret = 0;\r
+       RETAILMSG(1, (L"DeviceIo GETSIZE\r\n"));\r
+       if (devHandle)\r
+       {\r
+               RETAILMSG(1, (L"DeviceIo GETSIZE - getting ret\r\n"));\r
+               DeviceIoControl(devHandle,\r
+                                       YNANDIF_GETSIZE,\r
+                                       NULL,\r
+                                       0,\r
+                                       &ret,\r
+                                       sizeof(ret),\r
+                                       NULL,\r
+                                       NULL);\r
+       }\r
+       RETAILMSG(1, (L"DeviceIo GETSIZE ret %X\r\n", ret));\r
+\r
+\r
+\r
+       return ret;\r
+}\r
diff --git a/wince/ynandif.h b/wince/ynandif.h
new file mode 100644 (file)
index 0000000..3ae1e8a
--- /dev/null
@@ -0,0 +1,64 @@
+/*\r
+ * YAFFS: Yet another FFS. A NAND-flash specific file system. \r
+ * ynandif.h: Nand interface routines for WinCE version of YAFFS.\r
+ *\r
+ * Copyright (C) 2002 Trimble Navigaion Ltd.\r
+ *\r
+ * Created by Brad Beveridge <brad.beveridge@trimble.co.nz>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU Lesser General Public License version 2.1 as\r
+ * published by the Free Software Foundation.\r
+ *\r
+ * This program is distributed in the hope that it will be useful, \r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of \r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \r
+ * General Public License for more details. You should have received a \r
+ * copy of the GNU General Public License along with this program; \r
+ * if not, write to the Free Software Foundation, Inc., \r
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \r
+ *\r
+ *\r
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.\r
+ *\r
+ * $Id: ynandif.h,v 1.1 2002-11-08 07:30:00 charles Exp $\r
+ */\r
+\r
+#ifndef YNANDIF_H\r
+#define YNANDIF_H\r
+\r
+#include "yaffs_guts.h"\r
+\r
+typedef struct\r
+{\r
+       int chunk;\r
+       unsigned char *data;\r
+       unsigned char *spare;\r
+} ynandif_data;\r
+\r
+typedef enum\r
+{\r
+       YNANDIF_WRITE = 0x59AFF,\r
+       YNANDIF_READ,\r
+       YNANDIF_ERASE,\r
+       YNANDIF_INIT,\r
+       YNANDIF_GETSIZE,\r
+} ynandif_commands;\r
+\r
+\r
+/*\r
+*      Functions that need to be provided for YAFFS\r
+*/\r
+int ynandif_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND,const __u8 *data, yaffs_Spare *spare);\r
+int ynandif_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);\r
+int ynandif_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);\r
+int ynandif_InitialiseNAND(yaffs_Device *dev);\r
+\r
+/*\r
+*      Additional optional functions\r
+*/\r
+\r
+int ynandif_EraseAllBlocks(yaffs_Device *dev);\r
+int ynandif_GetChipSize(unsigned char chipNumber);\r
+\r
+#endif // end of file
\ No newline at end of file