*** empty log message ***
authorcharles <charles>
Fri, 31 Jan 2003 03:30:33 +0000 (03:30 +0000)
committercharles <charles>
Fri, 31 Jan 2003 03:30:33 +0000 (03:30 +0000)
direct/yaffscfg.c
wince/yaffsfsd.c
yaffs_fs.c
yaffs_guts.c
yaffs_guts.h
yportenv.h

index 1b9576a2a54a61dfc0a7b121234fa614873e24a1..466b381135a64051553b9a5e19a7e8be27175a09 100644 (file)
@@ -73,6 +73,7 @@ int yaffs_StartUp(void)
        // /ram
        ramDev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
        ramDev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+       ramDev.nReservedBlocks = 1; // Set this smaller for RAM
        ramDev.startBlock = 1; // Can't use block 0
        ramDev.endBlock = 127; // Last block in 2MB.    
        ramDev.useNANDECC = 1;
@@ -86,6 +87,7 @@ int yaffs_StartUp(void)
        // /boot
        bootDev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
        bootDev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+       bootDev.nReservedBlocks = 5;
        bootDev.startBlock = 1; // Can't use block 0
        bootDev.endBlock = 127; // Last block in 2MB.   
        bootDev.useNANDECC = 0; // use YAFFS's ECC
@@ -99,6 +101,7 @@ int yaffs_StartUp(void)
                // /flash
        flashDev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
        flashDev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+       flashDev.nReservedBlocks = 5;
        flashDev.startBlock = 128; // First block after 2MB
        flashDev.endBlock = 1023; // Last block in 16MB
        flashDev.useNANDECC = 0; // use YAFFS's ECC
