Fix blocks per chunk in resize
[yaffs/.git] / wince / yaffsfsd.c
index 7e202bfe17e60ab44912a09b6ec8b0af253b4830..f9e8bef50620bf40a4c937071ae14c363e06e0e3 100644 (file)
@@ -1,59 +1,65 @@
-/*\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 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
- * Acknowledgements:\r
- *  Various clean-ups and WinCE4 support by Steve Fogle\r
- * $Id: yaffsfsd.c,v 1.2 2003-01-14 23:15:41 charles Exp $\r
+/*
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
+ * yaffsfsd.c: FSD interface funtions for WinCE.
+ *
+ * Copyright (C) 2002 Trimble Navigation Ltd.
+ *
+ * Created by Charles Manning <charles.manning@trimble.co.nz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
+ * General Public License for more details. You should have received a 
+ * copy of the GNU General Public License along with this program; 
+ * if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+ *
+ * Acknowledgements:
+ *  Various clean-ups and WinCE4 support by Steve Fogle and Lynn Winter
+ * $Id: yaffsfsd.c,v 1.4 2003-01-31 03:30:33 charles Exp $
  */
 #include <windows.h>
 #include <extfile.h>
 #include <yaffs_guts.h>
-#include <ynandif.h>\r
-//slf021104b begin\r
-#include <diskio.h>\r
+#include <ynandif.h>
+//slf021104b begin
+#include <diskio.h>
 //slf021104b end
 
 #define MAX_WIN_FILE   200
 #define YFSD_NAME_LENGTH 128
 #define YFSD_FULL_PATH_NAME_SIZE 500
 
-\r
+
 #define YFSD_DISK_NAME L"Disk"
-#define YFSD_BOOT_NAME L"Boot"\r
+#define YFSD_BOOT_NAME L"Boot"
+
+#define PARTITION_START_NUMBER (1280)  
 
-#define PARTITION_START_NUMBER (1280)          
 
-//#define MSGSTATE 1\r
+// if this is defined the there will be a constant message box raised to display status
+//#define MSGBOX_DISPLAY
+       
+
+//#define MSGSTATE 1
 #define MSGSTATE 0
-//#define DISABLE_BOOT_PARTITION\r
-//slf021105a begin\r
-// Define DO_PARTITION_TABLE to cause the partition table \r
-// information to be retrieved from the block driver.\r
-//#define DO_PARTITION_TABLE\r
-// How many partitions the disk might have.  2 gives \r
-// space for the "Disk" and "Boot" partitions.\r
-#define MAXPARTITIONS (2)\r
+//#define DISABLE_BOOT_PARTITION
+//slf021105a begin
+// Define DO_PARTITION_TABLE to cause the partition table 
+// information to be retrieved from the block driver.
+// Can define this in your sources file.
+//#define DO_PARTITION_TABLE
+// How many partitions the disk might have.  2 gives 
+// space for the "Disk" and "Boot" partitions.
+#define MAXPARTITIONS (2)
 //slf021105a end
 
 //unsigned yaffs_traceMask=0xffffffff;
-unsigned yaffs_traceMask=0;\r
+unsigned yaffs_traceMask=0;
 
 
 typedef struct
@@ -77,10 +83,10 @@ typedef struct
        BOOL dirty;
        WCHAR *fullName;
        yfsd_Volume *myVolume;
-       BOOL writePermitted;\r
-       BOOL readPermitted;\r
-       BOOL shareRead;\r
-       BOOL shareWrite;\r
+       BOOL writePermitted;
+       BOOL readPermitted;
+       BOOL shareRead;
+       BOOL shareWrite;
 
 }      yfsd_WinFile;
 
@@ -110,10 +116,10 @@ typedef struct
 
 #include <fsdmgr.h>
 
-//slf021105a begin\r
+//slf021105a begin
 //static yfsd_Volume disk_volume;
-//static yfsd_Volume boot_volume;\r
-static yfsd_Volume * disk_volumes[MAXPARTITIONS];\r
+//static yfsd_Volume boot_volume;
+static yfsd_Volume * disk_volumes[MAXPARTITIONS];
 //slf021105a end;
 
 static CRITICAL_SECTION yaffsLock;
@@ -153,6 +159,49 @@ static void yfsd_CheckGuards(void)
 }
 #endif
 
