*** empty log message ***
[yaffs/.git] / wince / yaffsfsd.c
index dc64c1aa03a792d9a1860824d2c3b607e8ab9d17..7e202bfe17e60ab44912a09b6ec8b0af253b4830 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * YAFFS: Yet another FFS. A NAND-flash specific file system.\r
- * yaffsfsd.c: The FSD layer for the WinCE version of YAFFS.\r
+ * ynandif.c: NAND interface functions for the WinCE port of YAFFS.\r
  *\r
  * Copyright (C) 2002 Trimble Navigation Ltd.\r
  *\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
+ * 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
  */
 #include <windows.h>
 #include <extfile.h>
 #include <yaffs_guts.h>
-#include <ynandif.h>
+#include <ynandif.h>\r
+//slf021104b begin\r
+#include <diskio.h>\r
+//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"
+#define YFSD_BOOT_NAME L"Boot"\r
 
 #define PARTITION_START_NUMBER (1280)          
 
-#define MSGSTATE 1
+//#define MSGSTATE 1\r
+#define MSGSTATE 0
 //#define DISABLE_BOOT_PARTITION\r
-\r
-unsigned yaffs_traceMask=0xffffffff;
+//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
+//slf021105a end
+
+//unsigned yaffs_traceMask=0xffffffff;
+unsigned yaffs_traceMask=0;\r
 
 
 typedef struct
@@ -59,10 +74,13 @@ typedef struct
        yaffs_Object *obj;
        DWORD offset;
        BOOL isopen;
-       BOOL writePermitted;
        BOOL dirty;
        WCHAR *fullName;
        yfsd_Volume *myVolume;
+       BOOL writePermitted;\r
+       BOOL readPermitted;\r
+       BOOL shareRead;\r
+       BOOL shareWrite;\r
 
 }      yfsd_WinFile;
 
@@ -92,9 +110,11 @@ typedef struct
 
 #include <fsdmgr.h>
 
-
-static yfsd_Volume disk_volume;
-static yfsd_Volume boot_volume;
+//slf021105a begin\r
+//static yfsd_Volume disk_volume;
+//static yfsd_Volume boot_volume;\r
+static yfsd_Volume * disk_volumes[MAXPARTITIONS];\r
+//slf021105a end;
 
 static CRITICAL_SECTION yaffsLock;
 static CRITICAL_SECTION winFileLock;
@@ -192,7 +212,10 @@ yfsd_WinFile * yfsd_GetWinFile(void)
                if(!yfsd_winFile[i].isopen)
                {
                        yfsd_winFile[i].isopen = 1;
-                       yfsd_winFile[i].writePermitted = 0;
+                       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].dirty = 0;
                        yfsd_winFile[i].fullName = NULL;
                        yfsd_winFile[i].obj = NULL;