index e7ba9b16814b044fd35e9d525ef91a6dca7f4a2e..f9e8bef50620bf40a4c937071ae14c363e06e0e3 100644 (file)
-/*\r
- * YAFFS: Yet another FFS. A NAND-flash specific file system.\r
- * yaffsfsd.c: FSD interface funtions for WinCE.\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 and Lynn Winter\r
- * $Id: yaffsfsd.c,v 1.3 2003-01-31 00:52:53 charles Exp $\r
- */\r
-#include <windows.h>\r
-#include <extfile.h>\r
-#include <yaffs_guts.h>\r
-#include <ynandif.h>\r
-//slf021104b begin\r
-#include <diskio.h>\r
-//slf021104b end\r
-\r
-#define MAX_WIN_FILE   200\r
-#define YFSD_NAME_LENGTH 128\r
-#define YFSD_FULL_PATH_NAME_SIZE 500\r
-\r
-\r
-#define YFSD_DISK_NAME L"Disk"\r
-#define YFSD_BOOT_NAME L"Boot"\r
-\r
-#define PARTITION_START_NUMBER (1280)  \r
-\r
-\r
-// if this is defined the there will be a constant message box raised to display status\r
-//#define MSGBOX_DISPLAY\r
-       \r
-\r
-//#define MSGSTATE 1\r
-#define MSGSTATE 0\r
-//#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
-// Can define this in your sources file.\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\r
-\r
-//unsigned yaffs_traceMask=0xffffffff;\r
-unsigned yaffs_traceMask=0;\r
-\r
-\r
-typedef struct\r
-{\r
-       yaffs_Device dev;\r
-       DWORD   hdsk;\r
-       DWORD    mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL\r
-       BOOL    isMounted;\r
-       BOOL    configured;\r
-//     DWORD   guard0[100];\r
-//     DWORD   guard1[100];\r
-       SHELLFILECHANGEFUNC_t shellFunction;\r
-       PWSTR volName;\r
-} yfsd_Volume;\r
-\r
-typedef struct \r
-{\r
-       yaffs_Object *obj;\r
-       DWORD offset;\r
-       BOOL isopen;\r
-       BOOL dirty;\r
-       WCHAR *fullName;\r
-       yfsd_Volume *myVolume;\r
-       BOOL writePermitted;\r
-       BOOL readPermitted;\r
-       BOOL shareRead;\r
-       BOOL shareWrite;\r
-\r
-}      yfsd_WinFile;\r
-\r
-struct yfsd_FoundObjectStruct\r
-{\r
-  yaffs_Object *obj;\r
-  struct yfsd_FoundObjectStruct *next;\r
-};\r
-\r
-typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;\r
-\r
-typedef struct \r
-{\r
-       yaffs_Object *dir;\r
-       char pattern[YFSD_NAME_LENGTH+1];\r
-       yaffs_FoundObject *foundObjects;\r
-}      yfsd_WinFind;\r
-\r
-\r
-\r
-#define PSEARCH yfsd_WinFind*\r
-\r
-#define PVOLUME yfsd_Volume*\r
-#define PFILE   yfsd_WinFile*\r
-\r
-#define FSD_API        YFSD\r
-\r
-#include <fsdmgr.h>\r
-\r
-//slf021105a begin\r
-//static yfsd_Volume disk_volume;\r
-//static yfsd_Volume boot_volume;\r
-static yfsd_Volume * disk_volumes[MAXPARTITIONS];\r
-//slf021105a end;\r
-\r
-static CRITICAL_SECTION yaffsLock;\r
-static CRITICAL_SECTION winFileLock;\r
-\r
-static int yaffsLockInited = 0;\r
-\r
-static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];\r
-\r
-#if 0\r
-static yfsd_SetGuards(void)\r
-{\r
-       int i;\r
-       for(i = 0; i < 100; i++)\r
-       {\r
-               yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;\r
-       }\r
-}\r
-\r
-static void yfsd_CheckGuards(void)\r
-{\r
-       int i;\r
-       int found;\r
-       for(i = found = 0; i < 100 && !found; i++)\r
-       {\r
-                       if(yfsd_volume.guard0[i] != i)\r
-                       {\r
-                                       RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));\r
-                                       found = 1;\r
-                       }\r
-                       if(yfsd_volume.guard1[i] != i)\r
-                       {\r
-                                       RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));\r
-                                       found = 1;\r
-                       }\r
-       }\r
-}\r
-#endif\r
-\r
-\r
-#ifdef MSGBOX_DISPLAY\r
-DWORD WINAPI yfsd_MessageThread(LPVOID param)\r
-{\r
-    yaffs_Device *dev = (yaffs_Device *)param;\r
-    TCHAR dataBuffer[1000];\r
-    Sleep(10000);\r
-\r
-    // note : if the device gets free'd from under us, we will cause an exception in the loop\r
-    while (1)\r
-    {\r
-        wsprintf(dataBuffer, L"nShortOpCaches %i\r\n"\r
-                             L"nErasedBlocks %i\r\n"\r
-                             L"allocationBlock %i\r\n"\r
-                             L"allocationPage %i\r\n"\r
-                             L"garbageCollectionRequired %i\r\n"\r
-                             L"nRetiredBlocks %i\r\n"\r
-                             L"cacheHits %i\r\n"\r
-                             L"eccFixed %i\r\n"\r
-                             L"eccUnfixed %i\r\n"\r
-                             L"tagsEccFixed %i\r\n"\r
-                             L"tagsEccUnfixed %i\r\n",\r
-                             dev->nShortOpCaches, \r
-                             dev->nErasedBlocks,\r
-                             dev->allocationBlock,\r
-                             dev->allocationPage,\r
-                             dev->garbageCollectionRequired,\r
-                             dev->nRetiredBlocks,\r
-                             dev->cacheHits,\r
-                             dev->eccFixed,\r
-                             dev->eccUnfixed,\r
-                             dev->tagsEccFixed,\r
-                             dev->tagsEccUnfixed);\r
-\r
-        MessageBox(NULL,\r
-                   dataBuffer,\r
-                   L"YAFFS PROC INFO",\r
-                   MB_OK);\r
-        Sleep(1);\r
-    }\r
-}\r
-#endif\r
-\r
-void yfsd_LockWinFiles(void)\r
-{\r
-       //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));\r
-       EnterCriticalSection(&winFileLock);\r
-}\r
-void yfsd_UnlockWinFiles(void)\r
-{\r
-       //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));\r
-       LeaveCriticalSection(&winFileLock);\r
-}\r
-\r
-int lockwaits;\r
-\r
-void yfsd_LockYAFFS(void)\r
-{\r
-       //yfsd_CheckGuards();\r
-       //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));\r
-       lockwaits++;\r
-       EnterCriticalSection(&yaffsLock);\r
-       //RETAILMSG (MSGSTATE, (L" locked\r\n"));\r
-}\r
-void yfsd_UnlockYAFFS(void)\r
-{\r
-       //yfsd_CheckGuards();\r
-       //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));\r
-       LeaveCriticalSection(&yaffsLock);\r
-       lockwaits--;\r
-       //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));\r
-}\r
-\r
-\r
-void yfsd_InitialiseWinFiles(void)\r
-{\r
-       int i;\r
-       \r
-       RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));\r
-\r
-       InitializeCriticalSection(&winFileLock);\r
-\r
-       yfsd_LockWinFiles();\r
-       for(i = 0; i < MAX_WIN_FILE; i++)\r
-       {\r
-                       yfsd_winFile[i].isopen = 0;\r
-       }\r
-       yfsd_UnlockWinFiles();\r
-}\r
-\r
-yfsd_WinFile * yfsd_GetWinFile(void)\r
-{\r
-       int i;\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));\r
-\r
-       yfsd_LockWinFiles();\r
-\r
-       for(i = 0; i < MAX_WIN_FILE; i++)\r
-       {\r
-               if(!yfsd_winFile[i].isopen)\r
-               {\r
-                       yfsd_winFile[i].isopen = 1;\r
-                       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;\r
-                       yfsd_winFile[i].fullName = NULL;\r
-                       yfsd_winFile[i].obj = NULL;\r
-\r
-                       yfsd_UnlockWinFiles();\r
-                       return &yfsd_winFile[i];\r
-               }\r
-       }\r
-\r
-       yfsd_UnlockWinFiles();\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));\r
-\r
-       return NULL;\r
-}\r
-\r
-void yfsd_PutWinFile(yfsd_WinFile *f)\r
-{\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));\r
-       yfsd_LockWinFiles();\r
-       f->isopen = 0;\r
-       f->obj = NULL;\r
-       if(f->fullName)\r
-       {\r
-               free(f->fullName);\r
-               f->fullName = NULL;\r
-       }\r
-\r
-       yfsd_UnlockWinFiles();\r
-}\r
-\r
-\r
-\r
-void yfsd_FlushAllFiles(void)\r
-{\r
-       int i;\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));\r
-\r
-       yfsd_LockYAFFS();\r
-       yfsd_LockWinFiles();\r
-       for(i = 0; i < MAX_WIN_FILE; i++)\r
-       {\r
-               if(yfsd_winFile[i].isopen &&\r
-                  yfsd_winFile[i].obj)\r
-               {\r
-                       yaffs_FlushFile(yfsd_winFile[i].obj,1);\r
-               }\r
-       }\r
-       yfsd_UnlockWinFiles();\r
-       yfsd_UnlockYAFFS();\r
-}\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\r
-\r
-PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)\r
-{\r
-\r
-       // todo check for bounds\r
-       //slf021104b begin\r
-       //volName already has the initial backslash if it needs it.\r
-       //wcscpy(fpn,L"\\");\r
-       //wcscat(fpn,vol->volName);\r
-       wcscpy(fpn,vol->volName);\r
-       //slf021104b end\r
-       if(pathName[0] != '\\')\r
-       {\r
-               wcscat(fpn,L"\\");\r
-       }\r
-       wcscat(fpn,pathName);\r
-\r
-       return fpn;\r
-\r
-}\r
-\r
-\r
-// FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.\r
-\r
-void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)\r
-{\r
-       \r
-       wft->dwLowDateTime = target[0];\r
-       wft->dwHighDateTime = target[1];\r
-\r
-}\r
-\r
-void yfsd_NullWinFileTime(FILETIME *wft)\r
-{\r
-       wft->dwLowDateTime = 0;\r
-       wft->dwHighDateTime = 0;\r
-}\r
-\r
-void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])\r
-{\r
-       target[0] = wft->dwLowDateTime;\r
-       target[1] = wft->dwHighDateTime;\r
-}\r
-\r
-void  yfsd_WinFileTimeNow(__u32 target[2])\r
-{\r
-       SYSTEMTIME st;\r
-       FILETIME ft;\r
-\r
-       GetSystemTime(&st);\r
-       SystemTimeToFileTime(&st,&ft);\r
-       yfsd_WinFileTimeToU32s(&ft,target);\r
-}\r
-\r
-// Cut down the name to the parent directory, then inform the shell of\r
-// a change to the directory.\r
-void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)\r
-{\r
-       WCHAR str[500];\r
-       int i;\r
-       wcscpy(str,fullPathName);\r
-\r
-       i = wcslen(str) - 1;\r
-       \r
-       if(i > 0)\r
-       {\r
-               str[i] = 0;\r
-               i--;\r
-       }\r
-\r
-       // Curveball if the name is a directory (ie. we're doing an update of\r
-       // a directory because we added a directory item). , then it might end in a \\r
-       // which we must toss first\r
-       if(i >= 0 && (str[i] == '\\' || str[i] == '/'))\r
-       {\r
-               str[i] = 0;\r
-               i--;\r
-       }\r
-\r
-       // Ok, now strip back...\r
-\r
-       while(i >= 0 && str[i] != '\\' && str[i] != '/')\r
-       {\r
-               str[i] = 0;\r
-               i--;\r
-       }\r
-\r
-       if(pVolume->shellFunction)\r
-       {\r
-                       FILECHANGEINFO fc;\r
-                       \r
-                       fc.cbSize = sizeof(FILECHANGEINFO);\r
-                       fc.wEventId = SHCNE_UPDATEDIR;\r
-                       fc.uFlags = SHCNF_PATH;\r
-                       fc.dwItem1 = (DWORD)str;\r
-                       fc.dwItem2 = 0;\r
-                       fc.dwAttributes = 0;\r
-                       yfsd_NullWinFileTime(&fc.ftModified);\r
-                       fc.nFileSize = 0;\r
-\r
-                       pVolume->shellFunction(&fc);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));\r
-\r
-       }\r
-\r
-\r
-}\r
-\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
-}\r
-\r
-// File attributes:\r
-// Wince understands the following attributes of any use to YAFFS:\r
-//  \r
-//   ARCHIVE\r
-//   HIDDEN\r
-//   READONLY\r
-//   SYSTEM\r
-//   TEMPORARY\r
-//\r
-//      Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.\r
-//\r
-//   It also understands NORMAL. If no other flag is set, then set NORMAL.\r
-//   If any of the above are set, then NORMAL must **not** be set.\r
-//      Ignore this and the WinCE Explorer barfs the file.\r
-//\r
-//\r
-// in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY\r
-\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
-}\r
-DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)\r
-{\r
-\r
-               DWORD result;\r
-               \r
-               result = obj->st_mode & \r
-                                       (FILE_ATTRIBUTE_READONLY | \r
-                                        FILE_ATTRIBUTE_ARCHIVE | \r
-                                        FILE_ATTRIBUTE_HIDDEN |\r
-                                        FILE_ATTRIBUTE_SYSTEM);\r
-\r
-               if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;\r
-\r
-               if(result & ~FILE_ATTRIBUTE_NORMAL)\r
-               { \r
-                       result &= ~FILE_ATTRIBUTE_NORMAL;\r
-               }\r
-               else \r
-               {\r
-                       result = FILE_ATTRIBUTE_NORMAL;\r
-               }\r
-\r
-\r
-               return result;\r
-}\r
-\r
-\r
-\r
-/*\r
-*      Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is\r
-*      reached.  Characters are copied from input into output until the above stop\r
-*      condition is reached - output is then given a '\0'.  output must be at least\r
-*      as large as outSize\r
-*/\r
-static int parseToNextSlash(const unsigned short *input, char *output, int outSize)\r
-{\r
-       int counter = 0;\r
-       char *t = output;\r
-       /* strip any starting \'s */\r
-       //RETAILMSG(1, (L"\r\nParsing.. "));\r
-       while (*input == '\\' || *input == '/') input++, counter++;\r
-\r
-       for (; counter < outSize - 1; counter++)\r
-       {\r
-               if (*input == '\0' ||\r
-                       ((*input == '\\' || *input == '/') && input[1] == '\0'))   // special case: if the string ends in a '\', then toss the '\'\r
-               {\r
-                       counter = -1;   // break & tell people we've run to the end\r
-                       break;\r
-               }\r
-               if (*input == '\\' || *input == '/')\r
-                       break;\r
-               //RETAILMSG(1, (L"%c", *input));\r
-               *output = (char) (*input);\r
-               input++;\r
-               output++;\r
-       }\r
-       *output++ = '\0';\r
-       *output  = '\0';\r
-//     RETAILMSG(1, (L"\r\nOut %a\r\n", t));\r
-       \r
-       return counter;\r
-}\r
-\r
-/*\r
-*      Since the notion of paths as WinCE sees them and as YAFFS sees them\r
-*      is different, we needed a helper function to search from the root of\r
-*      device along the string in path.  The processed pointer is set to where\r
-*      abouts in the string the function was able to search up to.\r
-*/\r
-yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)\r
-{\r
-       // a buffer to keep the current chunk of path we're talking about it\r
-       char pathChunk[255];\r
-       int chunkSize;\r
-       int counter;\r
-       // the current object we are at\r
-       yaffs_Object *current;\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));\r
-       // start at the root of this device\r
-       current = yaffs_Root(device);\r
-       *processed = '\0';\r
-\r
-       do\r
-       {\r
-       //      parse chunks until we run out\r
-               chunkSize = parseToNextSlash(path, pathChunk, 255);\r
-//             RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));\r
-               if (chunkSize == -1)\r
-                       break;\r
-       //      move the path pointer along\r
-               path += chunkSize;\r
-       //      try and find the next yaffs object by chunkname \r
-               current = yaffs_FindObjectByName(current, pathChunk);\r
-               if (current == 0)\r
-               {\r
-                       processed[0] = '\0';\r
-                       return 0;\r
-               }\r
-       } while (1);\r
-\r
-       for (counter = 0; counter < length; counter++)\r
-       {\r
-               // Get the rest of the string\r
-               processed[counter] = pathChunk[counter];\r
-               if (pathChunk[counter] == '\0')\r
-                       break;\r
-       }\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));\r
-\r
-       return current;\r
-}\r
-\r
-\r
-yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )\r
-{\r
-       yaffs_Object *obj = NULL;\r
-       yaffs_Object *parent = NULL;\r
-       char name[YFSD_NAME_LENGTH+1];\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));\r
-\r
-       parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);\r
-\r
-       if(parent && yfsd_NameIsValid(name))\r
-       {\r
-               obj = yaffs_FindObjectByName(parent,name);\r
-       }\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));\r
-\r
-       return obj;\r
-}\r
-\r
-BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)\r
-{\r
-       //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.\r
-       //vol->volName = volName;\r
-       //slf021104b end\r
-\r
-\r
-       yfsd_LockYAFFS();\r
-       \r
-       //slf021220a Begin Cleanup block driver interface\r
-#if _WINCEOSVER >= 400\r
-       // For Win'CE 4.0 and later pass the hdsk for use by the yandif layer.\r
-       vol->dev.genericDevice = (PVOID)hdsk;\r
-#endif\r
-       //slf021220a End Cleanup block driver interface\r
-\r
-       //Mount/initialise YAFFs here\r
-       //slf021127a begin check for error returns!\r
-       if (ynandif_InitialiseNAND(&vol->dev))  \r
-       {\r
-       //slf021127a end check for error returns!\r
-               vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;\r
-               vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;\r
-               vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;\r
-               vol->dev.initialiseNAND = ynandif_InitialiseNAND;\r
-               vol->dev.startBlock = startBlock;\r
-               if (endBlock != -1)\r
-                       vol->dev.endBlock = endBlock;\r
-               vol->dev.nShortOpCaches = 10; // a nice number of caches.\r
-               vol->dev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;\r
-               vol->dev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;\r
-\r
-\r
-               // nBlocks is set the total size of the disk, not the partition\r
-       //      vol->dev.nBlocks = endBlock - startBlock + 1;\r
-\r
-       //      qnand_EraseAllBlocks(&vol->dev);\r
-\r
-               //slf021127a begin check for error returns!\r
-               if (yaffs_GutsInitialise(&vol->dev))\r
-               {\r
-               //slf021127a end check for error returns!\r
-                       RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));\r
-\r
-                       RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",\r
-                                                       vol->dev.startBlock,vol->dev.endBlock,\r
-                                                       vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));\r
-\r
-\r
-#if 0\r
-                       for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)\r
-                       {\r
-                                       switch(vol->dev.blockInfo[i].blockState)\r
-                                       {\r
-                                               case YAFFS_BLOCK_STATE_DEAD:\r
-                               \r
-                                                       RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));\r
-                                                       deadBlox++;\r
-                                                       break;\r
-                                               case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;\r
-                                               case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;\r
-                                               case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;\r
-                                               case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;\r
-                                               default:\r
-                                                       RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));\r
-                                                       break;\r
-                                       }\r
-                       }\r
-\r
-                       RETAILMSG(1, (L"Blocks dead  %d empty %d full %d allocating %d dirty %d\r\n",\r
-                                                       deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));\r
-\r
-#endif\r
-\r
-//slf021127a begin check for error returns!\r
-                       vol->isMounted = 1;\r
-               }\r
-       }\r
-//slf021127a begin check for error returns!\r
-       \r
-       yfsd_UnlockYAFFS();\r
-\r
-//slf021127a begin check for error returns!\r
-//     vol->isMounted = 1;\r
-//slf021127a begin check for error returns!\r
-       \r
-       //slf021104b begin\r
-       //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\r
-\r
-       if(vol->mgrVolume)\r
-       {\r
-               //slf021104b Begin\r
-               // Get some space for the volume name.\r
-        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;\r
-       }\r
-       else\r
-       {\r
-               vol->isMounted = 0;\r
-               SetLastError(ERROR_OUTOFMEMORY);\r
-               return FALSE;\r
-       }       \r
-}\r
-\r
-\r
-BOOL YFSD_MountDisk(HDSK hdsk)\r
-{\r
-//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;\r
-       //int i;\r
-       // Called to mount a disk.\r
-       // NB THis call might happen redundantly.\r
-       //\r
-       //\r
-       // If yaffs is not initialised, then call the \r
-       // initialisation function\r
-       //\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));\r
-\r
-       if (!yaffsLockInited)\r
-       {\r
-               InitializeCriticalSection(&yaffsLock);\r
-               yfsd_InitialiseWinFiles();\r
-               yaffsLockInited = 1;\r
-       }\r
-\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\r
-#ifdef DISABLE_BOOT_PARTITION\r
-       // 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
-#ifdef MSGBOX_DISPLAY\r
-        // pass the device we are sniffing to the thread\r
-        CreateThread(NULL, 0, yfsd_MessageThread, (LPVOID)&disk_volumes[0]->dev, 0, NULL);\r
-#endif\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);\r
-//\r
-//     \r
-//     if(disk_volume.isMounted)\r
-//     {\r
-//             return TRUE;\r
-//     }\r
-//#else\r
-//     // Want both boot and disk\r
-//     YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);\r
-//     YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);\r
-//\r
-//     \r
-//     if(disk_volume.isMounted && boot_volume.isMounted)\r
-//     {\r
-//             return TRUE;\r
-//     }\r
-//#endif\r
-//\r
-//     return FALSE;\r
-#endif\r
-//slf021105a end\r
-\r
-//     yfsd_SetGuards();\r
-\r
-       // todo - get name from registry\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_UnmountDisk(HDSK hdsk)\r
-{\r
-//slf021105a begin\r
-       int i;\r
-//slf021105a end\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));\r
-       \r
-       //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();\r
-//\r
-//     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
-//slf021220a Begin Cleanup block driver interface\r
-                       ynandif_DeinitialiseNAND(&(disk_volumes[i]->dev));\r
-//slf021220a end Cleanup block driver interface\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\r
-       return TRUE;\r
-}\r
-\r
-\r
-BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)\r
-{\r
-       // security attributes are ignored (should be NULL)\r
-\r
-       yaffs_Object *newDir = NULL;\r
-       yaffs_Object *parent = NULL;\r
-       char name[YFSD_NAME_LENGTH+1];\r
-       ULONG objSize;\r
-       DWORD attribs;\r
-       unsigned modifiedTime[2];\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);\r
-\r
-       //slf021101b begin \r
-       if (parent)\r
-       {\r
-               if(yfsd_NameIsValid(name))\r
-               {\r
-                       newDir = yaffs_MknodDirectory(parent,name,0,0,0);\r
-                       if(newDir)\r
-                       {\r
-                               objSize = yaffs_GetObjectFileLength(newDir);\r
-                               attribs = yfsd_GetObjectWinAttributes(newDir);\r
-                               modifiedTime[0] = newDir->win_mtime[0];\r
-                                modifiedTime[1] = newDir->win_mtime[1];\r
-                       }\r
-                       else\r
-                       {\r
-                               if(yaffs_FindObjectByName(parent,name))\r
-                                       SetLastError(ERROR_ALREADY_EXISTS);\r
-                               else\r
-                                       SetLastError(ERROR_DISK_FULL);\r
-                       }\r
-               }\r
-               else\r
-                       SetLastError(ERROR_INVALID_NAME);\r
-       }\r
-       else\r
-       {\r
-               SetLastError(ERROR_PATH_NOT_FOUND);\r
-       }\r
-    //slf021101b end\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       // Call shell function to tell of new directory\r
-       if(newDir && pVolume->shellFunction)\r
-       {\r
-                       FILECHANGEINFO fc;\r
-                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
-                       fc.cbSize = sizeof(FILECHANGEINFO);\r
-                       fc.wEventId = SHCNE_MKDIR;\r
-                       fc.uFlags = SHCNF_PATH;\r
-                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);\r
-                       fc.dwItem2 = 0;\r
-                       fc.dwAttributes = attribs; \r
-                       yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);\r
-                       fc.nFileSize = objSize;\r
-\r
-                       pVolume->shellFunction(&fc);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
-                       //yfsd_ShellDirectoryChanged(pVolume,fpn);\r
-\r
-       }\r
-\r
-//slf021101b begin \r
-//     if(parent && !newDir)\r
-//     {\r
-//                     SetLastError(ERROR_DISK_FULL);\r
-//     }\r
-//slf021101b end\r
-\r
-       return newDir ? TRUE : FALSE;\r
-}\r
-\r
-\r
-BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)\r
-{\r
-       int result = FALSE;\r
-       yaffs_Object *parent = NULL;\r
-       yaffs_Object *obj;\r
-       char name[YFSD_NAME_LENGTH+1];\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory (%s)\r\n", pathName));\r
-       \r
-       yfsd_LockYAFFS();\r
-\r
-       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);\r
-       if(!obj)\r
-       {\r
-               SetLastError(ERROR_PATH_NOT_FOUND);\r
-               result = FALSE;\r
-       }\r
-       else if (obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)\r
-       {\r
-               SetLastError(ERROR_ACCESS_DENIED);\r
-               result = FALSE;\r
-       }\r
-       else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)\r
-       {\r
-               SetLastError(ERROR_ACCESS_DENIED);\r
-               result = FALSE;\r
-       }\r
-       else if(obj->inUse)\r
-       {\r
-               SetLastError(ERROR_ACCESS_DENIED);\r
-               result = FALSE;\r
-       }\r
-       else\r
-       {\r
-\r
-               parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);\r
-\r
-               if(parent && yfsd_NameIsValid(name))\r
-               {\r
-                       result = yaffs_Unlink(parent,name);\r
-                       if(!result)\r
-                               SetLastError(ERROR_DIR_NOT_EMPTY);\r
-               }\r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       if(result && pVolume->shellFunction)\r
-       {\r
-                       FILECHANGEINFO fc;\r
-                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
-                       fc.cbSize = sizeof(FILECHANGEINFO);\r
-                       fc.wEventId = SHCNE_RMDIR;\r
-                       fc.uFlags = SHCNF_PATH;\r
-                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);\r
-                       fc.dwItem2 = 0;\r
-                       fc.dwAttributes = 0;\r
-                       yfsd_NullWinFileTime(&fc.ftModified);\r
-                       fc.nFileSize = 0;\r
-\r
-                       pVolume->shellFunction(&fc);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
-                       yfsd_ShellDirectoryChanged(pVolume,fpn);\r
-       }\r
-       \r
-       return result ? TRUE : FALSE;\r
-}\r
-\r
-\r
-DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )\r
-{\r
-       yaffs_Object *obj = NULL;\r
-\r
-       DWORD result = 0xFFFFFFFF;\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-\r
-       if(obj)\r
-       {\r
-               result = yfsd_GetObjectWinAttributes(obj);\r
-       }\r
-       else\r
-       {\r
-               SetLastError(ERROR_FILE_NOT_FOUND);\r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-       \r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));\r
-       return result;\r
-\r
-       \r
-}\r
-\r
-BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )\r
-{\r
-       yaffs_Object *obj = NULL;\r
-       DWORD mtime[2];\r
-       DWORD attribs;\r
-       DWORD objSize;\r
-\r
-       int result = 0;\r
-\r
-       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
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-\r
-       if(obj)\r
-       {\r
-               obj->st_mode = dwFileAttributes;\r
-               obj->dirty = 1;\r
-               result = yaffs_FlushFile(obj,0);\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
-       }\r
-       else\r
-       {\r
-               SetLastError(ERROR_FILE_NOT_FOUND);\r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       if(result && pVolume->shellFunction)\r
-       {\r
-                       FILECHANGEINFO fc;\r
-                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
-                       fc.cbSize = sizeof(FILECHANGEINFO);\r
-                       fc.wEventId = SHCNE_ATTRIBUTES;\r
-                       fc.uFlags = SHCNF_PATH;\r
-                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
-                       fc.dwItem2 = 0;\r
-                       fc.dwAttributes =  attribs;\r
-                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
-                       fc.nFileSize = objSize;\r
-\r
-                       pVolume->shellFunction(&fc);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
-                       //yfsd_ShellDirectoryChanged(pVolume,fpn);\r
-       }\r
-       \r
-\r
-       return result;\r
-\r
-}\r
-\r
-BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )\r
-{\r
-       int result = FALSE;\r
-       yaffs_Object *parent = NULL;\r
-       yaffs_Object *obj;\r
-       char name[YFSD_NAME_LENGTH+1];\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-       if(!obj)\r
-       {\r
-               SetLastError(ERROR_FILE_NOT_FOUND);\r
-               result = FALSE;\r
-       }\r
-       else if (obj->variantType != YAFFS_OBJECT_TYPE_FILE)\r
-       {\r
-               SetLastError(ERROR_ACCESS_DENIED);\r
-               result = FALSE;\r
-       }\r
-       else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)\r
-       {\r
-               SetLastError(ERROR_ACCESS_DENIED);\r
-               result = FALSE;\r
-       }\r
-       else if(obj->inUse)\r
-       {\r
-               SetLastError(ERROR_ACCESS_DENIED);\r
-               result = FALSE;\r
-       }\r
-       else\r
-       {\r
-\r
-               parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);\r
-\r
-               if(parent && yfsd_NameIsValid(name))\r
-               {\r
-                       result = yaffs_Unlink(parent,name);\r
-                       if(!result)\r
-                               SetLastError(ERROR_ACCESS_DENIED);\r
-               }\r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       if(result && pVolume->shellFunction)\r
-       {\r
-                       FILECHANGEINFO fc;\r
-                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
-                       fc.cbSize = sizeof(FILECHANGEINFO);\r
-                       fc.wEventId = SHCNE_DELETE;\r
-                       fc.uFlags = SHCNF_PATH;\r
-                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
-                       fc.dwItem2 = 0;\r
-                       fc.dwAttributes = -1;\r
-                       yfsd_NullWinFileTime(&fc.ftModified);\r
-                       fc.nFileSize = 0;\r
-\r
-                       pVolume->shellFunction(&fc);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
-                       yfsd_ShellDirectoryChanged(pVolume,fpn);\r
-       }\r
-\r
-       return result ? TRUE : FALSE;\r
-}\r
-\r
-BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )\r
-{\r
-       yaffs_Object *newParent = NULL;\r
-       yaffs_Object *oldParent = NULL;\r
-       yaffs_Object *obj = NULL;\r
-       char oldName[YFSD_NAME_LENGTH+1];\r
-       char newName[YFSD_NAME_LENGTH+1];\r
-       int result = 0;\r
-       int objIsDir = 0;\r
-       DWORD attribs;\r
-       DWORD objSize;\r
-       DWORD mtime[2];\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);\r
-       newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);\r
-\r
-       if(oldParent  && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))\r
-       {\r
-               result = yaffs_RenameObject(oldParent,oldName,newParent,newName);\r
-               if(!result)\r
-               {\r
-                       SetLastError(ERROR_FILE_NOT_FOUND);\r
-               }\r
-\r
-               obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);\r
-               if(obj)\r
-               {\r
-                       objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);\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
-               }\r
-       }\r
-       else\r
-       {\r
-               SetLastError(ERROR_PATH_NOT_FOUND);\r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-\r
-       if(result && pVolume->shellFunction)\r
-       {\r
-                       FILECHANGEINFO fc;\r
-                       WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];\r
-                       WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
-                       fc.cbSize = sizeof(FILECHANGEINFO);\r
-                       fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;\r
-                       fc.uFlags = SHCNF_PATH;\r
-                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);\r
-                       fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);\r
-                       fc.dwAttributes = attribs;\r
-                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
-                       fc.nFileSize = objSize;\r
-\r
-                       pVolume->shellFunction(&fc);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
-                       yfsd_ShellDirectoryChanged(pVolume,fpn1);\r
-                       yfsd_ShellDirectoryChanged(pVolume,fpn2);\r
-       }\r
-\r
-\r
-       return result ? TRUE : FALSE;\r
-\r
-}\r
-\r
-BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )\r
-{\r
-       //slf021104c begin\r
-    BOOL fSuccess;\r
-       //slf021104c end\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));\r
-\r
-       //slf021104c begin\r
-    if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))\r
-        fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);\r
-       return fSuccess;\r
-       //return FALSE;\r
-       //slf021104c end\r
-}\r
-\r
-BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )\r
-{\r
-\r
-       int nChunks;\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));\r
-\r
-       yfsd_LockYAFFS();\r
-       nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);\r
-       yfsd_UnlockYAFFS();\r
-\r
-       if(nChunks >= 0)\r
-       {\r
-               // Let's pretentd our clusters are the same size as eraseable blocks...\r
-               *pBytesPerSector = 512;\r
-               *pSectorsPerCluster  =32;\r
-               *pFreeClusters = nChunks/32;\r
-               *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;\r
-       }\r
-\r
-       return (nChunks >= 0)? TRUE : FALSE;\r
-\r
-\r
-\r
-}\r
-\r
-void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )\r
-{\r
-       // Flags can be one of:\r
-       // FSNOTIFY_POWER_ON: no action required\r
-       // FSNOTIFY_POWER_OFF: flush all files\r
-       // FSNOTIFY_DEVICE_ON: no action required\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));\r
-       if(dwFlags == FSNOTIFY_POWER_OFF)\r
-       {\r
-               yfsd_FlushAllFiles();\r
-       }\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )\r
-{\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));\r
-       \r
-       pVolume->shellFunction = pfn;\r
-\r
-       return TRUE;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-int iMatch(const char a, const char b)\r
-{\r
-       if (a == '?' || b == '?')\r
-               return 1;\r
-       return (toupper(a) == toupper(b));\r
-}\r
-\r
-void pString(const char *inp)\r
-{\r
-       while (*inp) RETAILMSG(1, (L"%c", *inp++));\r
-}\r
-\r
-int regularMatch(const char *regexp, const char *str)\r
-{\r
-//     pString(regexp);\r
-//     RETAILMSG(1, (L" "));\r
-//     pString(str);\r
-//     RETAILMSG(1, (L"\r\n"));\r
-\r
-       if (*regexp == 0 && *str == 0)\r
-       {\r
-               //RETAILMSG(1, (L"Match!\r\n"));\r
-               return 1;\r
-       }\r
-       if (*regexp == '*')                     \r
-       {\r
-               regexp++;\r
-               if (*regexp == 0)   // end of the expression is a *, we must match\r
-               {\r
-                       //RETAILMSG(1, (L"Match!\r\n"));\r
-                       return 1;\r
-               }\r
-               while (!iMatch(*regexp, *str)) // throw away chars from str until we match\r
-               {\r
-                       if (*str == 0)  // if we're not at the end\r
-                       {\r
-                               // if we have .* left to match, but the str is finished then match it OK\r
-                               if (regexp[0] == '.' && regexp[1] == '*')\r
-                               {\r
-                                       //RETAILMSG(1, (L"Match!\r\n"));\r
-                                       return 1;\r
-                               }\r
-                               else\r
-                               {\r
-                               // the extension failed the match\r
-                                       //RETAILMSG(1, (L"No Match!\r\n"));\r
-                                       return 0;\r
-                               }\r
-                       }\r
-                       str++;\r
-               } \r
-               // right now we should either eat more characters, or try to match\r
-               return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));\r
-       }\r
-//  compare chars until we hit another *, or we fail\r
-       while (iMatch(*regexp, *str))\r
-       {\r
-               if (*regexp == 0 && *str == 0)\r
-               {\r
-                       //RETAILMSG(1, (L"Match!\r\n"));\r
-                       return 1;\r
-               }\r
-               regexp++;\r
-               str++;\r
-       }\r
-\r
-       if (*regexp == 0 && *str == 0)\r
-       {\r
-               //RETAILMSG(1, (L"Match!\r\n"));\r
-               return 1;\r
-       }\r
-\r
-       if (*regexp == '*')\r
-               return regularMatch(regexp, str);\r
-\r
-       //RETAILMSG(1, (L"No Match!\r\n"));\r
-       return 0;\r
-}\r
-\r
-\r
-void yfsd_DeleteFinder(PSEARCH pSearch)\r
-{\r
-  if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.\r
-  {\r
-    yaffs_FoundObject *it;\r
-    yaffs_FoundObject *temp;\r
-\r
-    it = pSearch->foundObjects;\r
-\r
-    while(it != NULL)\r
-    {\r
-      temp = it;\r
-      it = it->next;\r
-      \r
-      free(temp);\r
-    }\r
-\r
-    pSearch->foundObjects = NULL;\r
-  }\r
-\r
-               pSearch->dir->inUse--;\r
-               free(pSearch);\r
-}\r
-\r
-BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)\r
-{\r
-  //Iterate through the current list of objs already found and return true if already exists.\r
-  //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.\r
-  BOOL found = FALSE;\r
-\r
-  yaffs_FoundObject *it;\r
-  it = pSearch->foundObjects;\r
-\r
-  \r
-  while(it->next != NULL) //iterate through singly linked list.\r
-  {\r
-    if(it->obj == l)\r
-    {\r
-      found = TRUE;\r
-      break;\r
-    }\r
-    it = it->next;\r
-  }\r
-\r
-  if(!found)\r
-  {\r
-    //Add the item to the list.\r
-    //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL\r
-    it->next = malloc(sizeof(yaffs_FoundObject));\r
-    it->next->next = NULL;\r
-    it->next->obj = 0;\r
-\r
-    it->obj = l;\r
-  }\r
-\r
-  return found;\r
-}\r
-\r
-#if 0\r
-// slower one\r
-BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)\r
-{\r
-\r
-       struct list_head *i;\r
-       int pos;\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
-       pos = 0;\r
-       list_for_each(i,&pSearch->dir->variant.directoryVariant.children)\r
-       {\r
-\r
-               l = list_entry(i, yaffs_Object,siblings);\r
-\r
-               yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);\r
-\r
-               if(regularMatch(pSearch->pattern,name))\r
-               {\r
-                       if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)\r
-                       {               \r
-\r
-                               \r
-                               found = 1;\r
-                               //pSearch->currentPos++;\r
-\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 = (CEOID)(INVALID_HANDLE_VALUE); // 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
-                       else\r
-                       {\r
-                               pos++;\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
-\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 = (CEOID)(INVALID_HANDLE_VALUE); // 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
-\r
-HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )\r
-{\r
-\r
-       // Create a search context, register it, and do the first search\r
-\r
-       PSEARCH pSearch;\r
-       HANDLE h = INVALID_HANDLE_VALUE;\r
-       BOOL found = 0;\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));\r
-\r
-       pSearch = malloc(sizeof(yfsd_WinFind));\r
-       if(!pSearch)\r
-       {\r
-               SetLastError(ERROR_OUTOFMEMORY);\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       if(pSearch)\r
-       {\r
-               pSearch->foundObjects = NULL; //pSearch->currentPos = 0;\r
-               pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);\r
-               if(pSearch->dir)\r
-               {\r
-                               pSearch->dir->inUse++;\r
-               }\r
-               else\r
-               {\r
-                       free(pSearch);\r
-                       pSearch = NULL;\r
-                       SetLastError(ERROR_PATH_NOT_FOUND);\r
-               }\r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-\r
-\r
-       if(pSearch)\r
-       {\r
-               found = yfsd_DoFindFile(pSearch,pfd);\r
-\r
-               if(found)\r
-               {\r
-                       h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);\r
-                       if(h == INVALID_HANDLE_VALUE)\r
-                       {\r
-                               SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       SetLastError(ERROR_FILE_NOT_FOUND);\r
-               }\r
-\r
-               if(h == INVALID_HANDLE_VALUE)\r
-               {\r
-                       yfsd_DeleteFinder(pSearch);\r
-               }\r
-\r
-       }\r
-\r
-\r
-       return h;\r
-}\r
-\r
-BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )\r
-{\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));\r
-       if(!pSearch)\r
-       {\r
-               return FALSE;\r
-       }\r
-       return yfsd_DoFindFile(pSearch,pfd);\r
-}\r
-\r
-BOOL YFSD_FindClose( PSEARCH pSearch )\r
-{      \r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));\r
-       if(!pSearch)\r
-       {\r
-               return FALSE;\r
-       }\r
-       yfsd_DeleteFinder(pSearch);\r
-       return TRUE;\r
-}\r
-\r
-\r
-HANDLE YFSD_CreateFileW( \r
-       PVOLUME pVolume, \r
-       HANDLE hProc, \r
-       PCWSTR pwsFileName, \r
-       DWORD dwAccess, \r
-       DWORD dwShareMode,\r
-       PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore\r
-       DWORD dwCreate,\r
-       DWORD dwFlagsAndAttributes, \r
-       HANDLE hTemplateFile ) // ignore\r
-{\r
-\r
-\r
-       yaffs_Object *parent = NULL;\r
-       yaffs_Object *obj = NULL;\r
-       char name[YFSD_NAME_LENGTH+1];\r
-       int mode;\r
-       yfsd_WinFile *f = NULL;\r
-       HANDLE handle = INVALID_HANDLE_VALUE;\r
-       unsigned modifiedTime[2];\r
-       unsigned objSize;\r
-\r
-       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
-\r
-       BOOL fileCreated = FALSE;\r
-       \r
-       BOOL fAlwaysCreateOnExistingFile = FALSE;\r
-       BOOL fTruncateExistingFile = FALSE;\r
-\r
-\r
-       mode = dwFlagsAndAttributes & 0x00FFFFFF;  // ding off the flags\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));\r
-       if(writePermitted)\r
-       {\r
-               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));\r
-       }\r
-       else\r
-       {\r
-               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));\r
-       }\r
-\r
-       if(!yfsd_CheckValidAttributes(mode))\r
-       {\r
-                       SetLastError(ERROR_INVALID_PARAMETER);\r
-                       return FALSE;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-\r
-       parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);\r
-\r
-\r
-       if(parent && yfsd_NameIsValid(name))\r
-       {\r
-\r
-               //slf021220b begin Fix still more bugs in CreateFile.\r
-               // Get the object for this file if it exists (only once).\r
-               obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-               //slf021220b end Fix still more bugs in CreateFile.\r
-               if(dwCreate == CREATE_NEW)\r
-               {\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));\r
-\r
-                       //slf021101c begin\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-                       if(!obj)\r
-                       {\r
-                               obj = yaffs_MknodFile(parent,name,mode,0,0);\r
-                               if(!obj)\r
-                                       SetLastError(ERROR_DISK_FULL);\r
-                               fileCreated = TRUE;\r
-                       }\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
-                       {\r
-                               obj = NULL;\r
-                               SetLastError(ERROR_ALREADY_EXISTS);\r
-                       }\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-                       else\r
-                       {\r
-                               obj = NULL;\r
-                               //slf021220b begin Fix still more bugs in CreateFile.\r
-                               //Match CE FAT error return SetLastError(ERROR_ALREADY_EXISTS);\r
-                               SetLastError(ERROR_FILE_EXISTS);\r
-                               //slf021220b begin Fix still more bugs in CreateFile.\r
-                       }\r
-                       //slf021101c end\r
-               }\r
-               else if( dwCreate == OPEN_ALWAYS)\r
-               {\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-                       if(!obj)\r
-                       {\r
-                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));\r
-                               obj = yaffs_MknodFile(parent,name,mode,0,0);\r
-                               if(!obj)\r
-                                       SetLastError(ERROR_DISK_FULL);\r
-                               fileCreated = TRUE;\r
-\r
-                       }\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
-                       {\r
-                               obj = NULL;\r
-                               SetLastError(ERROR_ACCESS_DENIED);\r
-                       }\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-                       else\r
-                       {\r
-                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));\r
-                       }\r
-               }\r
-               else if(dwCreate == OPEN_EXISTING)\r
-               {\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-                       if(!obj)\r
-                               SetLastError(ERROR_FILE_NOT_FOUND);\r
-               //slf021220b begin Fix still more bugs in CreateFile.\r
-            //slf021101c begin\r
-           //                  else\r
-           //                          if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)\r
-           //                          {\r
-           //                                  SetLastError(ERROR_ACCESS_DENIED);\r
-           //                                  obj = NULL;\r
-           //                          }\r
-            //slf021101c end\r
-                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
-                       {\r
-                               SetLastError(ERROR_ACCESS_DENIED);\r
-                               obj = NULL;\r
-                       }\r
-               //slf021220b end Fix still more bugs in CreateFile.\r
-               }\r
-               else if(dwCreate == TRUNCATE_EXISTING)\r
-               {\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-                       //if(obj)\r
-                       if (!writePermitted || (obj  && (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)))\r
-                       {\r
-                               obj = NULL;\r
-                               SetLastError(ERROR_ACCESS_DENIED);\r
-                       }\r
-                       else if(obj)\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-                       {\r
-                               // Indicate that file is to be truncated.  This will happen later on assuming\r
-                               // that a sharing violation does not occur and that we can get a file handle.\r
-                               fTruncateExistingFile = TRUE;\r
-                       }\r
-                       else \r
-                       {\r
-                               SetLastError(ERROR_FILE_NOT_FOUND);\r
-                       }\r
-               }\r
-               else if(dwCreate == CREATE_ALWAYS)\r
-               {\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-\r
-                       if(!obj)\r
-                       {\r
-                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));\r
-                               obj = yaffs_MknodFile(parent,name,mode,0,0);\r
-                               if(!obj)\r
-                                       SetLastError(ERROR_DISK_FULL);\r
-                               fileCreated = TRUE;\r
-                       }\r
-                       //slf021220b begin Fix still more bugs in CreateFile.\r
-                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
-                       {\r
-                               obj = NULL;\r
-                               SetLastError(ERROR_ACCESS_DENIED);\r
-                       }\r
-                       //slf021220b end Fix still more bugs in CreateFile.\r
-                       else\r
-                       {                       \r
-                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));\r
-                               // Indicate that file is to be recreated.  This will happen later on assuming\r
-                               // that a sharing violation does not occur and that we can get a file handle.\r
-                               fAlwaysCreateOnExistingFile = TRUE;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));\r
-                               SetLastError(ERROR_INVALID_PARAMETER);\r
-               }\r
-       }\r
-       else\r
-       {\r
-               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));\r
-               SetLastError(ERROR_PATH_NOT_FOUND);\r
-       }\r
-\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
-                               //slf021220c begin Fix error code for new sharing mode check code.\r
-                               SetLastError(ERROR_SHARING_VIOLATION);\r
-                               //slf021220c end Fix error code for new sharing mode check code.\r
-                               obj = NULL;\r
-                       }\r
-\r
-\r
-       }\r
-       if(obj)\r
-       {\r
-               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));\r
-               f = yfsd_GetWinFile();\r
-       }\r
-       else\r
-       {\r
-               RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));\r
-       }\r
-\r
-       if(f)\r
-       {\r
-\r
-               handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);\r
-\r
-               if(handle != INVALID_HANDLE_VALUE)\r
-               {\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));\r
-\r
-                       if (fTruncateExistingFile)\r
-                       {\r
-                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - TRUNCATE_EXISTING - truncating existing file\r\n"));\r
-                               yaffs_ResizeFile(obj,0);\r
-                       }\r
-                       \r
-                       if (fAlwaysCreateOnExistingFile)\r
-                       {\r
-                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - CREATE_ALWAYS - zapping existing file\r\n"));\r
-                               obj->st_mode = mode;\r
-                               obj->dirty = 1;\r
-                               yaffs_ResizeFile(obj,0);\r
-                               yaffs_FlushFile(obj,1);\r
-                       }\r
-                                               \r
-                       f->obj = obj;\r
-                       f->offset = 0;\r
-                       f->writePermitted = writePermitted;\r
-                       //slf021220d begin oops typo.\r
-                       f->readPermitted = readPermitted;\r
-                       //slf021220d end oops typo.\r
-                       f->shareRead= shareRead;\r
-                       f->shareWrite = shareWrite;\r
-                       f->myVolume = pVolume;\r
-                       obj->inUse++;\r
-\r
-                       modifiedTime[0] = obj->win_mtime[0];\r
-                       modifiedTime[1] = obj->win_mtime[1];\r
-                       objSize = yaffs_GetObjectFileLength(obj);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));\r
-               }\r
-               else\r
-               {\r
-                       yfsd_PutWinFile(f);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));\r
-               }\r
-\r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       if(handle != INVALID_HANDLE_VALUE && \r
-          fileCreated &&\r
-          pVolume->shellFunction)\r
-       {\r
-                       FILECHANGEINFO fc;\r
-                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
-                       fc.cbSize = sizeof(FILECHANGEINFO);\r
-                       fc.wEventId = SHCNE_CREATE;\r
-                       fc.uFlags = SHCNF_PATH;\r
-                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
-                       fc.dwItem2 = 0;\r
-                       fc.dwAttributes = mode;\r
-                       yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);\r
-                       fc.nFileSize = objSize;\r
-\r
-                       pVolume->shellFunction(&fc);\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
-                       yfsd_ShellDirectoryChanged(pVolume,fpn);\r
-       }\r
-\r
-       if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))\r
-       {\r
-                       // Remember the name\r
-\r
-                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-                       int slen;\r
-\r
-                       yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
-                       slen = wcslen(fpn);\r
-                       f->fullName = malloc((slen+1)* sizeof(WCHAR));\r
-                       if(f->fullName)\r
-                       {\r
-                               wcscpy(f->fullName,fpn);\r
-                       }\r
-\r
-       }\r
-\r
-\r
-       return handle;\r
-\r
-}\r
-\r
-BOOL yfsd_DoReadFile( \r
-       PFILE pFile, \r
-       PVOID pBuffer, \r
-       DWORD cbRead, \r
-       PDWORD pcbRead)\r
-{\r
-       \r
-       DWORD maxRead;\r
-       int nread = 0;\r
-       yaffs_Object *obj = NULL;\r
-\r
-\r
-       if(pcbRead)\r
-       {\r
-               *pcbRead = 0;\r
-       }\r
-       else\r
-       {\r
-               RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));\r
-       }\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));\r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-       \r
-       obj = pFile->obj;\r
-\r
-       if(yaffs_GetObjectFileLength(obj) > pFile->offset)\r
-       {\r
-               maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;\r
-       }\r
-       else\r
-       {\r
-               maxRead = 0;\r
-       }\r
-\r
-       if(cbRead > maxRead)\r
-       {\r
-               cbRead = maxRead;\r
-       }\r
-       \r
-       if(maxRead > 0)\r
-       {\r
-               nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);\r
-               if(nread > 0)\r
-               {\r
-                       pFile->offset += nread;\r
-\r
-                       if(pcbRead)\r
-                       {\r
-                               *pcbRead = nread;\r
-                       }\r
-               }\r
-       }\r
-       else\r
-       {\r
-               if(pcbRead) \r
-               {\r
-                       *pcbRead = maxRead;\r
-               }\r
-       }\r
-\r
-\r
-       return nread < 0? FALSE : TRUE; \r
-\r
-}\r
-\r
-BOOL YFSD_ReadFile( \r
-       PFILE pFile, \r
-       PVOID pBuffer, \r
-       DWORD cbRead, \r
-       PDWORD pcbRead, \r
-       OVERLAPPED *pOverlapped ) //ignore\r
-{\r
-       BOOL result;\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));\r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       return result;\r
-}\r
-\r
-BOOL YFSD_ReadFileWithSeek( \r
-       PFILE pFile, \r
-       PVOID pBuffer, \r
-       DWORD cbRead, \r
-       PDWORD pcbRead, \r
-       OVERLAPPED *pOverlapped, \r
-       DWORD dwLowOffset, \r
-       DWORD dwHighOffset )\r
-{\r
-       BOOL result;\r
-       DWORD rememberedOffset;\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));\r
-\r
-       // To determine if paging is supported, the kernel calls this with all parameters except pFile\r
-       // being zero.\r
-       if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)\r
-       {\r
-               return TRUE; // paging suppported\r
-               //return FALSE; // paging not supported\r
-       }\r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       rememberedOffset = pFile->offset;\r
-\r
-       pFile->offset = dwLowOffset;\r
-       // ignore high offset for now\r
-\r
-       result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);\r
-\r
-       //pFile->offset = rememberedOffset;\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       return result;\r
-\r
-\r
-}\r
-\r
-\r
-BOOL yfsd_DoWriteFile( \r
-       PFILE pFile, \r
-       PCVOID pBuffer, \r
-       DWORD cbWrite, \r
-       PDWORD pcbWritten)\r
-{\r
-       int nwritten = 0;\r
-       yaffs_Object *obj = NULL;\r
-       \r
-       RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));\r
-       \r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-\r
-       if(!pFile->writePermitted)\r
-       {\r
-                       *pcbWritten = 0;\r
-                       SetLastError(ERROR_ACCESS_DENIED);\r
-                       return FALSE;\r
-       }\r
-\r
-       obj = pFile->obj;\r
-\r
-       *pcbWritten = 0;\r
-\r
-\r
-               nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);\r
-               if(nwritten >= 0)\r
-               {\r
-                       pFile->offset += nwritten;\r
-                       *pcbWritten = nwritten;\r
-               }\r
-               if(nwritten != cbWrite)\r
-               {\r
-                       SetLastError(ERROR_DISK_FULL);\r
-               }\r
-\r
-\r
-       return nwritten != cbWrite? FALSE : TRUE; \r
-}\r
-\r
-\r
-BOOL YFSD_WriteFile( \r
-       PFILE pFile, \r
-       PCVOID pBuffer, \r
-       DWORD cbWrite, \r
-       PDWORD pcbWritten, \r
-       OVERLAPPED *pOverlapped )\r
-{\r
-       BOOL result;\r
-\r
-       yfsd_LockYAFFS();\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));\r
-\r
-       result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       return result;\r
-}\r
-\r
-BOOL YFSD_WriteFileWithSeek( \r
-       PFILE pFile, \r
-       PCVOID pBuffer, \r
-       DWORD cbWrite, \r
-       PDWORD pcbWritten, \r
-       OVERLAPPED *pOverlapped,\r
-       DWORD dwLowOffset, \r
-       DWORD dwHighOffset )\r
-{\r
-       BOOL result;\r
-       DWORD rememberedOffset;\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));\r
-\r
-       \r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       rememberedOffset = pFile->offset;\r
-\r
-       pFile->offset = dwLowOffset;\r
-       // ignore high offset for now\r
-\r
-       result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);\r
-\r
-       //pFile->offset = rememberedOffset;\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       return result;\r
-}\r
-\r
-DWORD YFSD_SetFilePointer( \r
-       PFILE pFile, \r
-       LONG lDistanceToMove, \r
-       PLONG pDistanceToMoveHigh, \r
-       DWORD dwMoveMethod )\r
-{\r
-       // ignore high offset for now\r
-\r
-       DWORD offset = 0xFFFFFFFF;\r
-       DWORD oldPos;\r
-       int fileSize;\r
-       int seekNegative = 0;\r
-\r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return offset;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-\r
-       oldPos = pFile->offset;\r
-\r
-       if(dwMoveMethod == FILE_BEGIN)\r
-       {\r
-               if(lDistanceToMove >= 0)\r
-               {       \r
-                       offset = pFile->offset = lDistanceToMove;\r
-               }\r
-               else\r
-               {\r
-                       seekNegative = 1;\r
-               }\r
-       }\r
-       else if(dwMoveMethod == FILE_END)\r
-       {\r
-               fileSize = yaffs_GetObjectFileLength(pFile->obj);\r
-               if(fileSize >= 0 &&\r
-                  (fileSize + lDistanceToMove) >= 0)\r
-               {\r
-                       offset = pFile->offset = fileSize + lDistanceToMove;\r
-               }\r
-               else\r
-               {\r
-                       seekNegative = 1;\r
-               }\r
-       }\r
-       else if(dwMoveMethod == FILE_CURRENT)\r
-       {\r
-               if(pFile->offset + lDistanceToMove >= 0)\r
-               {\r
-                       offset = pFile->offset = pFile->offset + lDistanceToMove;               \r
-               }\r
-               else\r
-               {\r
-                               seekNegative = 1;\r
-               }\r
-       }\r
-\r
-       if(seekNegative)\r
-       {\r
-                       SetLastError(ERROR_NEGATIVE_SEEK);\r
-                       \r
-       }\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",\r
-                                 dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));\r
-\r
-       return offset;\r
-\r
-}\r
-\r
-DWORD YFSD_GetFileSize( \r
-       PFILE pFile, \r
-       PDWORD pFileSizeHigh )\r
-{\r
-       int fileSize;\r
-       \r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));\r
-       \r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return -1;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       fileSize = yaffs_GetObjectFileLength(pFile->obj);\r
-\r
-       yfsd_UnlockYAFFS();\r
-       if(pFileSizeHigh)\r
-                *pFileSizeHigh = 0;\r
-\r
-       return fileSize;\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_GetFileInformationByHandle( \r
-       PFILE pFile,\r
-       PBY_HANDLE_FILE_INFORMATION pFileInfo )\r
-{\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));\r
-\r
-       if(!pFile || !pFile->obj || !pFileInfo)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\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
-       pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       return TRUE;\r
-}\r
-\r
-BOOL YFSD_FlushFileBuffers(PFILE pFile )\r
-{\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
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));\r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       yaffs_FlushFile(pFile->obj,1);\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
-       \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
-       \r
-       return TRUE;\r
-}\r
-\r
-BOOL YFSD_GetFileTime( \r
-       PFILE pFile, \r
-       FILETIME *pCreation, \r
-       FILETIME *pLastAccess, \r
-       FILETIME *pLastWrite )\r
-{\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);\r
-       if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);\r
-       if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);\r
-\r
-       yfsd_UnlockYAFFS();\r
-\r
-       return TRUE;\r
-}\r
-\r
-BOOL YFSD_SetFileTime( \r
-       PFILE pFile, \r
-       CONST FILETIME *pCreation, \r
-       CONST FILETIME *pLastAccess, \r
-       CONST FILETIME *pLastWrite )\r
-{\r
-       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-       int nameExists = 0;\r
-       int result = FALSE;\r
-       yfsd_Volume *vol = NULL;\r
-       DWORD attribs = 0;\r
-       DWORD objSize = 0;\r
-       DWORD mtime[2];\r
-\r
-       \r
-       RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));\r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-       \r
-       \r
-       yfsd_LockYAFFS();\r
-\r
-       if(pCreation) \r
-       {\r
-                yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);\r
-               pFile->obj->dirty = 1;\r
-       }\r
-       if(pLastAccess)\r
-       {\r
-               yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);\r
-               pFile->obj->dirty = 1;\r
-       }\r
-       if(pLastWrite)\r
-       {\r
-               yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);\r
-               pFile->obj->dirty = 1;\r
-       }\r
-       if(pCreation || pLastAccess || pLastWrite)\r
-       {\r
-               result = yaffs_FlushFile(pFile->obj,0);\r
-       }\r
-\r
-       if(result)\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
-       yfsd_UnlockYAFFS();\r
-\r
-       // Call shell function\r
-       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
-\r
-       return TRUE;\r
-}\r
-   \r
-BOOL YFSD_SetEndOfFile( \r
-PFILE pFile )\r
-{\r
-\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
-       static unsigned char zeros[512];\r
-\r
-       int result;\r
-       BOOL retVal = FALSE;\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));\r
-\r
-       if(!pFile || !pFile->obj)\r
-       {\r
-               SetLastError(ERROR_INVALID_HANDLE);\r
-               return FALSE;\r
-       }\r
-\r
-       yfsd_LockYAFFS();\r
-       result = yaffs_ResizeFile(pFile->obj,pFile->offset);\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));\r
-\r
-       // Resize only works if we're shortening the file.\r
-       // If the result is shorter than the offset, then we need to write zeros....\r
-       // \r
-       if(result != pFile->offset)\r
-       {\r
-               if(result < pFile->offset)\r
-               {\r
-\r
-                       int nBytes = pFile->offset - result;\r
-                       int thisWriteSize;\r
-                       int written;\r
-                       BOOL ok = TRUE;\r
-\r
-                       memset(zeros,0,512);\r
-\r
-                       pFile->offset = result;\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));\r
-                       while(nBytes > 0 && ok)\r
-                       {\r
-                               thisWriteSize = (nBytes > 512) ? 512  : nBytes;\r
-\r
-                               ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);      \r
-                               if(written != thisWriteSize)\r
-                               {\r
-                                       ok = FALSE;\r
-                               }\r
-\r
-                               nBytes -= thisWriteSize;\r
-                       }\r
-\r
-                       retVal = ok;\r
-               }\r
-               else\r
-               {\r
-\r
-                       SetLastError(ERROR_ACCESS_DENIED);\r
-                       retVal = FALSE;\r
-               }\r
-       }\r
-       else\r
-       {\r
-               retVal = TRUE;\r
-       }\r
-       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
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));\r
-\r
-\r
-       \r
-       return retVal;\r
-}\r
-\r
-BOOL YFSD_DeviceIoControl( \r
-       PFILE pFile, \r
-       DWORD dwIoControlCode, \r
-       PVOID pInBuf, \r
-       DWORD nInBufSize, \r
-       PVOID pOutBuf, \r
-       DWORD nOutBufSize, \r
-       PDWORD pBytesReturned, \r
-       OVERLAPPED *pOverlapped )\r
-{\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));\r
-\r
-       return FALSE;\r
-}\r
-\r
-BOOL YFSD_CloseFile( PFILE pFile )\r
-{\r
-       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-       int nameExists = 0;\r
-       yfsd_Volume *vol = NULL;\r
-       DWORD attribs = 0;\r
-       DWORD objSize = 0;\r
-       DWORD mtime[2];\r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));\r
-\r
-       yfsd_LockYAFFS();\r
-\r
-       if(!pFile)\r
-       {\r
-               RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));\r
-       }\r
-       else\r
-       {\r
-               if(pFile->obj)\r
-               {\r
-                       pFile->obj->inUse--;\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));\r
-                       yaffs_FlushFile(pFile->obj,1);\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
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));\r
-                       if(pFile->fullName)\r
-                       {\r
-                               wcscpy(fpn,pFile->fullName);\r
-                               nameExists = 1;\r
-                       }\r
-                       vol = pFile->myVolume;\r
-                       yfsd_PutWinFile(pFile);\r
-               }\r
-               else\r
-               {\r
-                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));\r
-               }\r
-\r
-       }\r
-       yfsd_UnlockYAFFS();\r
-\r
-\r
-       if(nameExists && 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
-\r
-       \r
-\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));\r
-\r
-       return TRUE;\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_CloseVolume(PVOLUME pVolume )\r
-{\r
-       RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));\r
-       yfsd_FlushAllFiles();\r
-       return TRUE;\r
-}\r
-\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>
+//slf021104b begin
+#include <diskio.h>
+//slf021104b end
+
+#define MAX_WIN_FILE   200
+#define YFSD_NAME_LENGTH 128
+#define YFSD_FULL_PATH_NAME_SIZE 500
+
+
+#define YFSD_DISK_NAME L"Disk"
+#define YFSD_BOOT_NAME L"Boot"
+
+#define PARTITION_START_NUMBER (1280)  
+
+
+// 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
+//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;
+
+
+typedef struct
+{
+       yaffs_Device dev;
+       DWORD   hdsk;
+       DWORD    mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
+       BOOL    isMounted;
+       BOOL    configured;
+//     DWORD   guard0[100];
+//     DWORD   guard1[100];
+       SHELLFILECHANGEFUNC_t shellFunction;
+       PWSTR volName;
+} yfsd_Volume;
+
+typedef struct 
+{
+       yaffs_Object *obj;
+       DWORD offset;
+       BOOL isopen;
+       BOOL dirty;
+       WCHAR *fullName;
+       yfsd_Volume *myVolume;
+       BOOL writePermitted;
+       BOOL readPermitted;
+       BOOL shareRead;
+       BOOL shareWrite;
+
+}      yfsd_WinFile;
+
+struct yfsd_FoundObjectStruct
+{
+  yaffs_Object *obj;
+  struct yfsd_FoundObjectStruct *next;
+};
+
+typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
+
+typedef struct 
+{
+       yaffs_Object *dir;
+       char pattern[YFSD_NAME_LENGTH+1];
+       yaffs_FoundObject *foundObjects;
+}      yfsd_WinFind;
+
+
+
+#define PSEARCH yfsd_WinFind*
+
+#define PVOLUME yfsd_Volume*
+#define PFILE   yfsd_WinFile*
+
+#define FSD_API        YFSD
+
+#include <fsdmgr.h>
+
+//slf021105a begin
+//static yfsd_Volume disk_volume;
+//static yfsd_Volume boot_volume;
+static yfsd_Volume * disk_volumes[MAXPARTITIONS];
+//slf021105a end;
+
+static CRITICAL_SECTION yaffsLock;
+static CRITICAL_SECTION winFileLock;
+
+static int yaffsLockInited = 0;
+
+static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
+
+#if 0
+static yfsd_SetGuards(void)
+{
+       int i;
+       for(i = 0; i < 100; i++)
+       {
+               yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
+       }
+}
+
+static void yfsd_CheckGuards(void)
+{
+       int i;
+       int found;
+       for(i = found = 0; i < 100 && !found; i++)
+       {
+                       if(yfsd_volume.guard0[i] != i)
+                       {
+                                       RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
+                                       found = 1;
+                       }
+                       if(yfsd_volume.guard1[i] != i)
+                       {
+                                       RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
+                                       found = 1;
+                       }
+       }
+}
+#endif
+
+
+#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"));
+       EnterCriticalSection(&winFileLock);
+}
+void yfsd_UnlockWinFiles(void)
+{
+       //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
+       LeaveCriticalSection(&winFileLock);
+}
+
+int lockwaits;
+
+void yfsd_LockYAFFS(void)
+{
+       //yfsd_CheckGuards();
+       //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
+       lockwaits++;
+       EnterCriticalSection(&yaffsLock);
+       //RETAILMSG (MSGSTATE, (L" locked\r\n"));
+}
+void yfsd_UnlockYAFFS(void)
+{
+       //yfsd_CheckGuards();
+       //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
+       LeaveCriticalSection(&yaffsLock);
+       lockwaits--;
+       //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
+}
+
+
+void yfsd_InitialiseWinFiles(void)
+{
+       int i;
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
+
+       InitializeCriticalSection(&winFileLock);
+
+       yfsd_LockWinFiles();
+       for(i = 0; i < MAX_WIN_FILE; i++)
+       {
+                       yfsd_winFile[i].isopen = 0;
+       }
+       yfsd_UnlockWinFiles();
+}
+
+yfsd_WinFile * yfsd_GetWinFile(void)
+{
+       int i;
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
+
+       yfsd_LockWinFiles();
+
+       for(i = 0; i < MAX_WIN_FILE; i++)
+       {
+               if(!yfsd_winFile[i].isopen)
+               {
+                       yfsd_winFile[i].isopen = 1;
+                       yfsd_winFile[i].writePermitted = 0;
+                       yfsd_winFile[i].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;
+
+                       yfsd_UnlockWinFiles();
+                       return &yfsd_winFile[i];
+               }
+       }
+
+       yfsd_UnlockWinFiles();
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
+
+       return NULL;
+}
+
+void yfsd_PutWinFile(yfsd_WinFile *f)
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
+       yfsd_LockWinFiles();
+       f->isopen = 0;
+       f->obj = NULL;
+       if(f->fullName)
+       {
+               free(f->fullName);
+               f->fullName = NULL;
+       }
+
+       yfsd_UnlockWinFiles();
+}
+
+
+
+void yfsd_FlushAllFiles(void)
+{
+       int i;
+       RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
+
+       yfsd_LockYAFFS();
+       yfsd_LockWinFiles();
+       for(i = 0; i < MAX_WIN_FILE; i++)
+       {
+               if(yfsd_winFile[i].isopen &&
+                  yfsd_winFile[i].obj)
+               {
+                       yaffs_FlushFile(yfsd_winFile[i].obj,1);
+               }
+       }
+       yfsd_UnlockWinFiles();
+       yfsd_UnlockYAFFS();
+}
+
+//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
+       //slf021104b begin
+       //volName already has the initial backslash if it needs it.
+       //wcscpy(fpn,L"\\");
+       //wcscat(fpn,vol->volName);
+       wcscpy(fpn,vol->volName);
+       //slf021104b end
+       if(pathName[0] != '\\')
+       {
+               wcscat(fpn,L"\\");
+       }
+       wcscat(fpn,pathName);
+
+       return fpn;
+
+}
+
+
+// FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
+
+void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
+{
+       
+       wft->dwLowDateTime = target[0];
+       wft->dwHighDateTime = target[1];
+
+}
+
+void yfsd_NullWinFileTime(FILETIME *wft)
+{
+       wft->dwLowDateTime = 0;
+       wft->dwHighDateTime = 0;
+}
+
+void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
+{
+       target[0] = wft->dwLowDateTime;
+       target[1] = wft->dwHighDateTime;
+}
+
+void  yfsd_WinFileTimeNow(__u32 target[2])
+{
+       SYSTEMTIME st;
+       FILETIME ft;
+
+       GetSystemTime(&st);
+       SystemTimeToFileTime(&st,&ft);
+       yfsd_WinFileTimeToU32s(&ft,target);
+}
+
+// Cut down the name to the parent directory, then inform the shell of
+// a change to the directory.
+void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
+{
+       WCHAR str[500];
+       int i;
+       wcscpy(str,fullPathName);
+
+       i = wcslen(str) - 1;
+       
+       if(i > 0)
+       {
+               str[i] = 0;
+               i--;
+       }
+
+       // Curveball if the name is a directory (ie. we're doing an update of
+       // a directory because we added a directory item). , then it might end in a \
+       // which we must toss first
+       if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
+       {
+               str[i] = 0;
+               i--;
+       }
+
+       // Ok, now strip back...
+
+       while(i >= 0 && str[i] != '\\' && str[i] != '/')
+       {
+               str[i] = 0;
+               i--;
+       }
+
+       if(pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_UPDATEDIR;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)str;
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = 0;
+                       yfsd_NullWinFileTime(&fc.ftModified);
+                       fc.nFileSize = 0;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
+
+       }
+
+
+}
+
+
+// Minimal name test for now
+BOOL yfsd_NameIsValid (const char *name)
+{
+       int length = strlen(name);
+
+       return (length > 0 && length <= YFSD_NAME_LENGTH);
+
+}
+
+// File attributes:
+// Wince understands the following attributes of any use to YAFFS:
+//  
+//   ARCHIVE
+//   HIDDEN
+//   READONLY
+//   SYSTEM
+//   TEMPORARY
+//
+//      Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
+//
+//   It also understands NORMAL. If no other flag is set, then set NORMAL.
+//   If any of the above are set, then NORMAL must **not** be set.
+//      Ignore this and the WinCE Explorer barfs the file.
+//
+//
+// in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
+
+// 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 & 
+                                       (FILE_ATTRIBUTE_READONLY | 
+                                        FILE_ATTRIBUTE_ARCHIVE | 
+                                        FILE_ATTRIBUTE_HIDDEN |
+                                        FILE_ATTRIBUTE_SYSTEM);
+
+               if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
+
+               if(result & ~FILE_ATTRIBUTE_NORMAL)
+               { 
+                       result &= ~FILE_ATTRIBUTE_NORMAL;
+               }
+               else 
+               {
+                       result = FILE_ATTRIBUTE_NORMAL;
+               }
+
+
+               return result;
+}
+
+
+
+/*
+*      Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
+*      reached.  Characters are copied from input into output until the above stop
+*      condition is reached - output is then given a '\0'.  output must be at least
+*      as large as outSize
+*/
+static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
+{
+       int counter = 0;
+       char *t = output;
+       /* strip any starting \'s */
+       //RETAILMSG(1, (L"\r\nParsing.. "));
+       while (*input == '\\' || *input == '/') input++, counter++;
+
+       for (; counter < outSize - 1; counter++)
+       {
+               if (*input == '\0' ||
+                       ((*input == '\\' || *input == '/') && input[1] == '\0'))   // special case: if the string ends in a '\', then toss the '\'
+               {
+                       counter = -1;   // break & tell people we've run to the end
+                       break;
+               }
+               if (*input == '\\' || *input == '/')
+                       break;
+               //RETAILMSG(1, (L"%c", *input));
+               *output = (char) (*input);
+               input++;
+               output++;
+       }
+       *output++ = '\0';
+       *output  = '\0';
+//     RETAILMSG(1, (L"\r\nOut %a\r\n", t));
+       
+       return counter;
+}
+
+/*
+*      Since the notion of paths as WinCE sees them and as YAFFS sees them
+*      is different, we needed a helper function to search from the root of
+*      device along the string in path.  The processed pointer is set to where
+*      abouts in the string the function was able to search up to.
+*/
+yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
+{
+       // a buffer to keep the current chunk of path we're talking about it
+       char pathChunk[255];
+       int chunkSize;
+       int counter;
+       // the current object we are at
+       yaffs_Object *current;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
+       // start at the root of this device
+       current = yaffs_Root(device);
+       *processed = '\0';
+
+       do
+       {
+       //      parse chunks until we run out
+               chunkSize = parseToNextSlash(path, pathChunk, 255);
+//             RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
+               if (chunkSize == -1)
+                       break;
+       //      move the path pointer along
+               path += chunkSize;
+       //      try and find the next yaffs object by chunkname 
+               current = yaffs_FindObjectByName(current, pathChunk);
+               if (current == 0)
+               {
+                       processed[0] = '\0';
+                       return 0;
+               }
+       } while (1);
+
+       for (counter = 0; counter < length; counter++)
+       {
+               // Get the rest of the string
+               processed[counter] = pathChunk[counter];
+               if (pathChunk[counter] == '\0')
+                       break;
+       }
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
+
+       return current;
+}
+
+
+yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
+{
+       yaffs_Object *obj = NULL;
+       yaffs_Object *parent = NULL;
+       char name[YFSD_NAME_LENGTH+1];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
+
+       parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
+
+       if(parent && yfsd_NameIsValid(name))
+       {
+               obj = yaffs_FindObjectByName(parent,name);
+       }
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
+
+       return obj;
+}
+
+BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
+{
+       //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;
+       //slf021104b end
+
+
+       yfsd_LockYAFFS();
+       
+       //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
+
+       //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));
+
+
+#if 0
+                       for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
+                       {
+                                       switch(vol->dev.blockInfo[i].blockState)
+                                       {
+                                               case YAFFS_BLOCK_STATE_DEAD:
+                               
+                                                       RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
+                                                       deadBlox++;
+                                                       break;
+                                               case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
+                                               case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
+                                               case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
+                                               case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
+                                               default:
+                                                       RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
+                                                       break;
+                                       }
+                       }
+
+                       RETAILMSG(1, (L"Blocks dead  %d empty %d full %d allocating %d dirty %d\r\n",
+                                                       deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
+
+#endif
+
+//slf021127a begin check for error returns!
+                       vol->isMounted = 1;
+               }
+       }
+//slf021127a begin check for error returns!
+       
+       yfsd_UnlockYAFFS();
+
+//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);
+       // 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)
+       {
+               //slf021104b Begin
+               // Get some space for the volume name.
+        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
+       {
+               vol->isMounted = 0;
+               SetLastError(ERROR_OUTOFMEMORY);
+               return FALSE;
+       }       
+}
+
+
+BOOL YFSD_MountDisk(HDSK hdsk)
+{
+//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.
+       // NB THis call might happen redundantly.
+       //
+       //
+       // If yaffs is not initialised, then call the 
+       // initialisation function
+       //
+       RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
+
+       if (!yaffsLockInited)
+       {
+               InitializeCriticalSection(&yaffsLock);
+               yfsd_InitialiseWinFiles();
+               yaffsLockInited = 1;
+       }
+
+       //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
+       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);
+//
+//     
+//     if(disk_volume.isMounted)
+//     {
+//             return TRUE;
+//     }
+//#else
+//     // Want both boot and disk
+//     YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
+//     YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
+//
+//     
+//     if(disk_volume.isMounted && boot_volume.isMounted)
+//     {
+//             return TRUE;
+//     }
+//#endif
+//
+//     return FALSE;
+#endif
+//slf021105a end
+
+//     yfsd_SetGuards();
+
+       // todo - get name from registry
+
+}
+
+
+BOOL YFSD_UnmountDisk(HDSK hdsk)
+{
+//slf021105a begin
+       int i;
+//slf021105a end
+       RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
+       
+       //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);
+//     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;
+}
+
+
+BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
+{
+       // security attributes are ignored (should be NULL)
+
+       yaffs_Object *newDir = NULL;
+       yaffs_Object *parent = NULL;
+       char name[YFSD_NAME_LENGTH+1];
+       ULONG objSize;
+       DWORD attribs;
+       unsigned modifiedTime[2];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
+
+       yfsd_LockYAFFS();
+
+       parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
+
+       //slf021101b begin 
+       if (parent)
+       {
+               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();
+
+       // Call shell function to tell of new directory
+       if(newDir && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_MKDIR;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = attribs; 
+                       yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       //yfsd_ShellDirectoryChanged(pVolume,fpn);
+
+       }
+
+//slf021101b begin 
+//     if(parent && !newDir)
+//     {
+//                     SetLastError(ERROR_DISK_FULL);
+//     }
+//slf021101b end
+
+       return newDir ? TRUE : FALSE;
+}
+
+
+BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
+{
+       int result = FALSE;
+       yaffs_Object *parent = NULL;
+       yaffs_Object *obj;
+       char name[YFSD_NAME_LENGTH+1];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory (%s)\r\n", pathName));
+       
+       yfsd_LockYAFFS();
+
+       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
+       if(!obj)
+       {
+               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)
+       {
+               SetLastError(ERROR_ACCESS_DENIED);
+               result = FALSE;
+       }
+       else if(obj->inUse)
+       {
+               SetLastError(ERROR_ACCESS_DENIED);
+               result = FALSE;
+       }
+       else
+       {
+
+               parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
+
+               if(parent && yfsd_NameIsValid(name))
+               {
+                       result = yaffs_Unlink(parent,name);
+                       if(!result)
+                               SetLastError(ERROR_DIR_NOT_EMPTY);
+               }
+       }
+
+       yfsd_UnlockYAFFS();
+
+       if(result && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_RMDIR;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = 0;
+                       yfsd_NullWinFileTime(&fc.ftModified);
+                       fc.nFileSize = 0;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+       
+       return result ? TRUE : FALSE;
+}
+
+
+DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
+{
+       yaffs_Object *obj = NULL;
+
+       DWORD result = 0xFFFFFFFF;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
+
+       yfsd_LockYAFFS();
+
+       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+
+       if(obj)
+       {
+               result = yfsd_GetObjectWinAttributes(obj);
+       }
+       else
+       {
+               SetLastError(ERROR_FILE_NOT_FOUND);
+       }
+
+       yfsd_UnlockYAFFS();
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
+       return result;
+
+       
+}
+
+BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
+{
+       yaffs_Object *obj = NULL;
+       DWORD mtime[2];
+       DWORD attribs;
+       DWORD objSize;
+
+       int result = 0;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
+
+       if(!yfsd_CheckValidAttributes(dwFileAttributes))
+       {
+                       SetLastError(ERROR_INVALID_PARAMETER);
+                       return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+       obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+
+       if(obj)
+       {
+               obj->st_mode = dwFileAttributes;
+               obj->dirty = 1;
+               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
+       {
+               SetLastError(ERROR_FILE_NOT_FOUND);
+       }
+
+       yfsd_UnlockYAFFS();
+
+       if(result && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_ATTRIBUTES;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes =  attribs;
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       //yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+       
+
+       return result;
+
+}
+
+BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
+{
+       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));
+
+       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;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_DELETE;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = -1;
+                       yfsd_NullWinFileTime(&fc.ftModified);
+                       fc.nFileSize = 0;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+
+       return result ? TRUE : FALSE;
+}
+
+BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
+{
+       yaffs_Object *newParent = NULL;
+       yaffs_Object *oldParent = NULL;
+       yaffs_Object *obj = NULL;
+       char oldName[YFSD_NAME_LENGTH+1];
+       char newName[YFSD_NAME_LENGTH+1];
+       int result = 0;
+       int objIsDir = 0;
+       DWORD attribs;
+       DWORD objSize;
+       DWORD mtime[2];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
+
+       yfsd_LockYAFFS();
+
+       oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
+       newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
+
+       if(oldParent  && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
+       {
+               result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
+               if(!result)
+               {
+                       SetLastError(ERROR_FILE_NOT_FOUND);
+               }
+
+               obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
+               if(obj)
+               {
+                       objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
+                       attribs = yfsd_GetObjectWinAttributes(obj);
+                       objSize = yaffs_GetObjectFileLength(obj);
+                       mtime[0] = obj->win_mtime[0];
+                       mtime[1] = obj->win_mtime[1];
+               }
+       }
+       else
+       {
+               SetLastError(ERROR_PATH_NOT_FOUND);
+       }
+
+       yfsd_UnlockYAFFS();
+
+
+       if(result && pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
+                       WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
+                       fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
+                       fc.dwAttributes = attribs;
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn1);
+                       yfsd_ShellDirectoryChanged(pVolume,fpn2);
+       }
+
+
+       return result ? TRUE : FALSE;
+
+}
+
+BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
+{
+       //slf021104c begin
+    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
+}
+
+BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
+{
+
+       int nChunks;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
+
+       yfsd_LockYAFFS();
+       nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
+       yfsd_UnlockYAFFS();
+
+       if(nChunks >= 0)
+       {
+               // Let's pretentd our clusters are the same size as eraseable blocks...
+               *pBytesPerSector = 512;
+               *pSectorsPerCluster  =32;
+               *pFreeClusters = nChunks/32;
+               *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
+       }
+
+       return (nChunks >= 0)? TRUE : FALSE;
+
+
+
+}
+
+void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
+{
+       // Flags can be one of:
+       // FSNOTIFY_POWER_ON: no action required
+       // FSNOTIFY_POWER_OFF: flush all files
+       // FSNOTIFY_DEVICE_ON: no action required
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
+       if(dwFlags == FSNOTIFY_POWER_OFF)
+       {
+               yfsd_FlushAllFiles();
+       }
+
+}
+
+
+BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
+       
+       pVolume->shellFunction = pfn;
+
+       return TRUE;
+}
+
+
+
+
+
+int iMatch(const char a, const char b)
+{
+       if (a == '?' || b == '?')
+               return 1;
+       return (toupper(a) == toupper(b));
+}
+
+void pString(const char *inp)
+{
+       while (*inp) RETAILMSG(1, (L"%c", *inp++));
+}
+
+int regularMatch(const char *regexp, const char *str)
+{
+//     pString(regexp);
+//     RETAILMSG(1, (L" "));
+//     pString(str);
+//     RETAILMSG(1, (L"\r\n"));
+
+       if (*regexp == 0 && *str == 0)
+       {
+               //RETAILMSG(1, (L"Match!\r\n"));
+               return 1;
+       }
+       if (*regexp == '*')                     
+       {
+               regexp++;
+               if (*regexp == 0)   // end of the expression is a *, we must match
+               {
+                       //RETAILMSG(1, (L"Match!\r\n"));
+                       return 1;
+               }
+               while (!iMatch(*regexp, *str)) // throw away chars from str until we match
+               {
+                       if (*str == 0)  // if we're not at the end
+                       {
+                               // if we have .* left to match, but the str is finished then match it OK
+                               if (regexp[0] == '.' && regexp[1] == '*')
+                               {
+                                       //RETAILMSG(1, (L"Match!\r\n"));
+                                       return 1;
+                               }
+                               else
+                               {
+                               // the extension failed the match
+                                       //RETAILMSG(1, (L"No Match!\r\n"));
+                                       return 0;
+                               }
+                       }
+                       str++;
+               } 
+               // right now we should either eat more characters, or try to match
+               return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
+       }
+//  compare chars until we hit another *, or we fail
+       while (iMatch(*regexp, *str))
+       {
+               if (*regexp == 0 && *str == 0)
+               {
+                       //RETAILMSG(1, (L"Match!\r\n"));
+                       return 1;
+               }
+               regexp++;
+               str++;
+       }
+
+       if (*regexp == 0 && *str == 0)
+       {
+               //RETAILMSG(1, (L"Match!\r\n"));
+               return 1;
+       }
+
+       if (*regexp == '*')
+               return regularMatch(regexp, str);
+
+       //RETAILMSG(1, (L"No Match!\r\n"));
+       return 0;
+}
+
+
+void yfsd_DeleteFinder(PSEARCH pSearch)
+{
+  if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
+  {
+    yaffs_FoundObject *it;
+    yaffs_FoundObject *temp;
+
+    it = pSearch->foundObjects;
+
+    while(it != NULL)
+    {
+      temp = it;
+      it = it->next;
+      
+      free(temp);
+    }
+
+    pSearch->foundObjects = NULL;
+  }
+
+               pSearch->dir->inUse--;
+               free(pSearch);
+}
+
+BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
+{
+  //Iterate through the current list of objs already found and return true if already exists.
+  //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
+  BOOL found = FALSE;
+
+  yaffs_FoundObject *it;
+  it = pSearch->foundObjects;
+
+  
+  while(it->next != NULL) //iterate through singly linked list.
+  {
+    if(it->obj == l)
+    {
+      found = TRUE;
+      break;
+    }
+    it = it->next;
+  }
+
+  if(!found)
+  {
+    //Add the item to the list.
+    //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
+    it->next = malloc(sizeof(yaffs_FoundObject));
+    it->next->next = NULL;
+    it->next->obj = 0;
+
+    it->obj = l;
+  }
+
+  return found;
+}
+
+#if 0
+// slower one
+BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
+{
+
+       struct list_head *i;
+       int pos;
+       yaffs_Object *l;
+       BOOL found = 0;
+
+       char name[YAFFS_MAX_NAME_LENGTH+1];
+
+  if(!pSearch->foundObjects)
+  {
+    pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
+    pSearch->foundObjects->next = NULL;
+    pSearch->foundObjects->obj = 0;
+  }
+
+
+       yfsd_LockYAFFS();
+
+       pos = 0;
+       list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
+       {
+
+               l = list_entry(i, yaffs_Object,siblings);
+
+               yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
+
+               if(regularMatch(pSearch->pattern,name))
+               {
+                       if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
+                       {               
+
+                               
+                               found = 1;
+                               //pSearch->currentPos++;
+
+                               // fill out find data
+
+                               pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
+
+                               yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
+                               yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
+                               yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
+
+                               pfd->nFileSizeHigh = 0;
+                               pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
+                               pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
+
+                               MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
+
+                               RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
+                                                       pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
+                                                       l->variant.fileVariant.scannedFileSize));
+                               goto out_of_here;
+                       }
+                       else
+                       {
+                               pos++;
+                       }
+               }
+       }
+
+out_of_here:
+       yfsd_UnlockYAFFS();
+
+
+       if(!found)
+       {
+               SetLastError(ERROR_NO_MORE_FILES);
+       }
+       return found;
+       
+}
+
+#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 = (CEOID)(INVALID_HANDLE_VALUE); // 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 )
+{
+
+       // Create a search context, register it, and do the first search
+
+       PSEARCH pSearch;
+       HANDLE h = INVALID_HANDLE_VALUE;
+       BOOL found = 0;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
+
+       pSearch = malloc(sizeof(yfsd_WinFind));
+       if(!pSearch)
+       {
+               SetLastError(ERROR_OUTOFMEMORY);
+       }
+
+       yfsd_LockYAFFS();
+
+       if(pSearch)
+       {
+               pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
+               pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
+               if(pSearch->dir)
+               {
+                               pSearch->dir->inUse++;
+               }
+               else
+               {
+                       free(pSearch);
+                       pSearch = NULL;
+                       SetLastError(ERROR_PATH_NOT_FOUND);
+               }
+       }
+
+       yfsd_UnlockYAFFS();
+
+
+
+       if(pSearch)
+       {
+               found = yfsd_DoFindFile(pSearch,pfd);
+
+               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)
+               {
+                       yfsd_DeleteFinder(pSearch);
+               }
+
+       }
+
+
+       return h;
+}
+
+BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
+       if(!pSearch)
+       {
+               return FALSE;
+       }
+       return yfsd_DoFindFile(pSearch,pfd);
+}
+
+BOOL YFSD_FindClose( PSEARCH pSearch )
+{      
+       RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
+       if(!pSearch)
+       {
+               return FALSE;
+       }
+       yfsd_DeleteFinder(pSearch);
+       return TRUE;
+}
+
+
+HANDLE YFSD_CreateFileW( 
+       PVOLUME pVolume, 
+       HANDLE hProc, 
+       PCWSTR pwsFileName, 
+       DWORD dwAccess, 
+       DWORD dwShareMode,
+       PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
+       DWORD dwCreate,
+       DWORD dwFlagsAndAttributes, 
+       HANDLE hTemplateFile ) // ignore
+{
+
+
+       yaffs_Object *parent = NULL;
+       yaffs_Object *obj = NULL;
+       char name[YFSD_NAME_LENGTH+1];
+       int mode;
+       yfsd_WinFile *f = NULL;
+       HANDLE handle = INVALID_HANDLE_VALUE;
+       unsigned modifiedTime[2];
+       unsigned objSize;
+
+       BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
+       BOOL 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)
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
+       }
+
+       if(!yfsd_CheckValidAttributes(mode))
+       {
+                       SetLastError(ERROR_INVALID_PARAMETER);
+                       return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+
+       parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
+
+
+       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
+                       //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);
+                               if(!obj)
+                                       SetLastError(ERROR_DISK_FULL);
+                               fileCreated = TRUE;
+                       }
+                       //slf021220b begin Fix still more bugs in CreateFile.
+                       else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+                       {
+                               obj = NULL;
+                               SetLastError(ERROR_ALREADY_EXISTS);
+                       }
+                       //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)
+               {
+                       //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"));
+                               obj = yaffs_MknodFile(parent,name,mode,0,0);
+                               if(!obj)
+                                       SetLastError(ERROR_DISK_FULL);
+                               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"));
+                       }
+               }
+               else if(dwCreate == OPEN_EXISTING)
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
+                       //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;
+           //                          }
+            //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"));
+                       //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)))
+                       {
+                               obj = NULL;
+                               SetLastError(ERROR_ACCESS_DENIED);
+                       }
+                       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)
+               {
+                       //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 parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
+                               obj = yaffs_MknodFile(parent,name,mode,0,0);
+                               if(!obj)
+                                       SetLastError(ERROR_DISK_FULL);
+                               fileCreated = TRUE;
+                       }
+                       //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"));
+                               // 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
+               {
+                               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
+                               SetLastError(ERROR_INVALID_PARAMETER);
+               }
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
+               SetLastError(ERROR_PATH_NOT_FOUND);
+       }
+
+       if(obj)
+       {
+                       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)
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
+               f = yfsd_GetWinFile();
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
+       }
+
+       if(f)
+       {
+
+               handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
+
+               if(handle != INVALID_HANDLE_VALUE)
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
+
+                       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;
+                       //slf021220d begin oops typo.
+                       f->readPermitted = readPermitted;
+                       //slf021220d end oops typo.
+                       f->shareRead= shareRead;
+                       f->shareWrite = shareWrite;
+                       f->myVolume = pVolume;
+                       obj->inUse++;
+
+                       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));
+               }
+               else
+               {
+                       yfsd_PutWinFile(f);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
+               }
+
+       }
+
+       yfsd_UnlockYAFFS();
+
+       if(handle != INVALID_HANDLE_VALUE && 
+          fileCreated &&
+          pVolume->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_CREATE;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = mode;
+                       yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       pVolume->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+                       yfsd_ShellDirectoryChanged(pVolume,fpn);
+       }
+
+       if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
+       {
+                       // Remember the name
+
+                       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+                       int slen;
+
+                       yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+                       slen = wcslen(fpn);
+                       f->fullName = malloc((slen+1)* sizeof(WCHAR));
+                       if(f->fullName)
+                       {
+                               wcscpy(f->fullName,fpn);
+                       }
+
+       }
+
+
+       return handle;
+
+}
+
+BOOL yfsd_DoReadFile( 
+       PFILE pFile, 
+       PVOID pBuffer, 
+       DWORD cbRead, 
+       PDWORD pcbRead)
+{
+       
+       DWORD maxRead;
+       int nread = 0;
+       yaffs_Object *obj = NULL;
+
+
+       if(pcbRead)
+       {
+               *pcbRead = 0;
+       }
+       else
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
+       }
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+       
+       obj = pFile->obj;
+
+       if(yaffs_GetObjectFileLength(obj) > pFile->offset)
+       {
+               maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
+       }
+       else
+       {
+               maxRead = 0;
+       }
+
+       if(cbRead > maxRead)
+       {
+               cbRead = maxRead;
+       }
+       
+       if(maxRead > 0)
+       {
+               nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
+               if(nread > 0)
+               {
+                       pFile->offset += nread;
+
+                       if(pcbRead)
+                       {
+                               *pcbRead = nread;
+                       }
+               }
+       }
+       else
+       {
+               if(pcbRead) 
+               {
+                       *pcbRead = maxRead;
+               }
+       }
+
+
+       return nread < 0? FALSE : TRUE; 
+
+}
+
+BOOL YFSD_ReadFile( 
+       PFILE pFile, 
+       PVOID pBuffer, 
+       DWORD cbRead, 
+       PDWORD pcbRead, 
+       OVERLAPPED *pOverlapped ) //ignore
+{
+       BOOL result;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+       result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+}
+
+BOOL YFSD_ReadFileWithSeek( 
+       PFILE pFile, 
+       PVOID pBuffer, 
+       DWORD cbRead, 
+       PDWORD pcbRead, 
+       OVERLAPPED *pOverlapped, 
+       DWORD dwLowOffset, 
+       DWORD dwHighOffset )
+{
+       BOOL result;
+       DWORD rememberedOffset;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
+
+       // To determine if paging is supported, the kernel calls this with all parameters except pFile
+       // being zero.
+       if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
+       {
+               return TRUE; // paging suppported
+               //return FALSE; // paging not supported
+       }
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+       rememberedOffset = pFile->offset;
+
+       pFile->offset = dwLowOffset;
+       // ignore high offset for now
+
+       result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
+
+       //pFile->offset = rememberedOffset;
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+
+
+}
+
+
+BOOL yfsd_DoWriteFile( 
+       PFILE pFile, 
+       PCVOID pBuffer, 
+       DWORD cbWrite, 
+       PDWORD pcbWritten)
+{
+       int nwritten = 0;
+       yaffs_Object *obj = NULL;
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
+       
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if(!pFile->writePermitted)
+       {
+                       *pcbWritten = 0;
+                       SetLastError(ERROR_ACCESS_DENIED);
+                       return FALSE;
+       }
+
+       obj = pFile->obj;
+
+       *pcbWritten = 0;
+
+
+               nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
+               if(nwritten >= 0)
+               {
+                       pFile->offset += nwritten;
+                       *pcbWritten = nwritten;
+               }
+               if(nwritten != cbWrite)
+               {
+                       SetLastError(ERROR_DISK_FULL);
+               }
+
+
+       return nwritten != cbWrite? FALSE : TRUE; 
+}
+
+
+BOOL YFSD_WriteFile( 
+       PFILE pFile, 
+       PCVOID pBuffer, 
+       DWORD cbWrite, 
+       PDWORD pcbWritten, 
+       OVERLAPPED *pOverlapped )
+{
+       BOOL result;
+
+       yfsd_LockYAFFS();
+       RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
+
+       result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+}
+
+BOOL YFSD_WriteFileWithSeek( 
+       PFILE pFile, 
+       PCVOID pBuffer, 
+       DWORD cbWrite, 
+       PDWORD pcbWritten, 
+       OVERLAPPED *pOverlapped,
+       DWORD dwLowOffset, 
+       DWORD dwHighOffset )
+{
+       BOOL result;
+       DWORD rememberedOffset;
+       RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
+
+       
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+       rememberedOffset = pFile->offset;
+
+       pFile->offset = dwLowOffset;
+       // ignore high offset for now
+
+       result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
+
+       //pFile->offset = rememberedOffset;
+
+       yfsd_UnlockYAFFS();
+
+       return result;
+}
+
+DWORD YFSD_SetFilePointer( 
+       PFILE pFile, 
+       LONG lDistanceToMove, 
+       PLONG pDistanceToMoveHigh, 
+       DWORD dwMoveMethod )
+{
+       // ignore high offset for now
+
+       DWORD offset = 0xFFFFFFFF;
+       DWORD oldPos;
+       int fileSize;
+       int seekNegative = 0;
+
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return offset;
+       }
+
+       yfsd_LockYAFFS();
+
+
+       oldPos = pFile->offset;
+
+       if(dwMoveMethod == FILE_BEGIN)
+       {
+               if(lDistanceToMove >= 0)
+               {       
+                       offset = pFile->offset = lDistanceToMove;
+               }
+               else
+               {
+                       seekNegative = 1;
+               }
+       }
+       else if(dwMoveMethod == FILE_END)
+       {
+               fileSize = yaffs_GetObjectFileLength(pFile->obj);
+               if(fileSize >= 0 &&
+                  (fileSize + lDistanceToMove) >= 0)
+               {
+                       offset = pFile->offset = fileSize + lDistanceToMove;
+               }
+               else
+               {
+                       seekNegative = 1;
+               }
+       }
+       else if(dwMoveMethod == FILE_CURRENT)
+       {
+               if(pFile->offset + lDistanceToMove >= 0)
+               {
+                       offset = pFile->offset = pFile->offset + lDistanceToMove;               
+               }
+               else
+               {
+                               seekNegative = 1;
+               }
+       }
+
+       if(seekNegative)
+       {
+                       SetLastError(ERROR_NEGATIVE_SEEK);
+                       
+       }
+
+       yfsd_UnlockYAFFS();
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
+                                 dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
+
+       return offset;
+
+}
+
+DWORD YFSD_GetFileSize( 
+       PFILE pFile, 
+       PDWORD pFileSizeHigh )
+{
+       int fileSize;
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
+       
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return -1;
+       }
+
+       yfsd_LockYAFFS();
+
+       fileSize = yaffs_GetObjectFileLength(pFile->obj);
+
+       yfsd_UnlockYAFFS();
+       if(pFileSizeHigh)
+                *pFileSizeHigh = 0;
+
+       return fileSize;
+
+}
+
+
+BOOL YFSD_GetFileInformationByHandle( 
+       PFILE pFile,
+       PBY_HANDLE_FILE_INFORMATION pFileInfo )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
+
+       if(!pFile || !pFile->obj || !pFileInfo)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       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;
+       pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);
+
+       yfsd_UnlockYAFFS();
+
+       return TRUE;
+}
+
+BOOL YFSD_FlushFileBuffers(PFILE pFile )
+{
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];
+
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       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;
+
+       yfsd_UnlockYAFFS();
+       
+       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;
+}
+
+BOOL YFSD_GetFileTime( 
+       PFILE pFile, 
+       FILETIME *pCreation, 
+       FILETIME *pLastAccess, 
+       FILETIME *pLastWrite )
+{
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+
+       if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
+       if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
+       if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
+
+       yfsd_UnlockYAFFS();
+
+       return TRUE;
+}
+
+BOOL YFSD_SetFileTime( 
+       PFILE pFile, 
+       CONST FILETIME *pCreation, 
+       CONST FILETIME *pLastAccess, 
+       CONST FILETIME *pLastWrite )
+{
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
+       int result = FALSE;
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];
+
+       
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+       
+       
+       yfsd_LockYAFFS();
+
+       if(pCreation) 
+       {
+                yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
+               pFile->obj->dirty = 1;
+       }
+       if(pLastAccess)
+       {
+               yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
+               pFile->obj->dirty = 1;
+       }
+       if(pLastWrite)
+       {
+               yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
+               pFile->obj->dirty = 1;
+       }
+       if(pCreation || pLastAccess || pLastWrite)
+       {
+               result = yaffs_FlushFile(pFile->obj,0);
+       }
+
+       if(result)
+       {
+               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)
+       {
+                       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;
+}
+   
+BOOL YFSD_SetEndOfFile( 
+PFILE pFile )
+{
+
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];
+       static unsigned char zeros[512];
+
+       int result;
+       BOOL retVal = FALSE;
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
+
+       if(!pFile || !pFile->obj)
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       yfsd_LockYAFFS();
+       result = yaffs_ResizeFile(pFile->obj,pFile->offset);
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
+
+       // Resize only works if we're shortening the file.
+       // If the result is shorter than the offset, then we need to write zeros....
+       // 
+       if(result != pFile->offset)
+       {
+               if(result < pFile->offset)
+               {
+
+                       int nBytes = pFile->offset - result;
+                       int thisWriteSize;
+                       int written;
+                       BOOL ok = TRUE;
+
+                       memset(zeros,0,512);
+
+                       pFile->offset = result;
+                       RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
+                       while(nBytes > 0 && ok)
+                       {
+                               thisWriteSize = (nBytes > 512) ? 512  : nBytes;
+
+                               ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);      
+                               if(written != thisWriteSize)
+                               {
+                                       ok = FALSE;
+                               }
+
+                               nBytes -= thisWriteSize;
+                       }
+
+                       retVal = ok;
+               }
+               else
+               {
+
+                       SetLastError(ERROR_ACCESS_DENIED);
+                       retVal = FALSE;
+               }
+       }
+       else
+       {
+               retVal = TRUE;
+       }
+       if(retVal)
+       {
+               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)));
+
+
+       
+       return retVal;
+}
+
+BOOL YFSD_DeviceIoControl( 
+       PFILE pFile, 
+       DWORD dwIoControlCode, 
+       PVOID pInBuf, 
+       DWORD nInBufSize, 
+       PVOID pOutBuf, 
+       DWORD nOutBufSize, 
+       PDWORD pBytesReturned, 
+       OVERLAPPED *pOverlapped )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
+
+       return FALSE;
+}
+
+BOOL YFSD_CloseFile( PFILE pFile )
+{
+       WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+       int nameExists = 0;
+       yfsd_Volume *vol = NULL;
+       DWORD attribs = 0;
+       DWORD objSize = 0;
+       DWORD mtime[2];
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
+
+       yfsd_LockYAFFS();
+
+       if(!pFile)
+       {
+               RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
+       }
+       else
+       {
+               if(pFile->obj)
+               {
+                       pFile->obj->inUse--;
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
+                       yaffs_FlushFile(pFile->obj,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];
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
+                       if(pFile->fullName)
+                       {
+                               wcscpy(fpn,pFile->fullName);
+                               nameExists = 1;
+                       }
+                       vol = pFile->myVolume;
+                       yfsd_PutWinFile(pFile);
+               }
+               else
+               {
+                       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
+               }
+
+       }
+       yfsd_UnlockYAFFS();
+
+
+       if(nameExists && vol && vol->shellFunction)
+       {
+                       FILECHANGEINFO fc;
+               
+                       fc.cbSize = sizeof(FILECHANGEINFO);
+                       fc.wEventId = SHCNE_UPDATEITEM;
+                       fc.uFlags = SHCNF_PATH;
+                       fc.dwItem1 = (DWORD)fpn;
+                       fc.dwItem2 = 0;
+                       fc.dwAttributes = attribs;
+                       yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+                       fc.nFileSize = objSize;
+
+                       vol->shellFunction(&fc);
+                       RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+                       //yfsd_ShellDirectoryChanged(vol,fpn);
+       }
+
+       
+
+       RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
+
+       return TRUE;
+
+}
+
+
+BOOL YFSD_CloseVolume(PVOLUME pVolume )
+{
+       RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
+       yfsd_FlushAllFiles();
+       return TRUE;
+}
+
index de7ee00f00b2d869c9f80a00187ca4acdb73c150..6096bbed045adb1aecf4ac8b7115132da535de46 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 
-const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.23 2003-01-17 04:19:08 charles Exp $";
+const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.24 2003-01-31 03:30:33 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 
@@ -1157,6 +1157,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
                dev->endBlock = nBlocks - 1;
                dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
                dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+               dev->nReservedBlocks = 5;
 
                dev->writeChunkToNAND = nandemul_WriteChunkToNAND;
                dev->readChunkFromNAND = nandemul_ReadChunkFromNAND;