+
+#ifdef MSGBOX_DISPLAY
+DWORD WINAPI yfsd_MessageThread(LPVOID param)
+{
+    yaffs_Device *dev = (yaffs_Device *)param;
+    TCHAR dataBuffer[1000];
+    Sleep(10000);
+
+    // note : if the device gets free'd from under us, we will cause an exception in the loop
+    while (1)
+    {
+        wsprintf(dataBuffer, L"nShortOpCaches %i\r\n"
+                             L"nErasedBlocks %i\r\n"
+                             L"allocationBlock %i\r\n"
+                             L"allocationPage %i\r\n"
+                             L"garbageCollectionRequired %i\r\n"
+                             L"nRetiredBlocks %i\r\n"
+                             L"cacheHits %i\r\n"
+                             L"eccFixed %i\r\n"
+                             L"eccUnfixed %i\r\n"
+                             L"tagsEccFixed %i\r\n"
+                             L"tagsEccUnfixed %i\r\n",
+                             dev->nShortOpCaches, 
+                             dev->nErasedBlocks,
+                             dev->allocationBlock,
+                             dev->allocationPage,
+                             dev->garbageCollectionRequired,
+                             dev->nRetiredBlocks,
+                             dev->cacheHits,
+                             dev->eccFixed,
+                             dev->eccUnfixed,
+                             dev->tagsEccFixed,
+                             dev->tagsEccUnfixed);
+
+        MessageBox(NULL,
+                   dataBuffer,
+                   L"YAFFS PROC INFO",
+                   MB_OK);
+        Sleep(1);
+    }
+}
+#endif
+
 void yfsd_LockWinFiles(void)
 {
        //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
@@ -212,10 +261,10 @@ yfsd_WinFile * yfsd_GetWinFile(void)
                if(!yfsd_winFile[i].isopen)
                {
                        yfsd_winFile[i].isopen = 1;
-                       yfsd_winFile[i].writePermitted = 0;\r
-                       yfsd_winFile[i].readPermitted = 0;\r
-                       yfsd_winFile[i].shareRead = 0;\r
-                       yfsd_winFile[i].shareWrite = 0;\r
+                       yfsd_winFile[i].writePermitted = 0;
+                       yfsd_winFile[i].readPermitted = 0;
+                       yfsd_winFile[i].shareRead = 0;
+                       yfsd_winFile[i].shareWrite = 0;
                        yfsd_winFile[i].dirty = 0;
                        yfsd_winFile[i].fullName = NULL;
                        yfsd_winFile[i].obj = NULL;
@@ -266,42 +315,42 @@ void yfsd_FlushAllFiles(void)
        }
        yfsd_UnlockWinFiles();
        yfsd_UnlockYAFFS();
-}\r
-\r
-//slf021104d begin\r
-//////////////////////////////////////////////////////////////////////\r
-// Search through winFiles to see if any are open.  \r
-\r
-BOOL yfsd_FilesOpen(void)\r
-{\r
-       int i;\r
-       BOOL rval;\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));\r
-\r
-       yfsd_LockWinFiles();\r
-       for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)\r
-       {\r
-               if(yfsd_winFile[i].isopen)\r
-               {\r
-                       rval = TRUE;\r
-                       break;\r
-               }\r
-       }\r
-       yfsd_UnlockWinFiles();\r
-       return rval;\r
-}\r
+}
+
+//slf021104d begin
+//////////////////////////////////////////////////////////////////////
+// Search through winFiles to see if any are open.  
+
+BOOL yfsd_FilesOpen(void)
+{
+       int i;
+       BOOL rval;
+       RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));
+
+       yfsd_LockWinFiles();
+       for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)
+       {
+               if(yfsd_winFile[i].isopen)
+               {
+                       rval = TRUE;
+                       break;
+               }
+       }
+       yfsd_UnlockWinFiles();
+       return rval;
+}
 //slf021104d end
 
 PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
 {
 
-       // todo check for bounds\r
-       //slf021104b begin\r
+       // todo check for bounds
+       //slf021104b begin
        //volName already has the initial backslash if it needs it.
-       //wcscpy(fpn,L"\\");\r
+       //wcscpy(fpn,L"\\");
        //wcscat(fpn,vol->volName);
-       wcscpy(fpn,vol->volName);\r
-       //slf021104b end\r
+       wcscpy(fpn,vol->volName);
+       //slf021104b end
        if(pathName[0] != '\\')
        {
                wcscat(fpn,L"\\");
@@ -604,116 +653,140 @@ yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
 
 BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
 {
-       //slf021104b Begin\r
-       WCHAR szName[MAX_PATH];\r
-    DWORD dwAvail;\r
-       //slf021104b end\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));\r
+       //slf021104b Begin
+       WCHAR szName[MAX_PATH];
+    DWORD dwAvail;
+       //slf021104b end
+       RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
        //slf021104b Begin filled in later.
-       //vol->volName = volName;\r
+       //vol->volName = volName;
        //slf021104b end
 
 
        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;\r
-       vol->dev.nShortOpCaches = 10; // a nice number of caches.
-
-       // nBlocks is set the total size of the disk, not the partition
-//     vol->dev.nBlocks = endBlock - startBlock + 1;
-
-//     qnand_EraseAllBlocks(&vol->dev);
+       //slf021220a Begin Cleanup block driver interface
+#if _WINCEOSVER >= 400
+       // For Win'CE 4.0 and later pass the hdsk for use by the yandif layer.
+       vol->dev.genericDevice = (PVOID)hdsk;
+#endif
+       //slf021220a End Cleanup block driver interface
 
-       yaffs_GutsInitialise(&vol->dev);
-       RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
+       //Mount/initialise YAFFs here
+       //slf021127a begin check for error returns!
+       if (ynandif_InitialiseNAND(&vol->dev))  
+       {
+       //slf021127a end check for error returns!
+               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;
+               vol->dev.nShortOpCaches = 10; // a nice number of caches.
+               vol->dev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+               vol->dev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+               vol->dev.nReservedBlocks = 5; // a nice reserve size
+
+
+               // nBlocks is set the total size of the disk, not the partition
+       //      vol->dev.nBlocks = endBlock - startBlock + 1;
+
+       //      qnand_EraseAllBlocks(&vol->dev);
+
+               //slf021127a begin check for error returns!
+               if (yaffs_GutsInitialise(&vol->dev))
+               {
+               //slf021127a end check for error returns!
+                       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));
+                       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)
+                       for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
                        {
-                               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;
+                                       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));
+                       RETAILMSG(1, (L"Blocks dead  %d empty %d full %d allocating %d dirty %d\r\n",
+                                                       deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
 
 #endif
 
+//slf021127a begin check for error returns!
+                       vol->isMounted = 1;
+               }
+       }
+//slf021127a begin check for error returns!
+       
        yfsd_UnlockYAFFS();
 
-       vol->isMounted = 1;
-       \r
+//slf021127a begin check for error returns!
+//     vol->isMounted = 1;
+//slf021127a begin check for error returns!
+       
        //slf021104b begin
-       //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);\r
-       // If the caller passed a volume name use it.\r
-       if (volName[0])\r
-        wcscpy( szName, volName);\r
-#if WINCEOSVER >= 400\r
-       // The user passed an empty volume name.  On CE 4.xx try to get\r
-       // if from the block driver (which got it from the registry).\r
-       else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL)) \r
-#else\r
-       else\r
-#endif\r
-       { \r
-               // Didn't get a volume name so use "Disk" by default.\r
-        wcscpy( szName, YFSD_DISK_NAME);\r
-    }    \r
-       vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);\r
+       //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
+       // If the caller passed a volume name use it.
+       if (volName[0])
+        wcscpy( szName, volName);
+#if WINCEOSVER >= 400
+       // The user passed an empty volume name.  On CE 4.xx try to get
+       // if from the block driver (which got it from the registry).
+       else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL)) 
+#else
+       else
+#endif
+       { 
+               // Didn't get a volume name so use "Disk" by default.
+        wcscpy( szName, YFSD_DISK_NAME);
+    }    
+       vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);
        //slf021104b end
 
        if(vol->mgrVolume)