@@ -238,19 +261,47 @@ void yfsd_FlushAllFiles(void)
                if(yfsd_winFile[i].isopen &&
                   yfsd_winFile[i].obj)
                {
-                       yaffs_FlushFile(yfsd_winFile[i].obj);
+                       yaffs_FlushFile(yfsd_winFile[i].obj,1);
                }
        }
        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 end
 
 PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
 {
 
-       // todo check for bounds
-       wcscpy(fpn,L"\\");
-       wcscat(fpn,vol->volName);
+       // todo check for bounds\r
+       //slf021104b begin\r
+       //volName already has the initial backslash if it needs it.
+       //wcscpy(fpn,L"\\");\r
+       //wcscat(fpn,vol->volName);
+       wcscpy(fpn,vol->volName);\r
+       //slf021104b end\r
        if(pathName[0] != '\\')
        {
                wcscat(fpn,L"\\");
@@ -263,7 +314,7 @@ PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
 
 
 // FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
-\r
+
 void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
 {
        
@@ -347,15 +398,15 @@ void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
 
 
 }
-\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
+
+
+// Minimal name test for now
+BOOL yfsd_NameIsValid (const char *name)
+{
+       int length = strlen(name);
+
+       return (length > 0 && length <= YFSD_NAME_LENGTH);
+
 }
 
 // File attributes:
@@ -375,58 +426,58 @@ BOOL yfsd_NameIsValid (const char *name)
 //
 //
 // 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
+
+// The following are valid ones we get presented with,
+// but must filter out the stuff we don't unserstand
+//#define FILE_ATTRIBUTE_READONLY             0x00000001  
+//#define FILE_ATTRIBUTE_HIDDEN               0x00000002  
+//#define FILE_ATTRIBUTE_SYSTEM               0x00000004  
+//#define FILE_ATTRIBUTE_DIRECTORY            0x00000010  
+//#define FILE_ATTRIBUTE_ARCHIVE              0x00000020  
+//#define FILE_ATTRIBUTE_INROM                           0x00000040
+//#define FILE_ATTRIBUTE_ENCRYPTED            0x00000040  
+//#define FILE_ATTRIBUTE_NORMAL               0x00000080  
+//#define FILE_ATTRIBUTE_TEMPORARY            0x00000100  
+//#define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200  
+//#define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400  
+//#define FILE_ATTRIBUTE_COMPRESSED           0x00000800  
+//#define FILE_ATTRIBUTE_OFFLINE              0x00001000  
+//#define FILE_ATTRIBUTE_ROMSTATICREF            0x00001000
+//#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000  
+//#define FILE_ATTRIBUTE_ROMMODULE                       0x00002000
+
+
+BOOL yfsd_CheckValidAttributes(DWORD attribs)
+{
+
+       RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
+
+#if 0
+               // If NORMAL, then nothing else
+               if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
+                       return FALSE;
+               if(attribs == FILE_ATTRIBUTE_NORMAL) 
+                       return TRUE;
+#endif
+               // Check that the bits are in the valid set
+               if(attribs & ~(0x3FE7))
+                       return FALSE;
+
+               return TRUE;
+
 }
 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
+               result = obj->st_mode & 
+                                       (FILE_ATTRIBUTE_READONLY | 
+                                        FILE_ATTRIBUTE_ARCHIVE | 
+                                        FILE_ATTRIBUTE_HIDDEN |
                                         FILE_ATTRIBUTE_SYSTEM);
-\r
-               if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;\r
+
+               if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
 
                if(result & ~FILE_ATTRIBUTE_NORMAL)
                { 
@@ -436,7 +487,7 @@ DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
                {
                        result = FILE_ATTRIBUTE_NORMAL;
                }
-\r
+
 
                return result;
 }
@@ -496,7 +547,7 @@ yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *p
 
        RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
        // start at the root of this device
-       current = yaffs_Root(device);\r
+       current = yaffs_Root(device);
        *processed = '\0';
 
        do
@@ -553,8 +604,14 @@ yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
 
 BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
 {
-       RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
-       vol->volName = 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 filled in later.
+       //vol->volName = volName;\r
+       //slf021104b end
 
 
        yfsd_LockYAFFS();
@@ -568,7 +625,8 @@ BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock,
        vol->dev.initialiseNAND = ynandif_InitialiseNAND;
        vol->dev.startBlock = startBlock;
        if (endBlock != -1)
-               vol->dev.endBlock = endBlock;
+               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;
@@ -611,11 +669,51 @@ BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock,
        yfsd_UnlockYAFFS();
 
        vol->isMounted = 1;
-       
-       vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
+       \r
+       //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
+       //slf021104b end
 
        if(vol->mgrVolume)
-       {
+       {\r
+               //slf021104b Begin\r
+               // 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
                return TRUE;
        }
        else
@@ -629,6 +727,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
        int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
        //int i;
        // Called to mount a disk.
@@ -646,29 +752,124 @@ BOOL YFSD_MountDisk(HDSK hdsk)
                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;
-       }
+\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
 #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;
+#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
+//     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\r
+//
+//     return FALSE;
+#endif\r
+//slf021105a end\r
 
 //     yfsd_SetGuards();
 
@@ -679,17 +880,47 @@ BOOL YFSD_MountDisk(HDSK hdsk)
 
 BOOL YFSD_UnmountDisk(HDSK hdsk)
 {
+//slf021105a begin\r
+       int i;\r
+//slf021105a end\r
        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);
+       //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
+//     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
+//slf021105a end
        return TRUE;
 }
 
@@ -711,22 +942,35 @@ BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTE
 
        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)
+       //slf021101b begin 
+       if (parent)
        {
-               objSize = yaffs_GetObjectFileLength(newDir);
-               attribs = yfsd_GetObjectWinAttributes(newDir);
-               modifiedTime[0] = newDir->win_mtime[0];\r
-               modifiedTime[1] = newDir->win_mtime[1];\r
+               if(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];
+                                modifiedTime[1] = newDir->win_mtime[1];
+                       }
+                       else
+                       {
+                               if(yaffs_FindObjectByName(parent,name))
+                                       SetLastError(ERROR_ALREADY_EXISTS);
+                               else
+                                       SetLastError(ERROR_DISK_FULL);
+                       }
+               }
+               else
+                       SetLastError(ERROR_INVALID_NAME);
        }
        else
        {
                SetLastError(ERROR_PATH_NOT_FOUND);
        }
