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