-       {\r
-               //slf021104b Begin\r
+       {
+               //slf021104b Begin
                // Get some space for the volume name.
-        vol->volName = malloc( MAX_PATH * sizeof(WCHAR));\r
-        if (vol->volName) \r
-               {\r
-#if WINCEOSVER >= 400\r
-                       // Get the name we were really mounted under.\r
-            FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);\r
-\r
-                       // If we got mounted as root then throw away the backslash\r
-                       // so we won't get a double backslash when volName is\r
-                       // prepended to the path in the full path name calculation\r
-                       // that is used for shell callbacks.\r
-                       if (0 == wcscmp(vol->volName,L"\\"))\r
-                               vol->volName[0] = 0;\r
-#else\r
-                       // Use the name we asked to be mounted under for\r
-                       // our root.  \r
-                       wcscpy(vol->volName,L"\\");\r
-                       wcscat(vol->volName, szName);\r
-#endif\r
-               }\r
-               //slf021104b end\r
+        vol->volName = malloc( MAX_PATH * sizeof(WCHAR));
+        if (vol->volName) 
+               {
+#if WINCEOSVER >= 400
+                       // Get the name we were really mounted under.
+            FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);
+
+                       // If we got mounted as root then throw away the backslash
+                       // so we won't get a double backslash when volName is
+                       // prepended to the path in the full path name calculation
+                       // that is used for shell callbacks.
+                       if (0 == wcscmp(vol->volName,L"\\"))
+                               vol->volName[0] = 0;
+#else
+                       // Use the name we asked to be mounted under for
+                       // our root.  
+                       wcscpy(vol->volName,L"\\");
+                       wcscat(vol->volName, szName);
+#endif
+               }
+               //slf021104b end
                return TRUE;
        }
        else
@@ -727,14 +800,14 @@ BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock,
 
 BOOL YFSD_MountDisk(HDSK hdsk)
 {
-//slf021105a begin\r
-#ifdef DO_PARTITION_TABLE\r
-       ynandif_partition PartTable[MAXPARTITIONS];\r
-       DWORD dwAvail;\r
-       int i;\r
-       BOOL rval = FALSE;\r
-#endif\r
-//slf021105a end\r
+//slf021105a begin
+#ifdef DO_PARTITION_TABLE
+       ynandif_partition PartTable[MAXPARTITIONS];
+       DWORD dwAvail;
+       int i;
+       BOOL rval = FALSE;
+#endif
+//slf021105a end
        int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
        //int i;
        // Called to mount a disk.
@@ -752,102 +825,107 @@ BOOL YFSD_MountDisk(HDSK hdsk)
                yfsd_InitialiseWinFiles();
                yaffsLockInited = 1;
        }