+    //slf021101b end
 
        yfsd_UnlockYAFFS();
 
@@ -752,10 +996,12 @@ BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTE
 
        }
 
-       if(parent && !newDir)
-       {
-                       SetLastError(ERROR_DISK_FULL);
-       }
+//slf021101b begin 
+//     if(parent && !newDir)
+//     {
+//                     SetLastError(ERROR_DISK_FULL);
+//     }
+//slf021101b end
 
        return newDir ? TRUE : FALSE;
 }
@@ -871,19 +1117,19 @@ DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
 
 BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
 {
-       yaffs_Object *obj = NULL;\r
-       DWORD mtime[2];\r
-       DWORD attribs;\r
+       yaffs_Object *obj = NULL;
+       DWORD mtime[2];
+       DWORD attribs;
        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
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
+
+       if(!yfsd_CheckValidAttributes(dwFileAttributes))
+       {
+                       SetLastError(ERROR_INVALID_PARAMETER);
+                       return FALSE;
        }
 
        yfsd_LockYAFFS();
@@ -894,11 +1140,11 @@ BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAt
        {
                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
+               result = yaffs_FlushFile(obj,0);
+               attribs = yfsd_GetObjectWinAttributes(obj);
+               objSize = yaffs_GetObjectFileLength(obj);
+               mtime[0] = obj->win_mtime[0];
+               mtime[1] = obj->win_mtime[1];
        }
        else
        {
@@ -971,7 +1217,7 @@ BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName
        int result = 0;
        int objIsDir = 0;
        DWORD attribs;
-       DWORD objSize;\r
+       DWORD objSize;
        DWORD mtime[2];
 
        RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
@@ -994,9 +1240,9 @@ BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName
                {
                        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
+                       objSize = yaffs_GetObjectFileLength(obj);
+                       mtime[0] = obj->win_mtime[0];
+                       mtime[1] = obj->win_mtime[1];
                }
        }
        else
@@ -1036,8 +1282,18 @@ BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName
 
 BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
 {
-       RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
-       return FALSE;
+       //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
+       //return FALSE;
+       //slf021104c end\r
 }
 
 BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
@@ -1232,8 +1488,8 @@ BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
 
   return found;
 }