@@ -1243,6 +1244,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
                dev->endBlock = nBlocks - 1;
                dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
                dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+               dev->nReservedBlocks = 5;
                
 
                // ... and the functions.
index 8198e419f0da720bd2fac3fd76534d2a1ed9d17b..cfe955f8ca306e7298b24a56f1534a42171557a3 100644 (file)
@@ -14,7 +14,7 @@
  */
  //yaffs_guts.c
 
-const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.19 2003-01-31 00:57:34 charles Exp $";
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.20 2003-01-31 03:30:33 charles Exp $";
 
 #include "yportenv.h"
 
@@ -2142,7 +2142,7 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
                dev->allocationPage = 0;
        }
        
-       if(!useReserve &&  dev->nErasedBlocks <= YAFFS_RESERVED_BLOCKS)
+       if(!useReserve &&  dev->nErasedBlocks <= dev->nReservedBlocks)
        {
                // Not enough space to allocate unless we're allowed to use the reserve.
                return -1;
@@ -2184,7 +2184,7 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
 
 static int yaffs_CheckSpaceForChunkCache(yaffs_Device *dev)
 {
-       return (dev->nErasedBlocks >= YAFFS_RESERVED_BLOCKS);
+       return (dev->nErasedBlocks >= dev->nReservedBlocks);
 }
 
 
@@ -2365,7 +2365,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev)
        
        //yaffs_DoUnlinkedFileDeletion(dev);
        