-\r
-       //slf021105a begin\r
-       memset(disk_volumes,0,sizeof(disk_volumes));\r
-#ifdef DO_PARTITION_TABLE\r
-       memset(&PartTable,0,sizeof(PartTable));\r
-       // Call the block driver to get the partition table from it.\r
-    if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL)) \r
-       {\r
-               // Scan throught the table it return.\r
-               for (i=0; i<MAXPARTITIONS; i++)\r
-               {\r
-                       // At the very lease check that the end is later than the beginning\r
-                       // and don't let it start at 0.  \r
-                       // Probably could do more thorough checking but I trust the block\r
-                       // driver.\r
-                       if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))\r
-                       {\r
-                               // Found a partion.  Get a volume structure to hold it.\r
-                               disk_volumes[i] = malloc(sizeof(yfsd_Volume));\r
-                               if (disk_volumes[i])\r
-                               {\r
-                                       memset(disk_volumes[i],0,sizeof(yfsd_Volume));\r
-                                       // Go init the volume.  Note that if the block driver wants the\r
-                                       // name to come from the registry it will have returned an\r
-                                       // empty name string.\r
-                                       YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);\r
-                                       if (disk_volumes[i]->isMounted)\r
-                                               rval = TRUE; //Hey, we found at least on partition.\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       return rval;\r
-\r
+
+       //slf021105a begin
+       memset(disk_volumes,0,sizeof(disk_volumes));
+#ifdef DO_PARTITION_TABLE
+       memset(&PartTable,0,sizeof(PartTable));
+       // Call the block driver to get the partition table from it.
+    if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL)) 
+       {
+               // Scan throught the table it return.
+               for (i=0; i<MAXPARTITIONS; i++)
+               {
+                       // At the very lease check that the end is later than the beginning
+                       // and don't let it start at 0.  
+                       // Probably could do more thorough checking but I trust the block
+                       // driver.
+                       if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))
+                       {
+                               // Found a partion.  Get a volume structure to hold it.
+                               disk_volumes[i] = malloc(sizeof(yfsd_Volume));
+                               if (disk_volumes[i])
+                               {
+                                       memset(disk_volumes[i],0,sizeof(yfsd_Volume));
+                                       // Go init the volume.  Note that if the block driver wants the
+                                       // name to come from the registry it will have returned an
+                                       // empty name string.
+                                       YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);
+                                       if (disk_volumes[i]->isMounted)
+                                               rval = TRUE; //Hey, we found at least on partition.
+                               }
+                       }
+               }
+       }
+
+       return rval;
+
 #else
 #ifdef DISABLE_BOOT_PARTITION