-\r
-#if 0\r
+
+#if 0
 // slower one
 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
 {
@@ -1309,77 +1565,77 @@ out_of_here:
        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
+
+#else
+// faster one
+BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
+{
+
+       struct list_head *i;
+       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();
+
+       list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
+       {
+
+               l = list_entry(i, yaffs_Object,siblings);
+               if(!yfsd_ObjectAlreadyFound(pSearch,l))
+               {
+                       // Only look at things we have not looked at already
+                       yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
+
+                       if(regularMatch(pSearch->pattern,name))
+                       {
+                               found = 1;
+                               // 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;
+                       }
+
+               }
+
+
+       }
+
+out_of_here:
+       yfsd_UnlockYAFFS();
+
+
+       if(!found)
+       {
+               SetLastError(ERROR_NO_MORE_FILES);
+       }
+       return found;
+       
+}
+#endif
 
 HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
 {
@@ -1484,7 +1740,12 @@ HANDLE YFSD_CreateFileW(
        unsigned modifiedTime[2];
        unsigned objSize;
 
-       BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
+       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 fileCreated = FALSE;
 
@@ -1502,11 +1763,11 @@ HANDLE YFSD_CreateFileW(
                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
+       if(!yfsd_CheckValidAttributes(mode))
+       {
+                       SetLastError(ERROR_INVALID_PARAMETER);
+                       return FALSE;
+       }
 
        yfsd_LockYAFFS();
 
@@ -1516,24 +1777,26 @@ HANDLE YFSD_CreateFileW(
 
        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)
+               if(dwCreate == CREATE_NEW)
                {
                        RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
 
-                       obj = yaffs_MknodFile(parent,name,mode,0,0);
+                       //slf021101c begin
+                       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
                        if(!obj)
-                               SetLastError(ERROR_DISK_FULL);
-                       fileCreated = TRUE;
+                       {
+                               obj = yaffs_MknodFile(parent,name,mode,0,0);
+                               if(!obj)
+                                       SetLastError(ERROR_DISK_FULL);
+                               fileCreated = TRUE;
+                       }
+                       else
+                       {
+                               obj = NULL;
+                               SetLastError(ERROR_ALREADY_EXISTS);
+                       }\r
+                       //slf021101c end
                }
                else if( dwCreate == OPEN_ALWAYS)
                {
@@ -1558,6 +1821,14 @@ HANDLE YFSD_CreateFileW(
                        obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
                        if(!obj)
                                SetLastError(ERROR_FILE_NOT_FOUND);
+            //slf021101c begin
+                       else
+                               if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
+                               {
+                                       SetLastError(ERROR_ACCESS_DENIED);
+                                       obj = NULL;
+                               }
+            //slf021101c end
                }
                else if(dwCreate == TRUNCATE_EXISTING)
                {
@@ -1590,7 +1861,7 @@ HANDLE YFSD_CreateFileW(
                                obj->st_mode = mode;
                                obj->dirty = 1;
                                yaffs_ResizeFile(obj,0);
-                               yaffs_FlushFile(obj);
+                               yaffs_FlushFile(obj,1);
                        }
                }
                else
@@ -1604,7 +1875,41 @@ 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)
        {
                RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
@@ -1625,12 +1930,15 @@ HANDLE YFSD_CreateFileW(
                        RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
                        f->obj = obj;
                        f->offset = 0;
-                       f->writePermitted = writePermitted;
+                       f->writePermitted = writePermitted;\r
+                       f->readPermitted = writePermitted;\r
+                       f->shareRead= shareRead;\r
+                       f->shareWrite = shareWrite;\r
                        f->myVolume = pVolume;
                        obj->inUse++;
 
-                       modifiedTime[0] = obj->win_mtime[0];\r
-                       modifiedTime[1] = obj->win_mtime[1];\r
+                       modifiedTime[0] = obj->win_mtime[0];
+                       modifiedTime[1] = obj->win_mtime[1];
                        objSize = yaffs_GetObjectFileLength(obj);
                        RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
                }
@@ -1737,8 +2045,8 @@ BOOL yfsd_DoReadFile(
        {
                nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
                if(nread > 0)
-               {\r
-                       pFile->offset += nread;\r
+               {
+                       pFile->offset += nread;
 
                        if(pcbRead)
                        {
@@ -1748,9 +2056,9 @@ BOOL yfsd_DoReadFile(
        }
        else
        {
-               if(pcbRead) \r
-               {\r
-                       *pcbRead = maxRead;\r
+               if(pcbRead) 
+               {
+                       *pcbRead = maxRead;
                }
        }
 
@@ -1794,7 +2102,7 @@ BOOL YFSD_ReadFileWithSeek(
        DWORD dwLowOffset, 
        DWORD dwHighOffset )
 {
-       BOOL result;\r
+       BOOL result;
        DWORD rememberedOffset;
 
        RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
@@ -1813,16 +2121,16 @@ BOOL YFSD_ReadFileWithSeek(
                return FALSE;
        }
 
-       yfsd_LockYAFFS();\r
-\r
+       yfsd_LockYAFFS();
+
        rememberedOffset = pFile->offset;
 
        pFile->offset = dwLowOffset;
        // ignore high offset for now
 
        result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
-\r
-       //pFile->offset = rememberedOffset;\r
+
+       //pFile->offset = rememberedOffset;
 
        yfsd_UnlockYAFFS();
 
@@ -1909,7 +2217,7 @@ BOOL YFSD_WriteFileWithSeek(
        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)
        {
@@ -1918,15 +2226,15 @@ BOOL YFSD_WriteFileWithSeek(
        }
 
        yfsd_LockYAFFS();
-\r
-       rememberedOffset = pFile->offset;\r
+
+       rememberedOffset = pFile->offset;
 
        pFile->offset = dwLowOffset;
        // ignore high offset for now
 
        result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
-\r
-       //pFile->offset = rememberedOffset;\r
+
+       //pFile->offset = rememberedOffset;
 
        yfsd_UnlockYAFFS();
 
@@ -1953,8 +2261,8 @@ DWORD YFSD_SetFilePointer(
                return offset;
        }
 
-       yfsd_LockYAFFS();\r
-\r
+       yfsd_LockYAFFS();
+
 
        oldPos = pFile->offset;
 
@@ -2028,8 +2336,8 @@ DWORD YFSD_GetFileSize(
 
        fileSize = yaffs_GetObjectFileLength(pFile->obj);
 
-       yfsd_UnlockYAFFS();\r
-       if(pFileSizeHigh)\r
+       yfsd_UnlockYAFFS();
+       if(pFileSizeHigh)
                 *pFileSizeHigh = 0;
 
        return fileSize;
@@ -2047,35 +2355,40 @@ BOOL YFSD_GetFileInformationByHandle(
        {
                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_LockYAFFS();
+
+       pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
+       yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
+       yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
+       yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
+       pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK? 
+       pFileInfo->nFileSizeHigh = 0;
+       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
+
        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
+{
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];
+
 
        RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
 
@@ -2085,40 +2398,40 @@ BOOL YFSD_FlushFileBuffers(PFILE pFile )
                return FALSE;
        }
 
-       yfsd_LockYAFFS();\r
+       yfsd_LockYAFFS();
+
+       yaffs_FlushFile(pFile->obj,1);
+       attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+       objSize = yaffs_GetObjectFileLength(pFile->obj);
+       mtime[0] = pFile->obj->win_mtime[0];
+       mtime[1] = pFile->obj->win_mtime[1];
+       if(pFile->fullName)
+       {
+               wcscpy(fpn,pFile->fullName);
+               nameExists = 1;
+       }
+       vol = pFile->myVolume;
 
-       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
+       
+       if(vol && vol->shellFunction && nameExists)
+       {
+                       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);
+       }
+
        
        return TRUE;
 }
@@ -2154,15 +2467,15 @@ BOOL YFSD_SetFileTime(
        CONST FILETIME *pLastAccess, 
        CONST FILETIME *pLastWrite )
 {
-       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-       int nameExists = 0;\r
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
        int result = FALSE;
-       yfsd_Volume *vol = NULL;\r
-       DWORD attribs = 0;\r
-       DWORD objSize = 0;\r
-       DWORD mtime[2];\r
-\r
-       \r
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];
+
+       
        RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
 
        if(!pFile || !pFile->obj)
@@ -2174,60 +2487,60 @@ BOOL YFSD_SetFileTime(
        
        yfsd_LockYAFFS();
 
-       if(pCreation) \r
-       {\r
-                yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);\r
-               pFile->obj->dirty = 1;\r
+       if(pCreation) 
+       {
+                yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
+               pFile->obj->dirty = 1;
        }
-       if(pLastAccess)\r
-       {\r
-               yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);\r
-               pFile->obj->dirty = 1;\r
+       if(pLastAccess)
+       {
+               yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
+               pFile->obj->dirty = 1;
        }
-       if(pLastWrite)\r
-       {\r
-               yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);\r
+       if(pLastWrite)
+       {
+               yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
                pFile->obj->dirty = 1;
        }
        if(pCreation || pLastAccess || pLastWrite)
        {
-               result = yaffs_FlushFile(pFile->obj);
+               result = yaffs_FlushFile(pFile->obj,0);
        }
-\r
-       if(result)\r
+
+       if(result)
        {
-               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
+               attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+               objSize = yaffs_GetObjectFileLength(pFile->obj);
+               mtime[0] = pFile->obj->win_mtime[0];
+               mtime[1] = pFile->obj->win_mtime[1];
+               if(pFile->fullName)
+               {
+                       wcscpy(fpn,pFile->fullName);
+                       nameExists = 1;
+               }
+               vol = pFile->myVolume;
+       }
+
        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
+       if(nameExists && result && 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);
+       }
 
        return TRUE;
 }
@@ -2236,12 +2549,12 @@ 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
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];
        static unsigned char zeros[512];
 
        int result;
@@ -2303,40 +2616,40 @@ PFILE pFile )
        {
                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
+       if(retVal)
+       {
+               attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+               objSize = yaffs_GetObjectFileLength(pFile->obj);
+               mtime[0] = pFile->obj->win_mtime[0];
+               mtime[1] = pFile->obj->win_mtime[1];
+               if(pFile->fullName)
+               {
+                       wcscpy(fpn,pFile->fullName);
+                       nameExists = 1;
+               }
+               vol = pFile->myVolume;
+       }
+
+
+       yfsd_UnlockYAFFS();
+
+       if(nameExists && retVal && 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::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
 
@@ -2367,7 +2680,7 @@ BOOL YFSD_CloseFile( PFILE pFile )
        yfsd_Volume *vol = NULL;
        DWORD attribs = 0;
        DWORD objSize = 0;
-       DWORD mtime[2];\r
+       DWORD mtime[2];
 
        RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
 
@@ -2383,11 +2696,11 @@ BOOL YFSD_CloseFile( PFILE pFile )
                {
                        pFile->obj->inUse--;
                        RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
-                       yaffs_FlushFile(pFile->obj);
+                       yaffs_FlushFile(pFile->obj,1);
                        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
+                       mtime[0] = pFile->obj->win_mtime[0];
+                       mtime[1] = pFile->obj->win_mtime[1];
                        RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
                        if(pFile->fullName)
                        {