-       if(dev->nErasedBlocks <= (YAFFS_RESERVED_BLOCKS + YAFFS_GARBAGE_COLLECT_LOW_WATER))
+       if(dev->nErasedBlocks <= (dev->nReservedBlocks + YAFFS_GARBAGE_COLLECT_LOW_WATER))
        {
                aggressive = 1;
        }               
@@ -2405,7 +2405,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev)
        
        //yaffs_DoUnlinkedFileDeletion(dev);
        
-       if(dev->nErasedBlocks <= (YAFFS_RESERVED_BLOCKS + 1))
+       if(dev->nErasedBlocks <= (dev->nReservedBlocks + 1))
        {
                aggressive = 1;
        }               
@@ -4602,6 +4602,20 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        int extraBits;
        int nBlocks;
 
+       if(     dev->nBytesPerChunk != YAFFS_BYTES_PER_CHUNK ||
+       
+               dev->nChunksPerBlock < 2 ||
+               dev->nReservedBlocks < 2 ||
+               dev->startBlock <= 0 ||
+               dev->endBlock <= 0 ||
+               dev->endBlock <= (dev->startBlock + dev->nReservedBlocks)
+         )
+       {
+               //these parameters must be set before stating yaffs
+               // Other parameters startBlock,
+               return YAFFS_FAIL;
+       }
+
 
        
        if(!yaffs_CheckStructures())