-       // Only want disk volume\r
-       disk_volumes[0] = malloc(sizeof(yfsd_Volume));\r
-       if (disk_volumes[0])\r
-       {\r
-               memset(disk_volumes[0],0,sizeof(yfsd_Volume));\r
-               YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);\r
-\r
-               if(disk_volumes[0].isMounted)\r
-               {\r
-                       return TRUE;\r
-               }\r
-       }\r
-       if (disk_volumes[0])\r
-       {\r
-               free(disk_volumes[0];\r
-               disk_volumes[0] = NULL;\r
-       }\r
-#else\r
-       // Want both boot and disk\r
-       disk_volumes[0] = malloc(sizeof(yfsd_Volume));\r
-       disk_volumes[1] = malloc(sizeof(yfsd_Volume));\r
-       if (disk_volumes[0] && disk_volumes[1])\r
-       {\r
-               memset(disk_volumes[0],0,sizeof(yfsd_Volume));\r
-               memset(disk_volumes[1],0,sizeof(yfsd_Volume));\r
-               YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);\r
-               YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);\r
-\r
-               if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)\r
-               {\r
-                       return TRUE;\r
-               }\r
-       }\r
-\r
-       // If we got this far something went wrong.  Make sure to \r
-       // free any memory we allocated.\r
-       if (disk_volumes[0])\r
-       {\r
-               if (disk_volumes[0]->volName)\r
-               {\r
-                       free(disk_volumes[0]->volName);\r
-               }\r
-               free(disk_volumes[0]);\r
-               disk_volumes[0] = NULL;\r
-       }\r
-       if (disk_volumes[1])\r
-       {\r
-               if (disk_volumes[1]->volName)\r
-               {\r
-                       free(disk_volumes[1]->volName);\r
-               }\r
-               free(disk_volumes[1]);\r
-               disk_volumes[1] = NULL;\r
-       }\r
-#endif\r
-\r
-       return FALSE;\r
-\r
-       // Only want disk volume\r
+       // Only want disk volume
+       disk_volumes[0] = malloc(sizeof(yfsd_Volume));
+       if (disk_volumes[0])
+       {
+               memset(disk_volumes[0],0,sizeof(yfsd_Volume));
+               YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);
+
+               if(disk_volumes[0].isMounted)
+               {
+                       return TRUE;
+               }
+       }
+       if (disk_volumes[0])
+       {
+               free(disk_volumes[0];
+               disk_volumes[0] = NULL;
+       }
+#else
+       // Want both boot and disk
+       disk_volumes[0] = malloc(sizeof(yfsd_Volume));
+       disk_volumes[1] = malloc(sizeof(yfsd_Volume));
+       if (disk_volumes[0] && disk_volumes[1])
+       {
+               memset(disk_volumes[0],0,sizeof(yfsd_Volume));
+               memset(disk_volumes[1],0,sizeof(yfsd_Volume));
+               YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
+               YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
+
+#ifdef MSGBOX_DISPLAY
+        // pass the device we are sniffing to the thread
+        CreateThread(NULL, 0, yfsd_MessageThread, (LPVOID)&disk_volumes[0]->dev, 0, NULL);
+#endif
+
+               if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)
+               {
+                       return TRUE;
+               }
+       }
+
+       // If we got this far something went wrong.  Make sure to 
+       // free any memory we allocated.
+       if (disk_volumes[0])
+       {
+               if (disk_volumes[0]->volName)
+               {
+                       free(disk_volumes[0]->volName);
+               }
+               free(disk_volumes[0]);
+               disk_volumes[0] = NULL;
+       }
+       if (disk_volumes[1])
+       {
+               if (disk_volumes[1]->volName)
+               {
+                       free(disk_volumes[1]->volName);
+               }
+               free(disk_volumes[1]);
+               disk_volumes[1] = NULL;
+       }
+#endif
+
+       return FALSE;
+
+       // Only want disk volume
 //     YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
 //
 //     
@@ -865,11 +943,11 @@ BOOL YFSD_MountDisk(HDSK hdsk)
 //     {
 //             return TRUE;
 //     }
-//#endif\r
+//#endif
 //
 //     return FALSE;
-#endif\r
-//slf021105a end\r
+#endif
+//slf021105a end
 
 //     yfsd_SetGuards();
 
@@ -880,46 +958,49 @@ BOOL YFSD_MountDisk(HDSK hdsk)
 
 BOOL YFSD_UnmountDisk(HDSK hdsk)
 {
-//slf021105a begin\r
-       int i;\r
-//slf021105a end\r
+//slf021105a begin
+       int i;
+//slf021105a end
        RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
        
-       //slf021104d begin\r
-       // If there are any files open don't let them dismount\r
-       // it or the system will get very confused.  \r
-       if (yfsd_FilesOpen())\r
-               return FALSE;\r
-\r
-       //yfsd_FlushAllFiles();\r
-       //slf021104d end\r
-\r
-       yfsd_LockYAFFS();\r
-//slf021105a begin\r
-//     yaffs_Deinitialise(&disk_volume.dev);\r
-//     yaffs_Deinitialise(&boot_volume.dev);\r
+       //slf021104d begin
+       // If there are any files open don't let them dismount
+       // it or the system will get very confused.  
+       if (yfsd_FilesOpen())
+               return FALSE;
+
+       //yfsd_FlushAllFiles();
+       //slf021104d end
+
+       yfsd_LockYAFFS();
+//slf021105a begin
+//     yaffs_Deinitialise(&disk_volume.dev);
+//     yaffs_Deinitialise(&boot_volume.dev);
 //     yfsd_UnlockYAFFS();
 //
-//     FSDMGR_DeregisterVolume(disk_volume.mgrVolume);\r
-//     FSDMGR_DeregisterVolume(boot_volume.mgrVolume);\r
-\r
-       // Walk through the partions deinitializing, deregistering\r
-       // and freeing them.\r
-       for (i=0; i<MAXPARTITIONS; i++)\r
-       {\r
-               if (disk_volumes[i])\r
-               {\r
-                       yaffs_Deinitialise(&(disk_volumes[i]->dev));\r
-                       FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);\r
-                       if (disk_volumes[i]->volName)\r
-                       {\r
-                               free(disk_volumes[i]->volName);\r
-                       }\r
-                       free(disk_volumes[i]);\r
-                       disk_volumes[i] = NULL;\r
-               }\r
-       }\r
-       yfsd_UnlockYAFFS();\r
+//     FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
+//     FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
+
+       // Walk through the partions deinitializing, deregistering
+       // and freeing them.
+       for (i=0; i<MAXPARTITIONS; i++)
+       {
+               if (disk_volumes[i])
+               {
+                       yaffs_Deinitialise(&(disk_volumes[i]->dev));
+//slf021220a Begin Cleanup block driver interface
+                       ynandif_DeinitialiseNAND(&(disk_volumes[i]->dev));
+//slf021220a end Cleanup block driver interface
+                       FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);
+                       if (disk_volumes[i]->volName)
+                       {
+                               free(disk_volumes[i]->volName);
+                       }
+                       free(disk_volumes[i]);
+                       disk_volumes[i] = NULL;
+               }
+       }
+       yfsd_UnlockYAFFS();
 //slf021105a end
        return TRUE;
 }
