*** empty log message ***
[yaffs/.git] / wince / yaffsfsd.c
1 /*\r
2  * YAFFS: Yet another FFS. A NAND-flash specific file system.\r
3  * ynandif.c: NAND interface functions for the WinCE port of YAFFS.\r
4  *\r
5  * Copyright (C) 2002 Trimble Navigation Ltd.\r
6  *\r
7  * Created by Charles Manning <charles.manning@trimble.co.nz>\r
8  *\r
9  * This program is free software; you can redistribute it and/or modify\r
10  * it under the terms of the GNU General Public License version 2 as\r
11  * published by the Free Software Foundation.\r
12  *\r
13  * This program is distributed in the hope that it will be useful, \r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of \r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \r
16  * General Public License for more details. You should have received a \r
17  * copy of the GNU General Public License along with this program; \r
18  * if not, write to the Free Software Foundation, Inc., \r
19  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \r
20  *\r
21  * Acknowledgements:\r
22  *  Various clean-ups and WinCE4 support by Steve Fogle\r
23  * $Id: yaffsfsd.c,v 1.2 2003-01-14 23:15:41 charles Exp $\r
24  */
25 #include <windows.h>
26 #include <extfile.h>
27 #include <yaffs_guts.h>
28 #include <ynandif.h>\r
29 //slf021104b begin\r
30 #include <diskio.h>\r
31 //slf021104b end
32
33 #define MAX_WIN_FILE    200
34 #define YFSD_NAME_LENGTH 128
35 #define YFSD_FULL_PATH_NAME_SIZE 500
36
37 \r
38 #define YFSD_DISK_NAME L"Disk"
39 #define YFSD_BOOT_NAME L"Boot"\r
40
41 #define PARTITION_START_NUMBER (1280)           
42
43 //#define MSGSTATE 1\r
44 #define MSGSTATE 0
45 //#define DISABLE_BOOT_PARTITION\r
46 //slf021105a begin\r
47 // Define DO_PARTITION_TABLE to cause the partition table \r
48 // information to be retrieved from the block driver.\r
49 //#define DO_PARTITION_TABLE\r
50 // How many partitions the disk might have.  2 gives \r
51 // space for the "Disk" and "Boot" partitions.\r
52 #define MAXPARTITIONS (2)\r
53 //slf021105a end
54
55 //unsigned yaffs_traceMask=0xffffffff;
56 unsigned yaffs_traceMask=0;\r
57
58
59 typedef struct
60 {
61         yaffs_Device dev;
62         DWORD   hdsk;
63         DWORD    mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
64         BOOL    isMounted;
65         BOOL    configured;
66 //      DWORD   guard0[100];
67 //      DWORD   guard1[100];
68         SHELLFILECHANGEFUNC_t shellFunction;
69         PWSTR volName;
70 } yfsd_Volume;
71
72 typedef struct 
73 {
74         yaffs_Object *obj;
75         DWORD offset;
76         BOOL isopen;
77         BOOL dirty;
78         WCHAR *fullName;
79         yfsd_Volume *myVolume;
80         BOOL writePermitted;\r
81         BOOL readPermitted;\r
82         BOOL shareRead;\r
83         BOOL shareWrite;\r
84
85 }       yfsd_WinFile;
86
87 struct yfsd_FoundObjectStruct
88 {
89   yaffs_Object *obj;
90   struct yfsd_FoundObjectStruct *next;
91 };
92
93 typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
94
95 typedef struct 
96 {
97         yaffs_Object *dir;
98         char pattern[YFSD_NAME_LENGTH+1];
99         yaffs_FoundObject *foundObjects;
100 }       yfsd_WinFind;
101
102
103
104 #define PSEARCH yfsd_WinFind*
105
106 #define PVOLUME yfsd_Volume*
107 #define PFILE   yfsd_WinFile*
108
109 #define FSD_API YFSD
110
111 #include <fsdmgr.h>
112
113 //slf021105a begin\r
114 //static yfsd_Volume disk_volume;
115 //static yfsd_Volume boot_volume;\r
116 static yfsd_Volume * disk_volumes[MAXPARTITIONS];\r
117 //slf021105a end;
118
119 static CRITICAL_SECTION yaffsLock;
120 static CRITICAL_SECTION winFileLock;
121
122 static int yaffsLockInited = 0;
123
124 static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
125
126 #if 0
127 static yfsd_SetGuards(void)
128 {
129         int i;
130         for(i = 0; i < 100; i++)
131         {
132                 yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
133         }
134 }
135
136 static void yfsd_CheckGuards(void)
137 {
138         int i;
139         int found;
140         for(i = found = 0; i < 100 && !found; i++)
141         {
142                         if(yfsd_volume.guard0[i] != i)
143                         {
144                                         RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
145                                         found = 1;
146                         }
147                         if(yfsd_volume.guard1[i] != i)
148                         {
149                                         RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
150                                         found = 1;
151                         }
152         }
153 }
154 #endif
155
156 void yfsd_LockWinFiles(void)
157 {
158         //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
159         EnterCriticalSection(&winFileLock);
160 }
161 void yfsd_UnlockWinFiles(void)
162 {
163         //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
164         LeaveCriticalSection(&winFileLock);
165 }
166
167 int lockwaits;
168
169 void yfsd_LockYAFFS(void)
170 {
171         //yfsd_CheckGuards();
172         //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
173         lockwaits++;
174         EnterCriticalSection(&yaffsLock);
175         //RETAILMSG (MSGSTATE, (L" locked\r\n"));
176 }
177 void yfsd_UnlockYAFFS(void)
178 {
179         //yfsd_CheckGuards();
180         //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
181         LeaveCriticalSection(&yaffsLock);
182         lockwaits--;
183         //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
184 }
185
186
187 void yfsd_InitialiseWinFiles(void)
188 {
189         int i;
190         
191         RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
192
193         InitializeCriticalSection(&winFileLock);
194
195         yfsd_LockWinFiles();
196         for(i = 0; i < MAX_WIN_FILE; i++)
197         {
198                         yfsd_winFile[i].isopen = 0;
199         }
200         yfsd_UnlockWinFiles();
201 }
202
203 yfsd_WinFile * yfsd_GetWinFile(void)
204 {
205         int i;
206         RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
207
208         yfsd_LockWinFiles();
209
210         for(i = 0; i < MAX_WIN_FILE; i++)
211         {
212                 if(!yfsd_winFile[i].isopen)
213                 {
214                         yfsd_winFile[i].isopen = 1;
215                         yfsd_winFile[i].writePermitted = 0;\r
216                         yfsd_winFile[i].readPermitted = 0;\r
217                         yfsd_winFile[i].shareRead = 0;\r
218                         yfsd_winFile[i].shareWrite = 0;\r
219                         yfsd_winFile[i].dirty = 0;
220                         yfsd_winFile[i].fullName = NULL;
221                         yfsd_winFile[i].obj = NULL;
222
223                         yfsd_UnlockWinFiles();
224                         return &yfsd_winFile[i];
225                 }
226         }
227
228         yfsd_UnlockWinFiles();
229
230         RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
231
232         return NULL;
233 }
234
235 void yfsd_PutWinFile(yfsd_WinFile *f)
236 {
237         RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
238         yfsd_LockWinFiles();
239         f->isopen = 0;
240         f->obj = NULL;
241         if(f->fullName)
242         {
243                 free(f->fullName);
244                 f->fullName = NULL;
245         }
246
247         yfsd_UnlockWinFiles();
248 }
249
250
251
252 void yfsd_FlushAllFiles(void)
253 {
254         int i;
255         RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
256
257         yfsd_LockYAFFS();
258         yfsd_LockWinFiles();
259         for(i = 0; i < MAX_WIN_FILE; i++)
260         {
261                 if(yfsd_winFile[i].isopen &&
262                    yfsd_winFile[i].obj)
263                 {
264                         yaffs_FlushFile(yfsd_winFile[i].obj,1);
265                 }
266         }
267         yfsd_UnlockWinFiles();
268         yfsd_UnlockYAFFS();
269 }\r
270 \r
271 //slf021104d begin\r
272 //////////////////////////////////////////////////////////////////////\r
273 // Search through winFiles to see if any are open.  \r
274 \r
275 BOOL yfsd_FilesOpen(void)\r
276 {\r
277         int i;\r
278         BOOL rval;\r
279         RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));\r
280 \r
281         yfsd_LockWinFiles();\r
282         for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)\r
283         {\r
284                 if(yfsd_winFile[i].isopen)\r
285                 {\r
286                         rval = TRUE;\r
287                         break;\r
288                 }\r
289         }\r
290         yfsd_UnlockWinFiles();\r
291         return rval;\r
292 }\r
293 //slf021104d end
294
295 PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
296 {
297
298         // todo check for bounds\r
299         //slf021104b begin\r
300         //volName already has the initial backslash if it needs it.
301         //wcscpy(fpn,L"\\");\r
302         //wcscat(fpn,vol->volName);
303         wcscpy(fpn,vol->volName);\r
304         //slf021104b end\r
305         if(pathName[0] != '\\')
306         {
307                 wcscat(fpn,L"\\");
308         }
309         wcscat(fpn,pathName);
310
311         return fpn;
312
313 }
314
315
316 // FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
317
318 void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
319 {
320         
321         wft->dwLowDateTime = target[0];
322         wft->dwHighDateTime = target[1];
323
324 }
325
326 void yfsd_NullWinFileTime(FILETIME *wft)
327 {
328         wft->dwLowDateTime = 0;
329         wft->dwHighDateTime = 0;
330 }
331
332 void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
333 {
334         target[0] = wft->dwLowDateTime;
335         target[1] = wft->dwHighDateTime;
336 }
337
338 void  yfsd_WinFileTimeNow(__u32 target[2])
339 {
340         SYSTEMTIME st;
341         FILETIME ft;
342
343         GetSystemTime(&st);
344         SystemTimeToFileTime(&st,&ft);
345         yfsd_WinFileTimeToU32s(&ft,target);
346 }
347
348 // Cut down the name to the parent directory, then inform the shell of
349 // a change to the directory.
350 void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
351 {
352         WCHAR str[500];
353         int i;
354         wcscpy(str,fullPathName);
355
356         i = wcslen(str) - 1;
357         
358         if(i > 0)
359         {
360                 str[i] = 0;
361                 i--;
362         }
363
364         // Curveball if the name is a directory (ie. we're doing an update of
365         // a directory because we added a directory item). , then it might end in a \
366         // which we must toss first
367         if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
368         {
369                 str[i] = 0;
370                 i--;
371         }
372
373         // Ok, now strip back...
374
375         while(i >= 0 && str[i] != '\\' && str[i] != '/')
376         {
377                 str[i] = 0;
378                 i--;
379         }
380
381         if(pVolume->shellFunction)
382         {
383                         FILECHANGEINFO fc;
384                         
385                         fc.cbSize = sizeof(FILECHANGEINFO);
386                         fc.wEventId = SHCNE_UPDATEDIR;
387                         fc.uFlags = SHCNF_PATH;
388                         fc.dwItem1 = (DWORD)str;
389                         fc.dwItem2 = 0;
390                         fc.dwAttributes = 0;
391                         yfsd_NullWinFileTime(&fc.ftModified);
392                         fc.nFileSize = 0;
393
394                         pVolume->shellFunction(&fc);
395                         RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
396
397         }
398
399
400 }
401
402
403 // Minimal name test for now
404 BOOL yfsd_NameIsValid (const char *name)
405 {
406         int length = strlen(name);
407
408         return (length > 0 && length <= YFSD_NAME_LENGTH);
409
410 }
411
412 // File attributes:
413 // Wince understands the following attributes of any use to YAFFS:
414 //  
415 //   ARCHIVE
416 //   HIDDEN
417 //   READONLY
418 //   SYSTEM
419 //   TEMPORARY
420 //
421 //       Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
422 //
423 //   It also understands NORMAL. If no other flag is set, then set NORMAL.
424 //   If any of the above are set, then NORMAL must **not** be set.
425 //       Ignore this and the WinCE Explorer barfs the file.
426 //
427 //
428 // in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
429
430 // The following are valid ones we get presented with,
431 // but must filter out the stuff we don't unserstand
432 //#define FILE_ATTRIBUTE_READONLY             0x00000001  
433 //#define FILE_ATTRIBUTE_HIDDEN               0x00000002  
434 //#define FILE_ATTRIBUTE_SYSTEM               0x00000004  
435 //#define FILE_ATTRIBUTE_DIRECTORY            0x00000010  
436 //#define FILE_ATTRIBUTE_ARCHIVE              0x00000020  
437 //#define FILE_ATTRIBUTE_INROM                            0x00000040
438 //#define FILE_ATTRIBUTE_ENCRYPTED            0x00000040  
439 //#define FILE_ATTRIBUTE_NORMAL               0x00000080  
440 //#define FILE_ATTRIBUTE_TEMPORARY            0x00000100  
441 //#define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200  
442 //#define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400  
443 //#define FILE_ATTRIBUTE_COMPRESSED           0x00000800  
444 //#define FILE_ATTRIBUTE_OFFLINE              0x00001000  
445 //#define FILE_ATTRIBUTE_ROMSTATICREF             0x00001000
446 //#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000  
447 //#define FILE_ATTRIBUTE_ROMMODULE                        0x00002000
448
449
450 BOOL yfsd_CheckValidAttributes(DWORD attribs)
451 {
452
453         RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
454
455 #if 0
456                 // If NORMAL, then nothing else
457                 if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
458                         return FALSE;
459                 if(attribs == FILE_ATTRIBUTE_NORMAL) 
460                         return TRUE;
461 #endif
462                 // Check that the bits are in the valid set
463                 if(attribs & ~(0x3FE7))
464                         return FALSE;
465
466                 return TRUE;
467
468 }
469 DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
470 {
471
472                 DWORD result;
473                 
474                 result = obj->st_mode & 
475                                         (FILE_ATTRIBUTE_READONLY | 
476                                          FILE_ATTRIBUTE_ARCHIVE | 
477                                          FILE_ATTRIBUTE_HIDDEN |
478                                          FILE_ATTRIBUTE_SYSTEM);
479
480                 if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
481
482                 if(result & ~FILE_ATTRIBUTE_NORMAL)
483                 { 
484                         result &= ~FILE_ATTRIBUTE_NORMAL;
485                 }
486                 else 
487                 {
488                         result = FILE_ATTRIBUTE_NORMAL;
489                 }
490
491
492                 return result;
493 }
494
495
496
497 /*
498 *       Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
499 *       reached.  Characters are copied from input into output until the above stop
500 *       condition is reached - output is then given a '\0'.  output must be at least
501 *       as large as outSize
502 */
503 static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
504 {
505         int counter = 0;
506         char *t = output;
507         /* strip any starting \'s */
508         //RETAILMSG(1, (L"\r\nParsing.. "));
509         while (*input == '\\' || *input == '/') input++, counter++;
510
511         for (; counter < outSize - 1; counter++)
512         {
513                 if (*input == '\0' ||
514                         ((*input == '\\' || *input == '/') && input[1] == '\0'))   // special case: if the string ends in a '\', then toss the '\'
515                 {
516                         counter = -1;   // break & tell people we've run to the end
517                         break;
518                 }
519                 if (*input == '\\' || *input == '/')
520                         break;
521                 //RETAILMSG(1, (L"%c", *input));
522                 *output = (char) (*input);
523                 input++;
524                 output++;
525         }
526         *output++ = '\0';
527         *output  = '\0';
528 //      RETAILMSG(1, (L"\r\nOut %a\r\n", t));
529         
530         return counter;
531 }
532
533 /*
534 *       Since the notion of paths as WinCE sees them and as YAFFS sees them
535 *       is different, we needed a helper function to search from the root of
536 *       device along the string in path.  The processed pointer is set to where
537 *       abouts in the string the function was able to search up to.
538 */
539 yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
540 {
541         // a buffer to keep the current chunk of path we're talking about it
542         char pathChunk[255];
543         int chunkSize;
544         int counter;
545         // the current object we are at
546         yaffs_Object *current;
547
548         RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
549         // start at the root of this device
550         current = yaffs_Root(device);
551         *processed = '\0';
552
553         do
554         {
555         //      parse chunks until we run out
556                 chunkSize = parseToNextSlash(path, pathChunk, 255);
557 //              RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
558                 if (chunkSize == -1)
559                         break;
560         //      move the path pointer along
561                 path += chunkSize;
562         //      try and find the next yaffs object by chunkname 
563                 current = yaffs_FindObjectByName(current, pathChunk);
564                 if (current == 0)
565                 {
566                         processed[0] = '\0';
567                         return 0;
568                 }
569         } while (1);
570
571         for (counter = 0; counter < length; counter++)
572         {
573                 // Get the rest of the string
574                 processed[counter] = pathChunk[counter];
575                 if (pathChunk[counter] == '\0')
576                         break;
577         }
578
579         RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
580
581         return current;
582 }
583
584
585 yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
586 {
587         yaffs_Object *obj = NULL;
588         yaffs_Object *parent = NULL;
589         char name[YFSD_NAME_LENGTH+1];
590
591         RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
592
593         parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
594
595         if(parent && yfsd_NameIsValid(name))
596         {
597                 obj = yaffs_FindObjectByName(parent,name);
598         }
599
600         RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
601
602         return obj;
603 }
604
605 BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
606 {
607         //slf021104b Begin\r
608         WCHAR szName[MAX_PATH];\r
609     DWORD dwAvail;\r
610         //slf021104b end\r
611         RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));\r
612         //slf021104b Begin filled in later.
613         //vol->volName = volName;\r
614         //slf021104b end
615
616
617         yfsd_LockYAFFS();
618         
619         //Mount/initialise YAFFs here
620         ynandif_InitialiseNAND(&vol->dev);
621         
622         vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;
623         vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;
624         vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;
625         vol->dev.initialiseNAND = ynandif_InitialiseNAND;
626         vol->dev.startBlock = startBlock;
627         if (endBlock != -1)
628                 vol->dev.endBlock = endBlock;\r
629         vol->dev.nShortOpCaches = 10; // a nice number of caches.
630
631         // nBlocks is set the total size of the disk, not the partition
632 //      vol->dev.nBlocks = endBlock - startBlock + 1;
633
634 //      qnand_EraseAllBlocks(&vol->dev);
635
636         yaffs_GutsInitialise(&vol->dev);
637         RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
638
639         RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",
640                             vol->dev.startBlock,vol->dev.endBlock,
641                                         vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));
642
643
644 #if 0
645         for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
646         {
647                         switch(vol->dev.blockInfo[i].blockState)
648                         {
649                                 case YAFFS_BLOCK_STATE_DEAD:
650                 
651                                         RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
652                                         deadBlox++;
653                                         break;
654                                 case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
655                                 case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
656                                 case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
657                                 case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
658                                 default:
659                                         RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
660                                         break;
661                         }
662         }
663
664         RETAILMSG(1, (L"Blocks dead  %d empty %d full %d allocating %d dirty %d\r\n",
665                             deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
666
667 #endif
668
669         yfsd_UnlockYAFFS();
670
671         vol->isMounted = 1;
672         \r
673         //slf021104b begin
674         //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);\r
675         // If the caller passed a volume name use it.\r
676         if (volName[0])\r
677         wcscpy( szName, volName);\r
678 #if WINCEOSVER >= 400\r
679         // The user passed an empty volume name.  On CE 4.xx try to get\r
680         // if from the block driver (which got it from the registry).\r
681         else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL)) \r
682 #else\r
683         else\r
684 #endif\r
685         { \r
686                 // Didn't get a volume name so use "Disk" by default.\r
687         wcscpy( szName, YFSD_DISK_NAME);\r
688     }    \r
689         vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);\r
690         //slf021104b end
691
692         if(vol->mgrVolume)
693         {\r
694                 //slf021104b Begin\r
695                 // Get some space for the volume name.
696         vol->volName = malloc( MAX_PATH * sizeof(WCHAR));\r
697         if (vol->volName) \r
698                 {\r
699 #if WINCEOSVER >= 400\r
700                         // Get the name we were really mounted under.\r
701             FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);\r
702 \r
703                         // If we got mounted as root then throw away the backslash\r
704                         // so we won't get a double backslash when volName is\r
705                         // prepended to the path in the full path name calculation\r
706                         // that is used for shell callbacks.\r
707                         if (0 == wcscmp(vol->volName,L"\\"))\r
708                                 vol->volName[0] = 0;\r
709 #else\r
710                         // Use the name we asked to be mounted under for\r
711                         // our root.  \r
712                         wcscpy(vol->volName,L"\\");\r
713                         wcscat(vol->volName, szName);\r
714 #endif\r
715                 }\r
716                 //slf021104b end\r
717                 return TRUE;
718         }
719         else
720         {
721                 vol->isMounted = 0;
722                 SetLastError(ERROR_OUTOFMEMORY);
723                 return FALSE;
724         }       
725 }
726
727
728 BOOL YFSD_MountDisk(HDSK hdsk)
729 {
730 //slf021105a begin\r
731 #ifdef DO_PARTITION_TABLE\r
732         ynandif_partition PartTable[MAXPARTITIONS];\r
733         DWORD dwAvail;\r
734         int i;\r
735         BOOL rval = FALSE;\r
736 #endif\r
737 //slf021105a end\r
738         int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
739         //int i;
740         // Called to mount a disk.
741         // NB THis call might happen redundantly.
742         //
743         //
744         // If yaffs is not initialised, then call the 
745         // initialisation function
746         //
747         RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
748
749         if (!yaffsLockInited)
750         {
751                 InitializeCriticalSection(&yaffsLock);
752                 yfsd_InitialiseWinFiles();
753                 yaffsLockInited = 1;
754         }
755 \r
756         //slf021105a begin\r
757         memset(disk_volumes,0,sizeof(disk_volumes));\r
758 #ifdef DO_PARTITION_TABLE\r
759         memset(&PartTable,0,sizeof(PartTable));\r
760         // Call the block driver to get the partition table from it.\r
761     if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL)) \r
762         {\r
763                 // Scan throught the table it return.\r
764                 for (i=0; i<MAXPARTITIONS; i++)\r
765                 {\r
766                         // At the very lease check that the end is later than the beginning\r
767                         // and don't let it start at 0.  \r
768                         // Probably could do more thorough checking but I trust the block\r
769                         // driver.\r
770                         if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))\r
771                         {\r
772                                 // Found a partion.  Get a volume structure to hold it.\r
773                                 disk_volumes[i] = malloc(sizeof(yfsd_Volume));\r
774                                 if (disk_volumes[i])\r
775                                 {\r
776                                         memset(disk_volumes[i],0,sizeof(yfsd_Volume));\r
777                                         // Go init the volume.  Note that if the block driver wants the\r
778                                         // name to come from the registry it will have returned an\r
779                                         // empty name string.\r
780                                         YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);\r
781                                         if (disk_volumes[i]->isMounted)\r
782                                                 rval = TRUE; //Hey, we found at least on partition.\r
783                                 }\r
784                         }\r
785                 }\r
786         }\r
787 \r
788         return rval;\r
789 \r
790 #else
791 #ifdef DISABLE_BOOT_PARTITION
792         // Only want disk volume\r
793         disk_volumes[0] = malloc(sizeof(yfsd_Volume));\r
794         if (disk_volumes[0])\r
795         {\r
796                 memset(disk_volumes[0],0,sizeof(yfsd_Volume));\r
797                 YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);\r
798 \r
799                 if(disk_volumes[0].isMounted)\r
800                 {\r
801                         return TRUE;\r
802                 }\r
803         }\r
804         if (disk_volumes[0])\r
805         {\r
806                 free(disk_volumes[0];\r
807                 disk_volumes[0] = NULL;\r
808         }\r
809 #else\r
810         // Want both boot and disk\r
811         disk_volumes[0] = malloc(sizeof(yfsd_Volume));\r
812         disk_volumes[1] = malloc(sizeof(yfsd_Volume));\r
813         if (disk_volumes[0] && disk_volumes[1])\r
814         {\r
815                 memset(disk_volumes[0],0,sizeof(yfsd_Volume));\r
816                 memset(disk_volumes[1],0,sizeof(yfsd_Volume));\r
817                 YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);\r
818                 YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);\r
819 \r
820                 if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)\r
821                 {\r
822                         return TRUE;\r
823                 }\r
824         }\r
825 \r
826         // If we got this far something went wrong.  Make sure to \r
827         // free any memory we allocated.\r
828         if (disk_volumes[0])\r
829         {\r
830                 if (disk_volumes[0]->volName)\r
831                 {\r
832                         free(disk_volumes[0]->volName);\r
833                 }\r
834                 free(disk_volumes[0]);\r
835                 disk_volumes[0] = NULL;\r
836         }\r
837         if (disk_volumes[1])\r
838         {\r
839                 if (disk_volumes[1]->volName)\r
840                 {\r
841                         free(disk_volumes[1]->volName);\r
842                 }\r
843                 free(disk_volumes[1]);\r
844                 disk_volumes[1] = NULL;\r
845         }\r
846 #endif\r
847 \r
848         return FALSE;\r
849 \r
850         // Only want disk volume\r
851 //      YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
852 //
853 //      
854 //      if(disk_volume.isMounted)
855 //      {
856 //              return TRUE;
857 //      }
858 //#else
859 //      // Want both boot and disk
860 //      YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
861 //      YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
862 //
863 //      
864 //      if(disk_volume.isMounted && boot_volume.isMounted)
865 //      {
866 //              return TRUE;
867 //      }
868 //#endif\r
869 //
870 //      return FALSE;
871 #endif\r
872 //slf021105a end\r
873
874 //      yfsd_SetGuards();
875
876         // todo - get name from registry
877
878 }
879
880
881 BOOL YFSD_UnmountDisk(HDSK hdsk)
882 {
883 //slf021105a begin\r
884         int i;\r
885 //slf021105a end\r
886         RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
887         
888         //slf021104d begin\r
889         // If there are any files open don't let them dismount\r
890         // it or the system will get very confused.  \r
891         if (yfsd_FilesOpen())\r
892                 return FALSE;\r
893 \r
894         //yfsd_FlushAllFiles();\r
895         //slf021104d end\r
896 \r
897         yfsd_LockYAFFS();\r
898 //slf021105a begin\r
899 //      yaffs_Deinitialise(&disk_volume.dev);\r
900 //      yaffs_Deinitialise(&boot_volume.dev);\r
901 //      yfsd_UnlockYAFFS();
902 //
903 //      FSDMGR_DeregisterVolume(disk_volume.mgrVolume);\r
904 //      FSDMGR_DeregisterVolume(boot_volume.mgrVolume);\r
905 \r
906         // Walk through the partions deinitializing, deregistering\r
907         // and freeing them.\r
908         for (i=0; i<MAXPARTITIONS; i++)\r
909         {\r
910                 if (disk_volumes[i])\r
911                 {\r
912                         yaffs_Deinitialise(&(disk_volumes[i]->dev));\r
913                         FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);\r
914                         if (disk_volumes[i]->volName)\r
915                         {\r
916                                 free(disk_volumes[i]->volName);\r
917                         }\r
918                         free(disk_volumes[i]);\r
919                         disk_volumes[i] = NULL;\r
920                 }\r
921         }\r
922         yfsd_UnlockYAFFS();\r
923 //slf021105a end
924         return TRUE;
925 }
926
927
928 BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
929 {
930         // security attributes are ignored (should be NULL)
931
932         yaffs_Object *newDir = NULL;
933         yaffs_Object *parent = NULL;
934         char name[YFSD_NAME_LENGTH+1];
935         ULONG objSize;
936         DWORD attribs;
937         unsigned modifiedTime[2];
938
939         RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
940
941         yfsd_LockYAFFS();
942
943         parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
944
945         //slf021101b begin 
946         if (parent)
947         {
948                 if(yfsd_NameIsValid(name))
949                 {
950                         newDir = yaffs_MknodDirectory(parent,name,0,0,0);
951                         if(newDir)
952                         {
953                                 objSize = yaffs_GetObjectFileLength(newDir);
954                                 attribs = yfsd_GetObjectWinAttributes(newDir);
955                                 modifiedTime[0] = newDir->win_mtime[0];
956                                 modifiedTime[1] = newDir->win_mtime[1];
957                         }
958                         else
959                         {
960                                 if(yaffs_FindObjectByName(parent,name))
961                                         SetLastError(ERROR_ALREADY_EXISTS);
962                                 else
963                                         SetLastError(ERROR_DISK_FULL);
964                         }
965                 }
966                 else
967                         SetLastError(ERROR_INVALID_NAME);
968         }
969         else
970         {
971                 SetLastError(ERROR_PATH_NOT_FOUND);
972         }
973     //slf021101b end
974
975         yfsd_UnlockYAFFS();
976
977         // Call shell function to tell of new directory
978         if(newDir && pVolume->shellFunction)
979         {
980                         FILECHANGEINFO fc;
981                         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
982
983                         fc.cbSize = sizeof(FILECHANGEINFO);
984                         fc.wEventId = SHCNE_MKDIR;
985                         fc.uFlags = SHCNF_PATH;
986                         fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
987                         fc.dwItem2 = 0;
988                         fc.dwAttributes = attribs; 
989                         yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
990                         fc.nFileSize = objSize;
991
992                         pVolume->shellFunction(&fc);
993                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
994
995                         //yfsd_ShellDirectoryChanged(pVolume,fpn);
996
997         }
998
999 //slf021101b begin 
1000 //      if(parent && !newDir)
1001 //      {
1002 //                      SetLastError(ERROR_DISK_FULL);
1003 //      }
1004 //slf021101b end
1005
1006         return newDir ? TRUE : FALSE;
1007 }
1008
1009
1010 BOOL yfsd_RemoveObjectW(PVOLUME pVolume, PCWSTR pathName)
1011 {
1012         // Fails if directory is not empty
1013         int result = FALSE;
1014         yaffs_Object *parent = NULL;
1015         yaffs_Object *obj;
1016         char name[YFSD_NAME_LENGTH+1];
1017
1018         RETAILMSG (MSGSTATE, (L"YAFFS::RemoveObjectW (%s)\r\n", pathName));
1019
1020         yfsd_LockYAFFS();
1021
1022         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
1023         if(!obj)
1024         {
1025                 SetLastError(ERROR_FILE_NOT_FOUND);
1026                 result = FALSE;
1027         }
1028         else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
1029         {
1030                 SetLastError(ERROR_ACCESS_DENIED);
1031                 result = FALSE;
1032         }
1033         else if(obj->inUse)
1034         {
1035                 SetLastError(ERROR_ACCESS_DENIED);
1036                 result = FALSE;
1037         }
1038         else
1039         {
1040
1041                 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
1042
1043                 if(parent && yfsd_NameIsValid(name))
1044                 {
1045                         result = yaffs_Unlink(parent,name);
1046                         if(!result)
1047                                 SetLastError(ERROR_ACCESS_DENIED);
1048                 }
1049         }
1050
1051         yfsd_UnlockYAFFS();
1052
1053         return result ? TRUE : FALSE;
1054 }
1055
1056
1057 BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
1058 {
1059         BOOL result;
1060         RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory\r\n"));
1061         
1062         result =  yfsd_RemoveObjectW(pVolume, pathName);
1063
1064         if(result && pVolume->shellFunction)
1065         {
1066                         FILECHANGEINFO fc;
1067                         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1068
1069                         fc.cbSize = sizeof(FILECHANGEINFO);
1070                         fc.wEventId = SHCNE_RMDIR;
1071                         fc.uFlags = SHCNF_PATH;
1072                         fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
1073                         fc.dwItem2 = 0;
1074                         fc.dwAttributes = 0;
1075                         yfsd_NullWinFileTime(&fc.ftModified);
1076                         fc.nFileSize = 0;
1077
1078                         pVolume->shellFunction(&fc);
1079                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1080
1081                         yfsd_ShellDirectoryChanged(pVolume,fpn);
1082         }
1083         
1084         return result;
1085
1086 }
1087
1088
1089 DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
1090 {
1091         yaffs_Object *obj = NULL;
1092
1093         DWORD result = 0xFFFFFFFF;
1094
1095         RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
1096
1097         yfsd_LockYAFFS();
1098
1099         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1100
1101         if(obj)
1102         {
1103                 result = yfsd_GetObjectWinAttributes(obj);
1104         }
1105         else
1106         {
1107                 SetLastError(ERROR_FILE_NOT_FOUND);
1108         }
1109
1110         yfsd_UnlockYAFFS();
1111         
1112         RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
1113         return result;
1114
1115         
1116 }
1117
1118 BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
1119 {
1120         yaffs_Object *obj = NULL;
1121         DWORD mtime[2];
1122         DWORD attribs;
1123         DWORD objSize;
1124
1125         int result = 0;
1126
1127         RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
1128
1129         if(!yfsd_CheckValidAttributes(dwFileAttributes))
1130         {
1131                         SetLastError(ERROR_INVALID_PARAMETER);
1132                         return FALSE;
1133         }
1134
1135         yfsd_LockYAFFS();
1136
1137         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1138
1139         if(obj)
1140         {
1141                 obj->st_mode = dwFileAttributes;
1142                 obj->dirty = 1;
1143                 result = yaffs_FlushFile(obj,0);
1144                 attribs = yfsd_GetObjectWinAttributes(obj);
1145                 objSize = yaffs_GetObjectFileLength(obj);
1146                 mtime[0] = obj->win_mtime[0];
1147                 mtime[1] = obj->win_mtime[1];
1148         }
1149         else
1150         {
1151                 SetLastError(ERROR_FILE_NOT_FOUND);
1152         }
1153
1154         yfsd_UnlockYAFFS();
1155
1156         if(result && pVolume->shellFunction)
1157         {
1158                         FILECHANGEINFO fc;
1159                         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1160
1161                         fc.cbSize = sizeof(FILECHANGEINFO);
1162                         fc.wEventId = SHCNE_ATTRIBUTES;
1163                         fc.uFlags = SHCNF_PATH;
1164                         fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1165                         fc.dwItem2 = 0;
1166                         fc.dwAttributes =  attribs;
1167                         yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
1168                         fc.nFileSize = objSize;
1169
1170                         pVolume->shellFunction(&fc);
1171                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1172
1173                         //yfsd_ShellDirectoryChanged(pVolume,fpn);
1174         }
1175         
1176
1177         return result;
1178
1179 }
1180
1181 BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
1182 {
1183         BOOL result;
1184         RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
1185
1186         result =  yfsd_RemoveObjectW(pVolume, pwsFileName);
1187         if(result && pVolume->shellFunction)
1188         {
1189                         FILECHANGEINFO fc;
1190                         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1191
1192                         fc.cbSize = sizeof(FILECHANGEINFO);
1193                         fc.wEventId = SHCNE_DELETE;
1194                         fc.uFlags = SHCNF_PATH;
1195                         fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1196                         fc.dwItem2 = 0;
1197                         fc.dwAttributes = -1;
1198                         yfsd_NullWinFileTime(&fc.ftModified);
1199                         fc.nFileSize = 0;
1200
1201                         pVolume->shellFunction(&fc);
1202                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1203
1204                         yfsd_ShellDirectoryChanged(pVolume,fpn);
1205         }
1206
1207         return result;
1208 }
1209
1210 BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
1211 {
1212         yaffs_Object *newParent = NULL;
1213         yaffs_Object *oldParent = NULL;
1214         yaffs_Object *obj = NULL;
1215         char oldName[YFSD_NAME_LENGTH+1];
1216         char newName[YFSD_NAME_LENGTH+1];
1217         int result = 0;
1218         int objIsDir = 0;
1219         DWORD attribs;
1220         DWORD objSize;
1221         DWORD mtime[2];
1222
1223         RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
1224
1225         yfsd_LockYAFFS();
1226
1227         oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
1228         newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
1229
1230         if(oldParent  && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
1231         {
1232                 result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
1233                 if(!result)
1234                 {
1235                         SetLastError(ERROR_FILE_NOT_FOUND);
1236                 }
1237
1238                 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
1239                 if(obj)
1240                 {
1241                         objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
1242                         attribs = yfsd_GetObjectWinAttributes(obj);
1243                         objSize = yaffs_GetObjectFileLength(obj);
1244                         mtime[0] = obj->win_mtime[0];
1245                         mtime[1] = obj->win_mtime[1];
1246                 }
1247         }
1248         else
1249         {
1250                 SetLastError(ERROR_PATH_NOT_FOUND);
1251         }
1252
1253         yfsd_UnlockYAFFS();
1254
1255
1256         if(result && pVolume->shellFunction)
1257         {
1258                         FILECHANGEINFO fc;
1259                         WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
1260                         WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
1261
1262                         fc.cbSize = sizeof(FILECHANGEINFO);
1263                         fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
1264                         fc.uFlags = SHCNF_PATH;
1265                         fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
1266                         fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
1267                         fc.dwAttributes = attribs;
1268                         yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
1269                         fc.nFileSize = objSize;
1270
1271                         pVolume->shellFunction(&fc);
1272                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1273
1274                         yfsd_ShellDirectoryChanged(pVolume,fpn1);
1275                         yfsd_ShellDirectoryChanged(pVolume,fpn2);
1276         }
1277
1278
1279         return result ? TRUE : FALSE;
1280
1281 }
1282
1283 BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
1284 {
1285         //slf021104c begin\r
1286     BOOL fSuccess;\r
1287         //slf021104c end\r
1288 \r
1289         RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));\r
1290 \r
1291         //slf021104c begin
1292     if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))\r
1293         fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);\r
1294         return fSuccess;\r
1295         //return FALSE;
1296         //slf021104c end\r
1297 }
1298
1299 BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
1300 {
1301
1302         int nChunks;
1303
1304         RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
1305
1306         yfsd_LockYAFFS();
1307         nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
1308         yfsd_UnlockYAFFS();
1309
1310         if(nChunks >= 0)
1311         {
1312                 // Let's pretentd our clusters are the same size as eraseable blocks...
1313                 *pBytesPerSector = 512;
1314                 *pSectorsPerCluster  =32;
1315                 *pFreeClusters = nChunks/32;
1316                 *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
1317         }
1318
1319         return (nChunks >= 0)? TRUE : FALSE;
1320
1321
1322
1323 }
1324
1325 void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
1326 {
1327         // Flags can be one of:
1328         // FSNOTIFY_POWER_ON: no action required
1329         // FSNOTIFY_POWER_OFF: flush all files
1330         // FSNOTIFY_DEVICE_ON: no action required
1331
1332         RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
1333         if(dwFlags == FSNOTIFY_POWER_OFF)
1334         {
1335                 yfsd_FlushAllFiles();
1336         }
1337
1338 }
1339
1340
1341 BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
1342 {
1343         RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
1344         
1345         pVolume->shellFunction = pfn;
1346
1347         return TRUE;
1348 }
1349
1350
1351
1352
1353
1354 int iMatch(const char a, const char b)
1355 {
1356         if (a == '?' || b == '?')
1357                 return 1;
1358         return (toupper(a) == toupper(b));
1359 }
1360
1361 void pString(const char *inp)
1362 {
1363         while (*inp) RETAILMSG(1, (L"%c", *inp++));
1364 }
1365
1366 int regularMatch(const char *regexp, const char *str)
1367 {
1368 //      pString(regexp);
1369 //      RETAILMSG(1, (L" "));
1370 //      pString(str);
1371 //      RETAILMSG(1, (L"\r\n"));
1372
1373         if (*regexp == 0 && *str == 0)
1374         {
1375                 //RETAILMSG(1, (L"Match!\r\n"));
1376                 return 1;
1377         }
1378         if (*regexp == '*')                     
1379         {
1380                 regexp++;
1381                 if (*regexp == 0)   // end of the expression is a *, we must match
1382                 {
1383                         //RETAILMSG(1, (L"Match!\r\n"));
1384                         return 1;
1385                 }
1386                 while (!iMatch(*regexp, *str)) // throw away chars from str until we match
1387                 {
1388                         if (*str == 0)  // if we're not at the end
1389                         {
1390                                 // if we have .* left to match, but the str is finished then match it OK
1391                                 if (regexp[0] == '.' && regexp[1] == '*')
1392                                 {
1393                                         //RETAILMSG(1, (L"Match!\r\n"));
1394                                         return 1;
1395                                 }
1396                                 else
1397                                 {
1398                                 // the extension failed the match
1399                                         //RETAILMSG(1, (L"No Match!\r\n"));
1400                                         return 0;
1401                                 }
1402                         }
1403                         str++;
1404                 } 
1405                 // right now we should either eat more characters, or try to match
1406                 return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
1407         }
1408 //  compare chars until we hit another *, or we fail
1409         while (iMatch(*regexp, *str))
1410         {
1411                 if (*regexp == 0 && *str == 0)
1412                 {
1413                         //RETAILMSG(1, (L"Match!\r\n"));
1414                         return 1;
1415                 }
1416                 regexp++;
1417                 str++;
1418         }
1419
1420         if (*regexp == 0 && *str == 0)
1421         {
1422                 //RETAILMSG(1, (L"Match!\r\n"));
1423                 return 1;
1424         }
1425
1426         if (*regexp == '*')
1427                 return regularMatch(regexp, str);
1428
1429         //RETAILMSG(1, (L"No Match!\r\n"));
1430         return 0;
1431 }
1432
1433
1434 void yfsd_DeleteFinder(PSEARCH pSearch)
1435 {
1436   if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
1437   {
1438     yaffs_FoundObject *it;
1439     yaffs_FoundObject *temp;
1440
1441     it = pSearch->foundObjects;
1442
1443     while(it != NULL)
1444     {
1445       temp = it;
1446       it = it->next;
1447       
1448       free(temp);
1449     }
1450
1451     pSearch->foundObjects = NULL;
1452   }
1453
1454                 pSearch->dir->inUse--;
1455                 free(pSearch);
1456 }
1457
1458 BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
1459 {
1460   //Iterate through the current list of objs already found and return true if already exists.
1461   //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
1462   BOOL found = FALSE;
1463
1464   yaffs_FoundObject *it;
1465   it = pSearch->foundObjects;
1466
1467   
1468   while(it->next != NULL) //iterate through singly linked list.
1469   {
1470     if(it->obj == l)
1471     {
1472       found = TRUE;
1473       break;
1474     }
1475     it = it->next;
1476   }
1477
1478   if(!found)
1479   {
1480     //Add the item to the list.
1481     //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
1482     it->next = malloc(sizeof(yaffs_FoundObject));
1483     it->next->next = NULL;
1484     it->next->obj = 0;
1485
1486     it->obj = l;
1487   }
1488
1489   return found;
1490 }
1491
1492 #if 0
1493 // slower one
1494 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
1495 {
1496
1497         struct list_head *i;
1498         int pos;
1499         yaffs_Object *l;
1500         BOOL found = 0;
1501
1502         char name[YAFFS_MAX_NAME_LENGTH+1];
1503
1504   if(!pSearch->foundObjects)
1505   {
1506     pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
1507     pSearch->foundObjects->next = NULL;
1508     pSearch->foundObjects->obj = 0;
1509   }
1510
1511
1512         yfsd_LockYAFFS();
1513
1514         pos = 0;
1515         list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
1516         {
1517
1518                 l = list_entry(i, yaffs_Object,siblings);
1519
1520                 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
1521
1522                 if(regularMatch(pSearch->pattern,name))
1523                 {
1524                         if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
1525                         {               
1526
1527                                 
1528                                 found = 1;
1529                                 //pSearch->currentPos++;
1530
1531                                 // fill out find data
1532
1533                                 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
1534
1535                                 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
1536                                 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
1537                                 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
1538
1539                                 pfd->nFileSizeHigh = 0;
1540                                 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
1541                                 pfd->dwOID = 0; // wtf is this???
1542
1543                                 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
1544
1545                                 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
1546                                                         pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
1547                                                         l->variant.fileVariant.scannedFileSize));
1548                                 goto out_of_here;
1549                         }
1550                         else
1551                         {
1552                                 pos++;
1553                         }
1554                 }
1555         }
1556
1557 out_of_here:
1558         yfsd_UnlockYAFFS();
1559
1560
1561         if(!found)
1562         {
1563                 SetLastError(ERROR_NO_MORE_FILES);
1564         }
1565         return found;
1566         
1567 }
1568
1569 #else
1570 // faster one
1571 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
1572 {
1573
1574         struct list_head *i;
1575         yaffs_Object *l;
1576         BOOL found = 0;
1577
1578         char name[YAFFS_MAX_NAME_LENGTH+1];
1579
1580   if(!pSearch->foundObjects)
1581   {
1582     pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
1583     pSearch->foundObjects->next = NULL;
1584     pSearch->foundObjects->obj = 0;
1585   }
1586
1587
1588         yfsd_LockYAFFS();
1589
1590         list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
1591         {
1592
1593                 l = list_entry(i, yaffs_Object,siblings);
1594                 if(!yfsd_ObjectAlreadyFound(pSearch,l))
1595                 {
1596                         // Only look at things we have not looked at already
1597                         yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
1598
1599                         if(regularMatch(pSearch->pattern,name))
1600                         {
1601                                 found = 1;
1602                                 // fill out find data
1603
1604                                 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
1605
1606                                 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
1607                                 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
1608                                 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
1609
1610                                 pfd->nFileSizeHigh = 0;
1611                                 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
1612                                 pfd->dwOID = 0; // wtf is this???
1613
1614                                 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
1615
1616                                 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
1617                                                         pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
1618                                                         l->variant.fileVariant.scannedFileSize));
1619                                 goto out_of_here;
1620                         }
1621
1622                 }
1623
1624
1625         }
1626
1627 out_of_here:
1628         yfsd_UnlockYAFFS();
1629
1630
1631         if(!found)
1632         {
1633                 SetLastError(ERROR_NO_MORE_FILES);
1634         }
1635         return found;
1636         
1637 }
1638 #endif
1639
1640 HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
1641 {
1642
1643         // Create a search context, register it, and do the first search
1644
1645         PSEARCH pSearch;
1646         HANDLE h = INVALID_HANDLE_VALUE;
1647         BOOL found = 0;
1648
1649         RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
1650
1651         pSearch = malloc(sizeof(yfsd_WinFind));
1652         if(!pSearch)
1653         {
1654                 SetLastError(ERROR_OUTOFMEMORY);
1655         }
1656
1657         yfsd_LockYAFFS();
1658
1659         if(pSearch)
1660         {
1661                 pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
1662                 pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
1663                 if(pSearch->dir)
1664                 {
1665                                 pSearch->dir->inUse++;
1666                 }
1667                 else
1668                 {
1669                         free(pSearch);
1670                         pSearch = NULL;
1671                 }
1672         }
1673
1674         yfsd_UnlockYAFFS();
1675
1676
1677
1678         if(pSearch)
1679         {
1680                 found = yfsd_DoFindFile(pSearch,pfd);
1681         }
1682
1683         if(found)
1684         {
1685                 h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
1686         }
1687
1688         if(h == INVALID_HANDLE_VALUE && pSearch)
1689         {
1690                 yfsd_DeleteFinder(pSearch);
1691                 SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
1692         }
1693
1694
1695
1696         return h;
1697 }
1698
1699 BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
1700 {
1701         RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
1702         if(!pSearch)
1703         {
1704                 return FALSE;
1705         }
1706         return yfsd_DoFindFile(pSearch,pfd);
1707 }
1708
1709 BOOL YFSD_FindClose( PSEARCH pSearch )
1710 {       
1711         RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
1712         if(!pSearch)
1713         {
1714                 return FALSE;
1715         }
1716         yfsd_DeleteFinder(pSearch);
1717         return TRUE;
1718 }
1719
1720
1721 HANDLE YFSD_CreateFileW( 
1722         PVOLUME pVolume, 
1723         HANDLE hProc, 
1724         PCWSTR pwsFileName, 
1725         DWORD dwAccess, 
1726         DWORD dwShareMode,
1727         PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
1728         DWORD dwCreate,
1729         DWORD dwFlagsAndAttributes, 
1730         HANDLE hTemplateFile ) // ignore
1731 {
1732
1733
1734         yaffs_Object *parent = NULL;
1735         yaffs_Object *obj = NULL;
1736         char name[YFSD_NAME_LENGTH+1];
1737         int mode;
1738         yfsd_WinFile *f = NULL;
1739         HANDLE handle = INVALID_HANDLE_VALUE;
1740         unsigned modifiedTime[2];
1741         unsigned objSize;
1742
1743         BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;\r
1744         BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;\r
1745         BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;\r
1746         BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;\r
1747 \r
1748         BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;\r
1749
1750         BOOL fileCreated = FALSE;
1751
1752
1753         mode = dwFlagsAndAttributes & 0x00FFFFFF;  // ding off the flags
1754
1755
1756         RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));
1757         if(writePermitted)
1758         {
1759                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
1760         }
1761         else
1762         {
1763                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
1764         }
1765
1766         if(!yfsd_CheckValidAttributes(mode))
1767         {
1768                         SetLastError(ERROR_INVALID_PARAMETER);
1769                         return FALSE;
1770         }
1771
1772         yfsd_LockYAFFS();
1773
1774
1775         parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
1776
1777
1778         if(parent && yfsd_NameIsValid(name))
1779         {
1780
1781                 if(dwCreate == CREATE_NEW)
1782                 {
1783                         RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
1784
1785                         //slf021101c begin
1786                         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1787                         if(!obj)
1788                         {
1789                                 obj = yaffs_MknodFile(parent,name,mode,0,0);
1790                                 if(!obj)
1791                                         SetLastError(ERROR_DISK_FULL);
1792                                 fileCreated = TRUE;
1793                         }
1794                         else
1795                         {
1796                                 obj = NULL;
1797                                 SetLastError(ERROR_ALREADY_EXISTS);
1798                         }\r
1799                         //slf021101c end
1800                 }
1801                 else if( dwCreate == OPEN_ALWAYS)
1802                 {
1803                         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1804                         if(!obj)
1805                         {
1806                                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
1807                                 obj = yaffs_MknodFile(parent,name,mode,0,0);
1808                                 if(!obj)
1809                                         SetLastError(ERROR_DISK_FULL);
1810                                 fileCreated = TRUE;
1811
1812                         }
1813                         else
1814                         {
1815                                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
1816                         }
1817                 }
1818                 else if(dwCreate == OPEN_EXISTING)
1819                 {
1820                         RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
1821                         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1822                         if(!obj)
1823                                 SetLastError(ERROR_FILE_NOT_FOUND);
1824             //slf021101c begin
1825                         else
1826                                 if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
1827                                 {
1828                                         SetLastError(ERROR_ACCESS_DENIED);
1829                                         obj = NULL;
1830                                 }
1831             //slf021101c end
1832                 }
1833                 else if(dwCreate == TRUNCATE_EXISTING)
1834                 {
1835                         RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));
1836                         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1837                         if(obj)
1838                         {
1839                                 yaffs_ResizeFile(obj,0);
1840                         }
1841                         else
1842                         {
1843                                 SetLastError(ERROR_FILE_NOT_FOUND);
1844                         }
1845                 }
1846                 else if(dwCreate == CREATE_ALWAYS)
1847                 {
1848                         obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1849
1850                         if(!obj)
1851                         {
1852                                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
1853                                 obj = yaffs_MknodFile(parent,name,mode,0,0);
1854                                 if(!obj)
1855                                         SetLastError(ERROR_DISK_FULL);
1856                                 fileCreated = TRUE;
1857                         }
1858                         else
1859                         {
1860                                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));
1861                                 obj->st_mode = mode;
1862                                 obj->dirty = 1;
1863                                 yaffs_ResizeFile(obj,0);
1864                                 yaffs_FlushFile(obj,1);
1865                         }
1866                 }
1867                 else
1868                 {
1869                                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
1870                                 SetLastError(ERROR_INVALID_PARAMETER);
1871                 }
1872         }
1873         else
1874         {
1875                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
1876                 SetLastError(ERROR_PATH_NOT_FOUND);
1877         }
1878 \r
1879         if(obj)\r
1880         {\r
1881                         int i;\r
1882                         yfsd_WinFile *p;\r
1883                         openRead = openWrite =0;\r
1884                         openReadAllowed = openWriteAllowed = 1;\r
1885 \r
1886                         for(i = 0; i < MAX_WIN_FILE; i++)\r
1887                         {\r
1888                                         p = &yfsd_winFile[i];\r
1889 \r
1890                                         if(p->obj == obj)\r
1891                                         {\r
1892                                                 if (p->readPermitted) openRead = 1;\r
1893                                                 if (p->writePermitted) openWrite = 1;\r
1894                                                 if (!p->shareRead) openReadAllowed = 0;\r
1895                                                 if (!p->shareWrite) openWriteAllowed = 0;\r
1896                                         }\r
1897 \r
1898                         }\r
1899 \r
1900                         // Now we test if the share works out.\r
1901 \r
1902                         if((openRead && !shareRead) ||   // already open for read, but we are not prepared to share it for read\r
1903                            (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write\r
1904                            (!openReadAllowed && readPermitted) || // already open with read sharing not permitted\r
1905                            (!openWriteAllowed && writePermitted)) // same... write\r
1906                         {\r
1907                                 SetLastError(ERROR_ACCESS_DENIED);\r
1908                                 obj = NULL;\r
1909                         }\r
1910 \r
1911 \r
1912         }
1913         if(obj)
1914         {
1915                 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
1916                 f = yfsd_GetWinFile();
1917         }
1918         else
1919         {
1920                 RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
1921         }
1922
1923         if(f)
1924         {
1925
1926                 handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
1927
1928                 if(handle != INVALID_HANDLE_VALUE)
1929                 {
1930                         RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
1931                         f->obj = obj;
1932                         f->offset = 0;
1933                         f->writePermitted = writePermitted;\r
1934                         f->readPermitted = writePermitted;\r
1935                         f->shareRead= shareRead;\r
1936                         f->shareWrite = shareWrite;\r
1937                         f->myVolume = pVolume;
1938                         obj->inUse++;
1939
1940                         modifiedTime[0] = obj->win_mtime[0];
1941                         modifiedTime[1] = obj->win_mtime[1];
1942                         objSize = yaffs_GetObjectFileLength(obj);
1943                         RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
1944                 }
1945                 else
1946                 {
1947                         yfsd_PutWinFile(f);
1948                         RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
1949                 }
1950
1951         }
1952
1953         yfsd_UnlockYAFFS();
1954
1955         if(handle != INVALID_HANDLE_VALUE && 
1956            fileCreated &&
1957            pVolume->shellFunction)
1958         {
1959                         FILECHANGEINFO fc;
1960                         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1961
1962                         fc.cbSize = sizeof(FILECHANGEINFO);
1963                         fc.wEventId = SHCNE_CREATE;
1964                         fc.uFlags = SHCNF_PATH;
1965                         fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1966                         fc.dwItem2 = 0;
1967                         fc.dwAttributes = mode;
1968                         yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
1969                         fc.nFileSize = objSize;
1970
1971                         pVolume->shellFunction(&fc);
1972                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1973
1974                         yfsd_ShellDirectoryChanged(pVolume,fpn);
1975         }
1976
1977         if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
1978         {
1979                         // Remember the name
1980
1981                         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1982                         int slen;
1983
1984                         yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1985                         slen = wcslen(fpn);
1986                         f->fullName = malloc((slen+1)* sizeof(WCHAR));
1987                         if(f->fullName)
1988                         {
1989                                 wcscpy(f->fullName,fpn);
1990                         }
1991
1992         }
1993
1994
1995         return handle;
1996
1997 }
1998
1999 BOOL yfsd_DoReadFile( 
2000         PFILE pFile, 
2001         PVOID pBuffer, 
2002         DWORD cbRead, 
2003         PDWORD pcbRead)
2004 {
2005         
2006         DWORD maxRead;
2007         int nread = 0;
2008         yaffs_Object *obj = NULL;
2009
2010
2011         if(pcbRead)
2012         {
2013                 *pcbRead = 0;
2014         }
2015         else
2016         {
2017                 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
2018         }
2019
2020         RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
2021
2022         if(!pFile || !pFile->obj)
2023         {
2024                 SetLastError(ERROR_INVALID_HANDLE);
2025                 return FALSE;
2026         }
2027         
2028         obj = pFile->obj;
2029
2030         if(yaffs_GetObjectFileLength(obj) > pFile->offset)
2031         {
2032                 maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
2033         }
2034         else
2035         {
2036                 maxRead = 0;
2037         }
2038
2039         if(cbRead > maxRead)
2040         {
2041                 cbRead = maxRead;
2042         }
2043         
2044         if(maxRead > 0)
2045         {
2046                 nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
2047                 if(nread > 0)
2048                 {
2049                         pFile->offset += nread;
2050
2051                         if(pcbRead)
2052                         {
2053                                 *pcbRead = nread;
2054                         }
2055                 }
2056         }
2057         else
2058         {
2059                 if(pcbRead) 
2060                 {
2061                         *pcbRead = maxRead;
2062                 }
2063         }
2064
2065
2066         return nread < 0? FALSE : TRUE; 
2067
2068 }
2069
2070 BOOL YFSD_ReadFile( 
2071         PFILE pFile, 
2072         PVOID pBuffer, 
2073         DWORD cbRead, 
2074         PDWORD pcbRead, 
2075         OVERLAPPED *pOverlapped ) //ignore
2076 {
2077         BOOL result;
2078
2079         RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
2080
2081         if(!pFile || !pFile->obj)
2082         {
2083                 SetLastError(ERROR_INVALID_HANDLE);
2084                 return FALSE;
2085         }
2086
2087         yfsd_LockYAFFS();
2088
2089         result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
2090
2091         yfsd_UnlockYAFFS();
2092
2093         return result;
2094 }
2095
2096 BOOL YFSD_ReadFileWithSeek( 
2097         PFILE pFile, 
2098         PVOID pBuffer, 
2099         DWORD cbRead, 
2100         PDWORD pcbRead, 
2101         OVERLAPPED *pOverlapped, 
2102         DWORD dwLowOffset, 
2103         DWORD dwHighOffset )
2104 {
2105         BOOL result;
2106         DWORD rememberedOffset;
2107
2108         RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
2109
2110         // To determine if paging is supported, the kernel calls this with all parameters except pFile
2111         // being zero.
2112         if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
2113         {
2114                 return TRUE; // paging suppported
2115                 //return FALSE; // paging not supported
2116         }
2117
2118         if(!pFile || !pFile->obj)
2119         {
2120                 SetLastError(ERROR_INVALID_HANDLE);
2121                 return FALSE;
2122         }
2123
2124         yfsd_LockYAFFS();
2125
2126         rememberedOffset = pFile->offset;
2127
2128         pFile->offset = dwLowOffset;
2129         // ignore high offset for now
2130
2131         result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
2132
2133         //pFile->offset = rememberedOffset;
2134
2135         yfsd_UnlockYAFFS();
2136
2137         return result;
2138
2139
2140 }
2141
2142
2143 BOOL yfsd_DoWriteFile( 
2144         PFILE pFile, 
2145         PCVOID pBuffer, 
2146         DWORD cbWrite, 
2147         PDWORD pcbWritten)
2148 {
2149         int nwritten = 0;
2150         yaffs_Object *obj = NULL;
2151         
2152         RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
2153         
2154         if(!pFile || !pFile->obj)
2155         {
2156                 SetLastError(ERROR_INVALID_HANDLE);
2157                 return FALSE;
2158         }
2159
2160         if(!pFile->writePermitted)
2161         {
2162                         *pcbWritten = 0;
2163                         SetLastError(ERROR_ACCESS_DENIED);
2164                         return FALSE;
2165         }
2166
2167         obj = pFile->obj;
2168
2169         *pcbWritten = 0;
2170
2171
2172                 nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
2173                 if(nwritten >= 0)
2174                 {
2175                         pFile->offset += nwritten;
2176                         *pcbWritten = nwritten;
2177                 }
2178                 if(nwritten != cbWrite)
2179                 {
2180                         SetLastError(ERROR_DISK_FULL);
2181                 }
2182
2183
2184         return nwritten != cbWrite? FALSE : TRUE; 
2185 }
2186
2187
2188 BOOL YFSD_WriteFile( 
2189         PFILE pFile, 
2190         PCVOID pBuffer, 
2191         DWORD cbWrite, 
2192         PDWORD pcbWritten, 
2193         OVERLAPPED *pOverlapped )
2194 {
2195         BOOL result;
2196
2197         yfsd_LockYAFFS();
2198         RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
2199
2200         result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
2201
2202         yfsd_UnlockYAFFS();
2203
2204         return result;
2205 }
2206
2207 BOOL YFSD_WriteFileWithSeek( 
2208         PFILE pFile, 
2209         PCVOID pBuffer, 
2210         DWORD cbWrite, 
2211         PDWORD pcbWritten, 
2212         OVERLAPPED *pOverlapped,
2213         DWORD dwLowOffset, 
2214         DWORD dwHighOffset )
2215 {
2216         BOOL result;
2217         DWORD rememberedOffset;
2218         RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
2219
2220         
2221
2222         if(!pFile || !pFile->obj)
2223         {
2224                 SetLastError(ERROR_INVALID_HANDLE);
2225                 return FALSE;
2226         }
2227
2228         yfsd_LockYAFFS();
2229
2230         rememberedOffset = pFile->offset;
2231
2232         pFile->offset = dwLowOffset;
2233         // ignore high offset for now
2234
2235         result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
2236
2237         //pFile->offset = rememberedOffset;
2238
2239         yfsd_UnlockYAFFS();
2240
2241         return result;
2242 }
2243
2244 DWORD YFSD_SetFilePointer( 
2245         PFILE pFile, 
2246         LONG lDistanceToMove, 
2247         PLONG pDistanceToMoveHigh, 
2248         DWORD dwMoveMethod )
2249 {
2250         // ignore high offset for now
2251
2252         DWORD offset = 0xFFFFFFFF;
2253         DWORD oldPos;
2254         int fileSize;
2255         int seekNegative = 0;
2256
2257
2258         if(!pFile || !pFile->obj)
2259         {
2260                 SetLastError(ERROR_INVALID_HANDLE);
2261                 return offset;
2262         }
2263
2264         yfsd_LockYAFFS();
2265
2266
2267         oldPos = pFile->offset;
2268
2269         if(dwMoveMethod == FILE_BEGIN)
2270         {
2271                 if(lDistanceToMove >= 0)
2272                 {       
2273                         offset = pFile->offset = lDistanceToMove;
2274                 }
2275                 else
2276                 {
2277                         seekNegative = 1;
2278                 }
2279         }
2280         else if(dwMoveMethod == FILE_END)
2281         {
2282                 fileSize = yaffs_GetObjectFileLength(pFile->obj);
2283                 if(fileSize >= 0 &&
2284                    (fileSize + lDistanceToMove) >= 0)
2285                 {
2286                         offset = pFile->offset = fileSize + lDistanceToMove;
2287                 }
2288                 else
2289                 {
2290                         seekNegative = 1;
2291                 }
2292         }
2293         else if(dwMoveMethod == FILE_CURRENT)
2294         {
2295                 if(pFile->offset + lDistanceToMove >= 0)
2296                 {
2297                         offset = pFile->offset = pFile->offset + lDistanceToMove;               
2298                 }
2299                 else
2300                 {
2301                                 seekNegative = 1;
2302                 }
2303         }
2304
2305         if(seekNegative)
2306         {
2307                         SetLastError(ERROR_NEGATIVE_SEEK);
2308                         
2309         }
2310
2311         yfsd_UnlockYAFFS();
2312
2313         RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
2314                                   dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
2315
2316         return offset;
2317
2318 }
2319
2320 DWORD YFSD_GetFileSize( 
2321         PFILE pFile, 
2322         PDWORD pFileSizeHigh )
2323 {
2324         int fileSize;
2325         
2326         RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
2327         
2328
2329         if(!pFile || !pFile->obj)
2330         {
2331                 SetLastError(ERROR_INVALID_HANDLE);
2332                 return -1;
2333         }
2334
2335         yfsd_LockYAFFS();
2336
2337         fileSize = yaffs_GetObjectFileLength(pFile->obj);
2338
2339         yfsd_UnlockYAFFS();
2340         if(pFileSizeHigh)
2341                  *pFileSizeHigh = 0;
2342
2343         return fileSize;
2344
2345 }
2346
2347
2348 BOOL YFSD_GetFileInformationByHandle( 
2349         PFILE pFile,
2350         PBY_HANDLE_FILE_INFORMATION pFileInfo )
2351 {
2352         RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
2353
2354         if(!pFile || !pFile->obj || !pFileInfo)
2355         {
2356                 SetLastError(ERROR_INVALID_HANDLE);
2357                 return FALSE;
2358         }
2359
2360         yfsd_LockYAFFS();
2361
2362         pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
2363         yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
2364         yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
2365         yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
2366         pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK? 
2367         pFileInfo->nFileSizeHigh = 0;
2368         pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj); 
2369         pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
2370         pFileInfo->nFileIndexHigh = 0; 
2371         pFileInfo->nFileIndexLow = pFile->obj->objectId;\r
2372 //slf021104a Begin Window CE 4.0 added an additional field.\r
2373 #if _WINCEOSVER >= 400
2374         pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);\r
2375 #endif\r
2376 //slf021104a end\r
2377
2378         yfsd_UnlockYAFFS();
2379
2380         return TRUE;
2381 }
2382
2383 BOOL YFSD_FlushFileBuffers(PFILE pFile )
2384 {
2385         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2386         int nameExists = 0;
2387         yfsd_Volume *vol = NULL;
2388         DWORD attribs = 0;
2389         DWORD objSize = 0;
2390         DWORD mtime[2];
2391
2392
2393         RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
2394
2395         if(!pFile || !pFile->obj)
2396         {
2397                 SetLastError(ERROR_INVALID_HANDLE);
2398                 return FALSE;
2399         }
2400
2401         yfsd_LockYAFFS();
2402
2403         yaffs_FlushFile(pFile->obj,1);
2404         attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2405         objSize = yaffs_GetObjectFileLength(pFile->obj);
2406         mtime[0] = pFile->obj->win_mtime[0];
2407         mtime[1] = pFile->obj->win_mtime[1];
2408         if(pFile->fullName)
2409         {
2410                 wcscpy(fpn,pFile->fullName);
2411                 nameExists = 1;
2412         }
2413         vol = pFile->myVolume;
2414
2415         yfsd_UnlockYAFFS();
2416         
2417         if(vol && vol->shellFunction && nameExists)
2418         {
2419                         FILECHANGEINFO fc;
2420                 
2421                         fc.cbSize = sizeof(FILECHANGEINFO);
2422                         fc.wEventId = SHCNE_UPDATEITEM;
2423                         fc.uFlags = SHCNF_PATH;
2424                         fc.dwItem1 = (DWORD)fpn;
2425                         fc.dwItem2 = 0;
2426                         fc.dwAttributes = attribs;
2427                         yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2428                         fc.nFileSize = objSize;
2429
2430                         vol->shellFunction(&fc);
2431                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2432                         //yfsd_ShellDirectoryChanged(vol,fpn);
2433         }
2434
2435         
2436         return TRUE;
2437 }
2438
2439 BOOL YFSD_GetFileTime( 
2440         PFILE pFile, 
2441         FILETIME *pCreation, 
2442         FILETIME *pLastAccess, 
2443         FILETIME *pLastWrite )
2444 {
2445
2446         RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
2447         if(!pFile || !pFile->obj)
2448         {
2449                 SetLastError(ERROR_INVALID_HANDLE);
2450                 return FALSE;
2451         }
2452
2453         yfsd_LockYAFFS();
2454
2455         if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
2456         if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
2457         if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
2458
2459         yfsd_UnlockYAFFS();
2460
2461         return TRUE;
2462 }
2463
2464 BOOL YFSD_SetFileTime( 
2465         PFILE pFile, 
2466         CONST FILETIME *pCreation, 
2467         CONST FILETIME *pLastAccess, 
2468         CONST FILETIME *pLastWrite )
2469 {
2470         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2471         int nameExists = 0;
2472         int result = FALSE;
2473         yfsd_Volume *vol = NULL;
2474         DWORD attribs = 0;
2475         DWORD objSize = 0;
2476         DWORD mtime[2];
2477
2478         
2479         RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
2480
2481         if(!pFile || !pFile->obj)
2482         {
2483                 SetLastError(ERROR_INVALID_HANDLE);
2484                 return FALSE;
2485         }
2486         
2487         
2488         yfsd_LockYAFFS();
2489
2490         if(pCreation) 
2491         {
2492                  yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
2493                 pFile->obj->dirty = 1;
2494         }
2495         if(pLastAccess)
2496         {
2497                 yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
2498                 pFile->obj->dirty = 1;
2499         }
2500         if(pLastWrite)
2501         {
2502                 yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
2503                 pFile->obj->dirty = 1;
2504         }
2505         if(pCreation || pLastAccess || pLastWrite)
2506         {
2507                 result = yaffs_FlushFile(pFile->obj,0);
2508         }
2509
2510         if(result)
2511         {
2512                 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2513                 objSize = yaffs_GetObjectFileLength(pFile->obj);
2514                 mtime[0] = pFile->obj->win_mtime[0];
2515                 mtime[1] = pFile->obj->win_mtime[1];
2516                 if(pFile->fullName)
2517                 {
2518                         wcscpy(fpn,pFile->fullName);
2519                         nameExists = 1;
2520                 }
2521                 vol = pFile->myVolume;
2522         }
2523
2524         yfsd_UnlockYAFFS();
2525
2526         // Call shell function
2527         if(nameExists && result && vol && vol->shellFunction)
2528         {
2529                         FILECHANGEINFO fc;
2530                 
2531                         fc.cbSize = sizeof(FILECHANGEINFO);
2532                         fc.wEventId = SHCNE_UPDATEITEM;
2533                         fc.uFlags = SHCNF_PATH;
2534                         fc.dwItem1 = (DWORD)fpn;
2535                         fc.dwItem2 = 0;
2536                         fc.dwAttributes = attribs;
2537                         yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2538                         fc.nFileSize = objSize;
2539
2540                         vol->shellFunction(&fc);
2541                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2542                         //yfsd_ShellDirectoryChanged(vol,fpn);
2543         }
2544
2545         return TRUE;
2546 }
2547    
2548 BOOL YFSD_SetEndOfFile( 
2549 PFILE pFile )
2550 {
2551
2552         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2553         int nameExists = 0;
2554         yfsd_Volume *vol = NULL;
2555         DWORD attribs = 0;
2556         DWORD objSize = 0;
2557         DWORD mtime[2];
2558         static unsigned char zeros[512];
2559
2560         int result;
2561         BOOL retVal = FALSE;
2562
2563         RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
2564
2565         if(!pFile || !pFile->obj)
2566         {
2567                 SetLastError(ERROR_INVALID_HANDLE);
2568                 return FALSE;
2569         }
2570
2571         yfsd_LockYAFFS();
2572         result = yaffs_ResizeFile(pFile->obj,pFile->offset);
2573
2574         RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
2575
2576         // Resize only works if we're shortening the file.
2577         // If the result is shorter than the offset, then we need to write zeros....
2578         // 
2579         if(result != pFile->offset)
2580         {
2581                 if(result < pFile->offset)
2582                 {
2583
2584                         int nBytes = pFile->offset - result;
2585                         int thisWriteSize;
2586                         int written;
2587                         BOOL ok = TRUE;
2588
2589                         memset(zeros,0,512);
2590
2591                         pFile->offset = result;
2592                         RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
2593                         while(nBytes > 0 && ok)
2594                         {
2595                                 thisWriteSize = (nBytes > 512) ? 512  : nBytes;
2596
2597                                 ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);      
2598                                 if(written != thisWriteSize)
2599                                 {
2600                                         ok = FALSE;
2601                                 }
2602
2603                                 nBytes -= thisWriteSize;
2604                         }
2605
2606                         retVal = ok;
2607                 }
2608                 else
2609                 {
2610
2611                         SetLastError(ERROR_ACCESS_DENIED);
2612                         retVal = FALSE;
2613                 }
2614         }
2615         else
2616         {
2617                 retVal = TRUE;
2618         }
2619         if(retVal)
2620         {
2621                 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2622                 objSize = yaffs_GetObjectFileLength(pFile->obj);
2623                 mtime[0] = pFile->obj->win_mtime[0];
2624                 mtime[1] = pFile->obj->win_mtime[1];
2625                 if(pFile->fullName)
2626                 {
2627                         wcscpy(fpn,pFile->fullName);
2628                         nameExists = 1;
2629                 }
2630                 vol = pFile->myVolume;
2631         }
2632
2633
2634         yfsd_UnlockYAFFS();
2635
2636         if(nameExists && retVal && vol && vol->shellFunction)
2637         {
2638                         FILECHANGEINFO fc;
2639                 
2640                         fc.cbSize = sizeof(FILECHANGEINFO);
2641                         fc.wEventId = SHCNE_UPDATEITEM;
2642                         fc.uFlags = SHCNF_PATH;
2643                         fc.dwItem1 = (DWORD)fpn;
2644                         fc.dwItem2 = 0;
2645                         fc.dwAttributes = attribs;
2646                         yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2647                         fc.nFileSize = objSize;
2648
2649                         vol->shellFunction(&fc);
2650                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2651                         //yfsd_ShellDirectoryChanged(vol,fpn);
2652         }
2653
2654         RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
2655
2656
2657         
2658         return retVal;
2659 }
2660
2661 BOOL YFSD_DeviceIoControl( 
2662         PFILE pFile, 
2663         DWORD dwIoControlCode, 
2664         PVOID pInBuf, 
2665         DWORD nInBufSize, 
2666         PVOID pOutBuf, 
2667         DWORD nOutBufSize, 
2668         PDWORD pBytesReturned, 
2669         OVERLAPPED *pOverlapped )
2670 {
2671         RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
2672
2673         return FALSE;
2674 }
2675
2676 BOOL YFSD_CloseFile( PFILE pFile )
2677 {
2678         WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2679         int nameExists = 0;
2680         yfsd_Volume *vol = NULL;
2681         DWORD attribs = 0;
2682         DWORD objSize = 0;
2683         DWORD mtime[2];
2684
2685         RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
2686
2687         yfsd_LockYAFFS();
2688
2689         if(!pFile)
2690         {
2691                 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
2692         }
2693         else
2694         {
2695                 if(pFile->obj)
2696                 {
2697                         pFile->obj->inUse--;
2698                         RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
2699                         yaffs_FlushFile(pFile->obj,1);
2700                         attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2701                         objSize = yaffs_GetObjectFileLength(pFile->obj);
2702                         mtime[0] = pFile->obj->win_mtime[0];
2703                         mtime[1] = pFile->obj->win_mtime[1];
2704                         RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
2705                         if(pFile->fullName)
2706                         {
2707                                 wcscpy(fpn,pFile->fullName);
2708                                 nameExists = 1;
2709                         }
2710                         vol = pFile->myVolume;
2711                         yfsd_PutWinFile(pFile);
2712                 }
2713                 else
2714                 {
2715                         RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
2716                 }
2717
2718         }
2719         yfsd_UnlockYAFFS();
2720
2721
2722         if(nameExists && vol && vol->shellFunction)
2723         {
2724                         FILECHANGEINFO fc;
2725                 
2726                         fc.cbSize = sizeof(FILECHANGEINFO);
2727                         fc.wEventId = SHCNE_UPDATEITEM;
2728                         fc.uFlags = SHCNF_PATH;
2729                         fc.dwItem1 = (DWORD)fpn;
2730                         fc.dwItem2 = 0;
2731                         fc.dwAttributes = attribs;
2732                         yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2733                         fc.nFileSize = objSize;
2734
2735                         vol->shellFunction(&fc);
2736                         RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2737                         //yfsd_ShellDirectoryChanged(vol,fpn);
2738         }
2739
2740         
2741
2742         RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
2743
2744         return TRUE;
2745
2746 }
2747
2748
2749 BOOL YFSD_CloseVolume(PVOLUME pVolume )
2750 {
2751         RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
2752         yfsd_FlushAllFiles();
2753         return TRUE;
2754 }
2755