@@ -4658,9 +4672,6 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        }
        dev->chunkGroupSize = 1 << dev->chunkGroupBits;
        
-       // Stuff to be taken out later
-       dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
-       dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
        
        
        // More device initialisation
index 46e8f982fe704c63c388a4e344f36cf367711237..769dcc50adc2a7706012569b9d54c96bc8dbc64e 100644 (file)
@@ -14,7 +14,7 @@
  *
  * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  *
- * $Id: yaffs_guts.h,v 1.15 2003-01-17 04:19:08 charles Exp $
+ * $Id: yaffs_guts.h,v 1.16 2003-01-31 03:30:33 charles Exp $
  */
 
 #ifndef __YAFFS_GUTS_H__
@@ -62,8 +62,6 @@
 #define YAFFS_NOBJECT_BUCKETS          256
 
 
-#define YAFFS_RESERVED_BLOCKS          8
-
 #define YAFFS_OBJECT_SPACE                     0x40000
 #define YAFFS_MAX_NAME_LENGTH          255
 #define YAFFS_SHORT_NAME_LENGTH                15
@@ -399,9 +397,11 @@ struct yaffs_DeviceStruct
 {
        // Entry parameters set up way early. Yaffs sets up the rest.
        int   nBytesPerChunk;    // Should be a power of 2 >= 512
-       int       nChunksPerBlock;
-       int   startBlock;       // Start block we're allowed to use
-       int   endBlock;         // End block we're allowed to use
+       int       nChunksPerBlock;       // does not need to be a power of 2
+       int   startBlock;                // Start block we're allowed to use
+       int   endBlock;                  // End block we're allowed to use
+       int   nReservedBlocks;   // We want this tuneable so that we can reduce
+                                                        // reserved blocks on NOR and RAM.
        
        int   useNANDECC;               // Flag to decide whether or not to use NANDECC
        int   nShortOpCaches;   // If <= 0, then short op caching is disabled, else
index 9b3e637e29547c155a5c8bc29a9be0981e35f56c..f95c6eebd06f5cd5d75a85603b9e12d3715a99ec 100644 (file)
@@ -15,7 +15,7 @@
  *
  * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  *
- * $Id: yportenv.h,v 1.9 2003-01-17 04:19:08 charles Exp $
+ * $Id: yportenv.h,v 1.10 2003-01-31 03:30:33 charles Exp $
  *
  */
  
@@ -44,7 +44,7 @@
 #define YAFFS_LOSTNFOUND_NAME          "Lost Clusters"
 #define YAFFS_LOSTNFOUND_PREFIX                "OBJ"
 
-#define YPRINTF(x)
+#define YPRINTF(x)     RETAILMSG(1,x)
 
 // Always pass the sum compare to overcome the case insensitivity issue
 #define yaffs_SumCompare(x,y) ((x) == (y))
@@ -104,7 +104,7 @@ extern unsigned yfsd_U32FileTimeNow(void);
 
 #elif defined CONFIG_YAFFS_DIRECT
 
-// Directct interface
+// Direct interface
 
 #include "stdlib.h"
 #include "stdio.h"