@@ -1007,22 +1088,26 @@ BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTE
 }
 
 
-BOOL yfsd_RemoveObjectW(PVOLUME pVolume, PCWSTR pathName)
+BOOL YFSD_RemoveDirectoryW(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));
-
+       RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory (%s)\r\n", pathName));
+       
        yfsd_LockYAFFS();
 
        obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
        if(!obj)
        {
-               SetLastError(ERROR_FILE_NOT_FOUND);
+               SetLastError(ERROR_PATH_NOT_FOUND);
+               result = FALSE;
+       }
+       else if (obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+       {
+               SetLastError(ERROR_ACCESS_DENIED);
                result = FALSE;
        }
        else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
@@ -1044,23 +1129,12 @@ BOOL yfsd_RemoveObjectW(PVOLUME pVolume, PCWSTR pathName)
                {
                        result = yaffs_Unlink(parent,name);
                        if(!result)
-                               SetLastError(ERROR_ACCESS_DENIED);
+                               SetLastError(ERROR_DIR_NOT_EMPTY);
                }
        }
 
        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;
@@ -1081,8 +1155,7 @@ BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
                        yfsd_ShellDirectoryChanged(pVolume,fpn);
        }
        
-       return result;
-
+       return result ? TRUE : FALSE;
 }
 
 
@@ -1180,10 +1253,51 @@ BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAt
 
 BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
 {
-       BOOL result;
+       int result = FALSE;
+       yaffs_Object *parent = NULL;
+       yaffs_Object *obj;
+       char name[YFSD_NAME_LENGTH+1];
+
        RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
 
-       result =  yfsd_RemoveObjectW(pVolume, pwsFileName);
+       yfsd_LockYAFFS();
+
+       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+       if(!obj)
+       {
+               SetLastError(ERROR_FILE_NOT_FOUND);
+               result = FALSE;
+       }
+       else if (obj->variantType != YAFFS_OBJECT_TYPE_FILE)
+       {
+               SetLastError(ERROR_ACCESS_DENIED);
+               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,pwsFileName,name,YFSD_NAME_LENGTH);
+
+               if(parent && yfsd_NameIsValid(name))
+               {
+                       result = yaffs_Unlink(parent,name);
+                       if(!result)
+                               SetLastError(ERROR_ACCESS_DENIED);
+               }
+       }
+
+       yfsd_UnlockYAFFS();
+
        if(result && pVolume->shellFunction)
        {
                        FILECHANGEINFO fc;
@@ -1204,7 +1318,7 @@ BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
                        yfsd_ShellDirectoryChanged(pVolume,fpn);
        }
 
-       return result;
+       return result ? TRUE : FALSE;
 }
 
 BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
@@ -1282,18 +1396,18 @@ BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName
 
 BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
 {
-       //slf021104c begin\r
-    BOOL fSuccess;\r
-       //slf021104c end\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));\r
-\r
        //slf021104c begin
-    if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))\r
-        fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);\r
-       return fSuccess;\r
+    BOOL fSuccess;
+       //slf021104c end
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
+
+       //slf021104c begin
+    if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))
+        fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);
+       return fSuccess;
        //return FALSE;
-       //slf021104c end\r
+       //slf021104c end
 }
 
 BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
@@ -1538,7 +1652,7 @@ BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
 
                                pfd->nFileSizeHigh = 0;
                                pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
-                               pfd->dwOID = 0; // wtf is this???
+                               pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
 
                                MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
 
@@ -1609,7 +1723,7 @@ BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
 
                                pfd->nFileSizeHigh = 0;
                                pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
-                               pfd->dwOID = 0; // wtf is this???
+                               pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
 
                                MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
 
@@ -1668,6 +1782,7 @@ HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWI
                {
                        free(pSearch);
                        pSearch = NULL;
+                       SetLastError(ERROR_PATH_NOT_FOUND);
                }
        }
 
@@ -1678,19 +1793,26 @@ HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWI
        if(pSearch)
        {
                found = yfsd_DoFindFile(pSearch,pfd);
-       }
 
-       if(found)
-       {
-               h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
-       }
+               if(found)
+               {
+                       h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
+                       if(h == INVALID_HANDLE_VALUE)
+                       {
+                               SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
+                       }
+               }
+               else
+               {
+                       SetLastError(ERROR_FILE_NOT_FOUND);
+               }
 
-       if(h == INVALID_HANDLE_VALUE && pSearch)
-       {
-               yfsd_DeleteFinder(pSearch);
-               SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
-       }
+               if(h == INVALID_HANDLE_VALUE)
+               {
+                       yfsd_DeleteFinder(pSearch);
+               }
 
+       }
 
 
        return h;
@@ -1740,19 +1862,20 @@ HANDLE YFSD_CreateFileW(
        unsigned modifiedTime[2];
        unsigned objSize;
 
-       BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;\r
-       BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;\r
-       BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;\r
-       BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;\r
-\r
-       BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;\r
+       BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
+       BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;
+       BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;
+       BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;
+
+       BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;
 
        BOOL fileCreated = FALSE;
+       
+       BOOL fAlwaysCreateOnExistingFile = FALSE;
+       BOOL fTruncateExistingFile = 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)
        {
@@ -1778,12 +1901,18 @@ HANDLE YFSD_CreateFileW(
        if(parent && yfsd_NameIsValid(name))
        {
 
+               //slf021220b begin Fix still more bugs in CreateFile.
+               // Get the object for this file if it exists (only once).
+               obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+               //slf021220b end Fix still more bugs in CreateFile.
                if(dwCreate == CREATE_NEW)
                {
                        RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
 
                        //slf021101c begin
-                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b end Fix still more bugs in CreateFile.
                        if(!obj)
                        {
                                obj = yaffs_MknodFile(parent,name,mode,0,0);
@@ -1791,16 +1920,28 @@ HANDLE YFSD_CreateFileW(
                                        SetLastError(ERROR_DISK_FULL);
                                fileCreated = TRUE;
                        }
-                       else
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
                        {
                                obj = NULL;
                                SetLastError(ERROR_ALREADY_EXISTS);
-                       }\r
+                       }
+                       //slf021220b end Fix still more bugs in CreateFile.
+                       else
+                       {
+                               obj = NULL;
+                               //slf021220b begin Fix still more bugs in CreateFile.
+                               //Match CE FAT error return SetLastError(ERROR_ALREADY_EXISTS);
+                               SetLastError(ERROR_FILE_EXISTS);
+                               //slf021220b begin Fix still more bugs in CreateFile.
+                       }
                        //slf021101c end
                }
                else if( dwCreate == OPEN_ALWAYS)
                {
-                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b end Fix still more bugs in CreateFile.
                        if(!obj)
                        {
                                RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
@@ -1810,6 +1951,13 @@ HANDLE YFSD_CreateFileW(
                                fileCreated = TRUE;
 
                        }
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+                       {
+                               obj = NULL;
+                               SetLastError(ERROR_ACCESS_DENIED);
+                       }
+                       //slf021220b end Fix still more bugs in CreateFile.
                        else
                        {
                                RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
@@ -1818,34 +1966,55 @@ HANDLE YFSD_CreateFileW(
                else if(dwCreate == OPEN_EXISTING)
                {
                        RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
-                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b end Fix still more bugs in CreateFile.
                        if(!obj)
                                SetLastError(ERROR_FILE_NOT_FOUND);
+               //slf021220b begin Fix still more bugs in CreateFile.
             //slf021101c begin
-                       else
-                               if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
-                               {
-                                       SetLastError(ERROR_ACCESS_DENIED);
-                                       obj = NULL;
-                               }
+           //                  else
+           //                          if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
+           //                          {
+           //                                  SetLastError(ERROR_ACCESS_DENIED);
+           //                                  obj = NULL;
+           //                          }
             //slf021101c end
+                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+                       {
+                               SetLastError(ERROR_ACCESS_DENIED);
+                               obj = NULL;
+                       }
+               //slf021220b end Fix still more bugs in CreateFile.
                }
                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)
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //if(obj)
+                       if (!writePermitted || (obj  && (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)))
                        {
-                               yaffs_ResizeFile(obj,0);
+                               obj = NULL;
+                               SetLastError(ERROR_ACCESS_DENIED);
                        }
-                       else
+                       else if(obj)
+                       //slf021220b end Fix still more bugs in CreateFile.
+                       {
+                               // Indicate that file is to be truncated.  This will happen later on assuming
+                               // that a sharing violation does not occur and that we can get a file handle.
+                               fTruncateExistingFile = TRUE;
+                       }
+                       else 
                        {
                                SetLastError(ERROR_FILE_NOT_FOUND);
                        }
                }
                else if(dwCreate == CREATE_ALWAYS)
                {
-                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+                       //slf021220b end Fix still more bugs in CreateFile.
 
                        if(!obj)
                        {
@@ -1855,13 +2024,19 @@ HANDLE YFSD_CreateFileW(
                                        SetLastError(ERROR_DISK_FULL);
                                fileCreated = TRUE;
                        }
-                       else
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
                        {
+                               obj = NULL;
+                               SetLastError(ERROR_ACCESS_DENIED);
+                       }
+                       //slf021220b end Fix still more bugs in CreateFile.
+                       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,1);
+                               // Indicate that file is to be recreated.  This will happen later on assuming
+                               // that a sharing violation does not occur and that we can get a file handle.
+                               fAlwaysCreateOnExistingFile = TRUE;
                        }
                }
                else
@@ -1875,40 +2050,42 @@ HANDLE YFSD_CreateFileW(
                RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
                SetLastError(ERROR_PATH_NOT_FOUND);
        }
-\r
-       if(obj)\r
-       {\r
-                       int i;\r
-                       yfsd_WinFile *p;\r
-                       openRead = openWrite =0;\r
-                       openReadAllowed = openWriteAllowed = 1;\r
-\r
-                       for(i = 0; i < MAX_WIN_FILE; i++)\r
-                       {\r
-                                       p = &yfsd_winFile[i];\r
-\r
-                                       if(p->obj == obj)\r
-                                       {\r
-                                               if (p->readPermitted) openRead = 1;\r
-                                               if (p->writePermitted) openWrite = 1;\r
-                                               if (!p->shareRead) openReadAllowed = 0;\r
-                                               if (!p->shareWrite) openWriteAllowed = 0;\r
-                                       }\r
-\r
-                       }\r
-\r
-                       // Now we test if the share works out.\r
-\r
-                       if((openRead && !shareRead) ||   // already open for read, but we are not prepared to share it for read\r
-                          (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write\r
-                          (!openReadAllowed && readPermitted) || // already open with read sharing not permitted\r
-                          (!openWriteAllowed && writePermitted)) // same... write\r
-                       {\r
-                               SetLastError(ERROR_ACCESS_DENIED);\r
-                               obj = NULL;\r
-                       }\r
-\r
-\r
+
+       if(obj)
+       {
+                       int i;
+                       yfsd_WinFile *p;
+                       openRead = openWrite =0;
+                       openReadAllowed = openWriteAllowed = 1;
+
+                       for(i = 0; i < MAX_WIN_FILE; i++)
+                       {
+                                       p = &yfsd_winFile[i];
+
+                                       if(p->obj == obj)
+                                       {
+                                               if (p->readPermitted) openRead = 1;
+                                               if (p->writePermitted) openWrite = 1;
+                                               if (!p->shareRead) openReadAllowed = 0;
+                                               if (!p->shareWrite) openWriteAllowed = 0;
+                                       }
+
+                       }
+
+                       // Now we test if the share works out.
+
+                       if((openRead && !shareRead) ||   // already open for read, but we are not prepared to share it for read
+                          (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write
+                          (!openReadAllowed && readPermitted) || // already open with read sharing not permitted
+                          (!openWriteAllowed && writePermitted)) // same... write
+                       {
+                               //slf021220c begin Fix error code for new sharing mode check code.
+                               SetLastError(ERROR_SHARING_VIOLATION);
+                               //slf021220c end Fix error code for new sharing mode check code.
+                               obj = NULL;
+                       }
+
+
        }
        if(obj)
        {
@@ -1928,12 +2105,30 @@ HANDLE YFSD_CreateFileW(
                if(handle != INVALID_HANDLE_VALUE)
                {
                        RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
+
+                       if (fTruncateExistingFile)
+                       {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - TRUNCATE_EXISTING - truncating existing file\r\n"));
+                               yaffs_ResizeFile(obj,0);
+                       }
+                       
+                       if (fAlwaysCreateOnExistingFile)
+                       {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - CREATE_ALWAYS - zapping existing file\r\n"));
+                               obj->st_mode = mode;
+                               obj->dirty = 1;
+                               yaffs_ResizeFile(obj,0);
+                               yaffs_FlushFile(obj,1);
+                       }
+                                               
                        f->obj = obj;
                        f->offset = 0;
-                       f->writePermitted = writePermitted;\r
-                       f->readPermitted = writePermitted;\r
-                       f->shareRead= shareRead;\r
-                       f->shareWrite = shareWrite;\r
+                       f->writePermitted = writePermitted;
+                       //slf021220d begin oops typo.
+                       f->readPermitted = readPermitted;
+                       //slf021220d end oops typo.
+                       f->shareRead= shareRead;
+                       f->shareWrite = shareWrite;
                        f->myVolume = pVolume;
                        obj->inUse++;
 
@@ -2368,12 +2563,8 @@ BOOL YFSD_GetFileInformationByHandle(
        pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj); 
        pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
        pFileInfo->nFileIndexHigh = 0; 
-       pFileInfo->nFileIndexLow = pFile->obj->objectId;\r
-//slf021104a Begin Window CE 4.0 added an additional field.\r
-#if _WINCEOSVER >= 400
-       pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);\r
-#endif\r
-//slf021104a end\r
+       pFileInfo->nFileIndexLow = pFile->obj->objectId;
+       pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);
 
        yfsd_UnlockYAFFS();