d4565e969e64d8d4e1786987515ad929a86fe80a
[vuplus_xbmc] / xbmc / cores / DllLoader / exports / emu_msvcrt.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #ifndef TARGET_POSIX
25 #include <io.h>
26 #include <direct.h>
27 #include <process.h>
28 #else
29 #if !defined(TARGET_DARWIN) && !defined(TARGET_FREEBSD)
30 #include <mntent.h>
31 #endif
32 #endif
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #if !defined(TARGET_FREEBSD)
36 #include <sys/timeb.h>
37 #endif
38 #include "system.h" // for HAS_DVD_DRIVE
39 #ifdef HAS_DVD_DRIVE
40   #ifdef TARGET_POSIX
41     #include <sys/ioctl.h>
42     #if defined(TARGET_DARWIN)
43       #include <IOKit/storage/IODVDMediaBSDClient.h>
44     #elif !defined(TARGET_FREEBSD)
45       #include <linux/cdrom.h>
46     #endif
47   #endif
48 #endif
49 #include <fcntl.h>
50 #include <time.h>
51 #include <signal.h>
52 #ifdef TARGET_POSIX
53 #include "PlatformDefs.h" // for __stat64
54 #endif
55 #include "Util.h"
56 #include "filesystem/SpecialProtocol.h"
57 #include "URL.h"
58 #include "filesystem/File.h"
59 #include "settings/Settings.h"
60 #include "FileItem.h"
61 #include "filesystem/Directory.h"
62
63 #include "emu_msvcrt.h"
64 #include "emu_dummy.h"
65 #include "emu_kernel32.h"
66 #include "util/EmuFileWrapper.h"
67 #include "utils/log.h"
68 #include "threads/SingleLock.h"
69 #ifndef TARGET_POSIX
70 #include "utils/CharsetConverter.h"
71 #include "utils/URIUtils.h"
72 #endif
73 #if defined(TARGET_ANDROID)
74 #include "android/loader/AndroidDyload.h"
75 #elif !defined(TARGET_WINDOWS)
76 #include <dlfcn.h>
77 #endif
78 #include "utils/Environment.h"
79
80 using namespace std;
81 using namespace XFILE;
82
83 struct SDirData
84 {
85   CFileItemList items;
86   int curr_index;
87   struct dirent *last_entry;
88   SDirData()
89   {
90     curr_index = -1;
91     last_entry = NULL;
92   }
93 };
94
95 #define MAX_OPEN_DIRS 10
96 static SDirData vecDirsOpen[MAX_OPEN_DIRS];
97 bool bVecDirsInited = false;
98 #ifdef HAS_VIDEO_PLAYBACK
99 extern void update_cache_dialog(const char* tmp);
100 #endif
101
102 #define EMU_MAX_ENVIRONMENT_ITEMS 100
103 static char *dll__environ_imp[EMU_MAX_ENVIRONMENT_ITEMS + 1];
104 extern "C" char **dll__environ;
105 char **dll__environ = dll__environ_imp;
106
107 CCriticalSection dll_cs_environ;
108
109 #define dll_environ    (*dll___p__environ())   /* pointer to environment table */
110
111 extern "C" void __stdcall init_emu_environ()
112 {
113   memset(dll__environ, 0, EMU_MAX_ENVIRONMENT_ITEMS + 1);
114
115   // python
116 #if defined(TARGET_WINDOWS)
117   // fill our array with the windows system vars
118   LPTSTR lpszVariable; 
119   LPTCH lpvEnv;
120   lpvEnv = GetEnvironmentStrings();
121   if (lpvEnv != NULL)
122   {
123     lpszVariable = (LPTSTR) lpvEnv;
124     while (*lpszVariable)
125     {
126       dll_putenv(lpszVariable);
127       lpszVariable += lstrlen(lpszVariable) + 1;
128     }
129     FreeEnvironmentStrings(lpvEnv);
130   }
131   dll_putenv("OS=win32");
132 #elif defined(TARGET_DARWIN)
133   dll_putenv("OS=darwin");
134 #elif defined(TARGET_POSIX)
135   dll_putenv("OS=linux");
136 #else
137   dll_putenv("OS=unknown");
138 #endif
139
140   // check if we are running as real xbmc.app or just binary
141   if (!CUtil::GetFrameworksPath(true).IsEmpty())
142   {
143     // using external python, it's build looking for xxx/lib/python2.6
144     // so point it to frameworks which is where python2.6 is located
145     dll_putenv(string("PYTHONPATH=" +
146       CSpecialProtocol::TranslatePath("special://frameworks")).c_str());
147     dll_putenv(string("PYTHONHOME=" +
148       CSpecialProtocol::TranslatePath("special://frameworks")).c_str());
149     dll_putenv(string("PATH=.;" +
150       CSpecialProtocol::TranslatePath("special://xbmc") + ";" +
151       CSpecialProtocol::TranslatePath("special://frameworks")).c_str());
152   }
153   else
154   {
155     dll_putenv(string("PYTHONPATH=" +
156       CSpecialProtocol::TranslatePath("special://xbmc/system/python/DLLs") + ";" +
157       CSpecialProtocol::TranslatePath("special://xbmc/system/python/Lib")).c_str());
158     dll_putenv(string("PYTHONHOME=" +
159       CSpecialProtocol::TranslatePath("special://xbmc/system/python")).c_str());
160     dll_putenv(string("PATH=.;" + CSpecialProtocol::TranslatePath("special://xbmc") + ";" +
161       CSpecialProtocol::TranslatePath("special://xbmc/system/python")).c_str());
162   }
163
164 #if defined(TARGET_ANDROID)
165   string apkPath = getenv("XBMC_ANDROID_APK");
166   apkPath += "/assets/python2.6";
167   dll_putenv(string("PYTHONHOME=" + apkPath).c_str());
168   dll_putenv("PYTHONOPTIMIZE=");
169   dll_putenv("PYTHONNOUSERSITE=1");
170   dll_putenv("PYTHONPATH=");
171 #else
172   dll_putenv("PYTHONOPTIMIZE=1");
173 #endif
174
175   //dll_putenv("PYTHONCASEOK=1");
176   //dll_putenv("PYTHONDEBUG=1");
177   //dll_putenv("PYTHONVERBOSE=2"); // "1" for normal verbose, "2" for more verbose ?
178   //dll_putenv("PYTHONDUMPREFS=1");
179   //dll_putenv("THREADDEBUG=1");
180   //dll_putenv("PYTHONMALLOCSTATS=1");
181   //dll_putenv("PYTHONY2K=1");
182   dll_putenv("TEMP=special://temp/temp"); // for python tempdir
183
184   // libdvdnav
185   dll_putenv("DVDREAD_NOKEYS=1");
186   //dll_putenv("DVDREAD_VERBOSE=1");
187   //dll_putenv("DVDREAD_USE_DIRECT=1");
188
189   // libdvdcss
190   dll_putenv("DVDCSS_METHOD=key");
191   dll_putenv("DVDCSS_VERBOSE=3");
192   dll_putenv("DVDCSS_CACHE=special://masterprofile/cache");
193 }
194
195 extern "C" void __stdcall update_emu_environ()
196 {
197   // Use a proxy, if the GUI was configured as such
198   if (CSettings::Get().GetBool("network.usehttpproxy")
199       && !CSettings::Get().GetString("network.httpproxyserver").empty()
200       && CSettings::Get().GetInt("network.httpproxyport") > 0
201       && CSettings::Get().GetInt("network.httpproxytype") == 0)
202   {
203     CStdString strProxy;
204     if (!CSettings::Get().GetString("network.httpproxyusername").empty() &&
205         !CSettings::Get().GetString("network.httpproxypassword").empty())
206     {
207       strProxy.Format("%s:%s@", CSettings::Get().GetString("network.httpproxyusername").c_str(),
208                                 CSettings::Get().GetString("network.httpproxypassword").c_str());
209     }
210
211     strProxy += CSettings::Get().GetString("network.httpproxyserver");
212     strProxy.AppendFormat(":%d", CSettings::Get().GetInt("network.httpproxyport"));
213
214     CEnvironment::setenv( "HTTP_PROXY", "http://" + strProxy, true );
215     CEnvironment::setenv( "HTTPS_PROXY", "http://" + strProxy, true );
216   }
217   else
218   {
219     // is there a better way to delete an environment variable?
220     // this works but leaves the variable
221     dll_putenv( "HTTP_PROXY=" );
222     dll_putenv( "HTTPS_PROXY=" );
223   }
224 }
225
226 static int convert_fmode(const char* mode)
227 {
228   int iMode = O_BINARY;
229   if (strstr(mode, "r+"))
230     iMode |= O_RDWR;
231   else if (strchr(mode, 'r'))
232     iMode |= _O_RDONLY;
233   if (strstr(mode, "w+"))
234     iMode |= O_RDWR | _O_TRUNC;
235   else if (strchr(mode, 'w'))
236     iMode |= _O_WRONLY  | O_CREAT;
237   return iMode;
238 }
239
240 #ifdef TARGET_WINDOWS
241 static void to_finddata64i32(_wfinddata64i32_t *wdata, _finddata64i32_t *data)
242 {
243   CStdString strname;
244   g_charsetConverter.wToUTF8(wdata->name, strname);
245   size_t size = sizeof(data->name) / sizeof(char);
246   strncpy(data->name, strname.c_str(), size);
247   if (size)
248     data->name[size - 1] = '\0';
249   data->attrib = wdata->attrib;
250   data->time_create = wdata->time_create;
251   data->time_access = wdata->time_access;
252   data->time_write = wdata->time_write;
253   data->size = wdata->size;
254 }
255
256 static void to_wfinddata64i32(_finddata64i32_t *data, _wfinddata64i32_t *wdata)
257 {
258   CStdStringW strwname;
259   g_charsetConverter.utf8ToW(data->name, strwname, false);
260   size_t size = sizeof(wdata->name) / sizeof(wchar_t);
261   wcsncpy(wdata->name, strwname.c_str(), size);
262   if (size)
263     wdata->name[size - 1] = '\0';
264   wdata->attrib = data->attrib;
265   wdata->time_create = data->time_create;
266   wdata->time_access = data->time_access;
267   wdata->time_write = data->time_write;
268   wdata->size = data->size;
269 }
270 #endif
271
272 extern "C"
273 {
274   void dll_sleep(unsigned long imSec)
275   {
276     Sleep(imSec);
277   }
278
279   // FIXME, XXX, !!!!!!
280   void dllReleaseAll( )
281   {
282     // close all open dirs...
283     if (bVecDirsInited)
284     {
285       for (int i=0;i < MAX_OPEN_DIRS; ++i)
286       {
287         vecDirsOpen[i].items.Clear();
288       }
289       bVecDirsInited = false;
290     }
291   }
292
293   void* dllmalloc(size_t size)
294   {
295     void* pBlock = malloc(size);
296     if (!pBlock)
297     {
298       CLog::Log(LOGSEVERE, "malloc %"PRIdS" bytes failed, crash imminent", size);
299     }
300     return pBlock;
301   }
302
303   void dllfree( void* pPtr )
304   {
305     free(pPtr);
306   }
307
308   void* dllcalloc(size_t num, size_t size)
309   {
310     void* pBlock = calloc(num, size);
311     if (!pBlock)
312     {
313       CLog::Log(LOGSEVERE, "calloc %"PRIdS" bytes failed, crash imminent", size);
314     }
315     return pBlock;
316   }
317
318   void* dllrealloc( void *memblock, size_t size )
319   {
320     void* pBlock =  realloc(memblock, size);
321     if (!pBlock)
322     {
323       CLog::Log(LOGSEVERE, "realloc %"PRIdS" bytes failed, crash imminent", size);
324     }
325     return pBlock;
326   }
327
328   void dllexit(int iCode)
329   {
330     not_implement("msvcrt.dll fake function exit() called\n");      //warning
331   }
332
333   void dllabort()
334   {
335     not_implement("msvcrt.dll fake function abort() called\n");     //warning
336   }
337
338   void* dll__dllonexit(PFV input, PFV ** start, PFV ** end)
339   {
340     //ported from WINE code
341     PFV *tmp;
342     int len;
343
344     if (!start || !*start || !end || !*end)
345     {
346       //FIXME("bad table\n");
347       return NULL;
348     }
349
350     len = (*end - *start);
351
352     if (++len <= 0)
353       return NULL;
354
355     tmp = (PFV*) realloc (*start, len * sizeof(tmp) );
356     if (!tmp)
357       return NULL;
358     *start = tmp;
359     *end = tmp + len;
360     tmp[len - 1] = input;
361     return (void *)input;
362
363     //wrong handling, this function is used for register functions
364     //that called before exit use _initterm functions.
365
366     //dllReleaseAll( );
367     //return TRUE;
368   }
369
370   _onexit_t dll_onexit(_onexit_t func)
371   {
372     not_implement("msvcrt.dll fake function dll_onexit() called\n");
373
374     // register to dll unload list
375     // return func if succsesfully added to the dll unload list
376     return NULL;
377   }
378
379   int dllputs(const char* szLine)
380   {
381     if (!szLine[0]) return EOF;
382     if (szLine[strlen(szLine) - 1] != '\n')
383       CLog::Log(LOGDEBUG,"  msg: %s", szLine);
384     else
385       CLog::Log(LOGDEBUG,"  msg: %s\n", szLine);
386
387     // return a non negative value
388     return 0;
389   }
390
391   int dllprintf(const char *format, ...)
392   {
393     va_list va;
394     static char tmp[2048];
395     va_start(va, format);
396     _vsnprintf(tmp, 2048, format, va);
397     va_end(va);
398     tmp[2048 - 1] = 0;
399     CLog::Log(LOGDEBUG, "  msg: %s", tmp);
400
401     return strlen(tmp);
402   }
403
404   char *dll_fullpath(char *absPath, const char *relPath, size_t maxLength)
405   {
406     unsigned int len = strlen(relPath);
407     if (len > maxLength && absPath != NULL) return NULL;
408
409     // dll has to make sure it uses the correct path for now
410     if (len > 1 && relPath[1] == ':')
411     {
412       if (absPath == NULL) absPath = dll_strdup(relPath);
413       else
414       {
415         strncpy(absPath, relPath, maxLength);
416         if (maxLength != 0)
417           absPath[maxLength-1] = '\0';
418       }
419       return absPath;
420     }
421     if (!strncmp(relPath, "\\Device\\Cdrom0", 14))
422     {
423       // needed?
424       if (absPath == NULL) absPath = strdup(relPath);
425       else
426       {
427         strncpy(absPath, relPath, maxLength);
428         if (maxLength != 0)
429           absPath[maxLength-1] = '\0';
430       }
431       return absPath;
432     }
433
434     not_implement("msvcrt.dll incomplete function _fullpath(...) called\n");      //warning
435     return NULL;
436   }
437
438   FILE* dll_popen(const char *command, const char *mode)
439   {
440     not_implement("msvcrt.dll fake function _popen(...) called\n"); //warning
441     return NULL;
442   }
443
444   void *dll_dlopen(const char *filename, int flag)
445   {
446 #if defined(TARGET_ANDROID)
447     CAndroidDyload temp;
448     return temp.Open(filename);
449 #elif !defined(TARGET_WINDOWS)
450     return dlopen(filename, flag);
451 #else
452     return NULL;
453 #endif
454   }
455
456   int dll_pclose(FILE *stream)
457   {
458     not_implement("msvcrt.dll fake function _pclose(...) called\n");        //warning
459     return 0;
460   }
461
462   FILE* dll_fdopen(int fd, const char* mode)
463   {
464     EmuFileObject* o = g_emuFileWrapper.GetFileObjectByDescriptor(fd);
465     if (o)
466     {
467       if(!o->used)
468         return NULL;
469
470       int nmode = convert_fmode(mode);
471       if( (o->mode & nmode) != nmode)
472         CLog::Log(LOGWARNING, "dll_fdopen - mode 0x%x differs from fd mode 0x%x", nmode, o->mode);
473       return &o->file_emu;
474     }
475     else if (!IS_STD_DESCRIPTOR(fd))
476     {
477       // it might be something else than a file, or the file is not emulated
478       // let the operating system handle it
479       return _fdopen(fd, mode);
480     }
481
482     not_implement("msvcrt.dll incomplete function _fdopen(...) called\n");
483     return NULL;
484   }
485
486   int dll_open(const char* szFileName, int iMode)
487   {
488     char str[1024];
489     int size = sizeof(str);
490     // move to CFile classes
491     if (strncmp(szFileName, "\\Device\\Cdrom0", 14) == 0)
492     {
493       // replace "\\Device\\Cdrom0" with "D:"
494       strncpy(str, "D:", size);
495       if (size)
496       {
497         str[size-1] = '\0';
498         strncat(str, szFileName + 14, size - strlen(str));
499       }
500     }
501     else
502     {
503       strncpy(str, szFileName, size);
504       if (size)
505         str[size-1] = '\0';
506     }
507
508     CFile* pFile = new CFile();
509     bool bWrite = false;
510     if ((iMode & O_RDWR) || (iMode & O_WRONLY))
511       bWrite = true;
512     bool bOverwrite=false;
513     if ((iMode & _O_TRUNC) || (iMode & O_CREAT))
514       bOverwrite = true;
515     // currently always overwrites
516     bool bResult;
517
518     // We need to validate the path here as some calls from ie. libdvdnav
519     // or the python DLLs have malformed slashes on Win32
520     // (-> E:\test\VIDEO_TS/VIDEO_TS.BUP))
521     if (bWrite)
522       bResult = pFile->OpenForWrite(CUtil::ValidatePath(str), bOverwrite);
523     else
524       bResult = pFile->Open(CUtil::ValidatePath(str));
525
526     if (bResult)
527     {
528       EmuFileObject* object = g_emuFileWrapper.RegisterFileObject(pFile);
529       if (object == NULL)
530       {
531         pFile->Close();
532         delete pFile;
533         return -1;
534       }
535       object->mode = iMode;
536       return g_emuFileWrapper.GetDescriptorByStream(&object->file_emu);
537     }
538     delete pFile;
539     return -1;
540   }
541
542   FILE* dll_freopen(const char *path, const char *mode, FILE *stream)
543   {
544     if (g_emuFileWrapper.StreamIsEmulatedFile(stream))
545     {
546       dll_fclose(stream);
547       return dll_fopen(path, mode);
548     }
549     else if (!IS_STD_STREAM(stream))
550     {
551       // Translate the path
552       return freopen(CSpecialProtocol::TranslatePath(path).c_str(), mode, stream);
553     }
554
555     // error
556     // close stream and return NULL
557     dll_fclose(stream);
558     return NULL;
559   }
560
561
562   int dll_read(int fd, void* buffer, unsigned int uiSize)
563   {
564     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
565     if (pFile != NULL)
566     {
567        return pFile->Read(buffer, uiSize);
568     }
569     else if (!IS_STD_DESCRIPTOR(fd))
570     {
571       // it might be something else than a file, or the file is not emulated
572       // let the operating system handle it
573       return read(fd, buffer, uiSize);
574     }
575     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
576     return -1;
577   }
578
579   int dll_write(int fd, const void* buffer, unsigned int uiSize)
580   {
581     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
582     if (pFile != NULL)
583     {
584        return pFile->Write(buffer, uiSize);
585     }
586     else if (!IS_STD_DESCRIPTOR(fd))
587     {
588       // it might be something else than a file, or the file is not emulated
589       // let the operating system handle it
590       return write(fd, buffer, uiSize);
591     }
592     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
593     return -1;
594   }
595
596   int dll_fstat64(int fd, struct __stat64 *buf)
597   {
598     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
599     if (pFile != NULL)
600       return pFile->Stat(buf);
601     else if (IS_STD_DESCRIPTOR(fd))
602       return _fstat64(fd, buf);
603     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
604     return -1;
605   }
606
607   int dll_close(int fd)
608   {
609     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
610     if (pFile != NULL)
611     {
612       g_emuFileWrapper.UnRegisterFileObjectByDescriptor(fd);
613
614       pFile->Close();
615       delete pFile;
616       return 0;
617     }
618     else if (!IS_STD_DESCRIPTOR(fd))
619     {
620       // it might be something else than a file, or the file is not emulated
621       // let the operating system handle it
622       return close(fd);
623     }
624     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
625     return -1;
626   }
627
628   __off64_t dll_lseeki64(int fd, __off64_t lPos, int iWhence)
629   {
630     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
631     if (pFile != NULL)
632     {
633       lPos = pFile->Seek(lPos, iWhence);
634       return lPos;
635     }
636     else if (!IS_STD_DESCRIPTOR(fd))
637     {
638       // it might be something else than a file, or the file is not emulated
639       // let the operating system handle it
640       // not supported: return lseeki64(fd, lPos, iWhence);
641       CLog::Log(LOGWARNING, "msvcrt.dll: dll_lseeki64 called, TODO: add 'int64 -> long' type checking");      //warning
642       return (__int64)lseek(fd, (long)lPos, iWhence);
643     }
644     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
645     return (__int64)-1;
646   }
647
648   __off_t dll_lseek(int fd, __off_t lPos, int iWhence)
649   {
650     if (g_emuFileWrapper.DescriptorIsEmulatedFile(fd))
651     {
652       return (__off_t)dll_lseeki64(fd, (__off_t)lPos, iWhence);
653     }
654     else if (!IS_STD_DESCRIPTOR(fd))
655     {
656       // it might be something else than a file, or the file is not emulated
657       // let the operating system handle it
658       return lseek(fd, lPos, iWhence);
659     }
660     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
661     return -1;
662   }
663
664   void dll_rewind(FILE* stream)
665   {
666     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
667     if (fd >= 0)
668     {
669       dll_lseeki64(fd, 0, SEEK_SET);
670     }
671     else if (!IS_STD_STREAM(stream))
672     {
673       // it might be something else than a file, let the operating system handle it
674       rewind(stream);
675     }
676     else
677     {
678     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
679     }
680   }
681
682   //---------------------------------------------------------------------------------------------------------
683   void dll_flockfile(FILE *stream)
684   {
685     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
686     if (fd >= 0)
687     {
688       g_emuFileWrapper.LockFileObjectByDescriptor(fd);
689       return;
690     }
691     else if (!IS_STD_STREAM(stream))
692     {
693       // it might be something else than a file, let the operating system handle it
694 #ifdef TARGET_POSIX
695       flockfile(stream);
696       return;
697 #else
698       CLog::Log(LOGERROR, "%s: flockfile not available on non-linux platforms",  __FUNCTION__);
699 #endif
700     }
701     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
702   }
703
704   int dll_ftrylockfile(FILE *stream)
705   {
706     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
707     if (fd >= 0)
708     {
709       if (g_emuFileWrapper.TryLockFileObjectByDescriptor(fd))
710         return 0;
711       return -1;
712     }
713     else if (!IS_STD_STREAM(stream))
714     {
715       // it might be something else than a file, let the operating system handle it
716 #ifdef TARGET_POSIX
717       return ftrylockfile(stream);
718 #else
719       CLog::Log(LOGERROR, "%s: ftrylockfile not available on non-linux platforms",  __FUNCTION__);
720 #endif
721     }
722     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
723     return -1;
724   }
725
726   void dll_funlockfile(FILE *stream)
727   {
728     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
729     if (fd >= 0)
730     {
731       g_emuFileWrapper.UnlockFileObjectByDescriptor(fd);
732       return;
733     }
734     else if (!IS_STD_STREAM(stream))
735     {
736       // it might be something else than a file, let the operating system handle it
737 #ifdef TARGET_POSIX
738       funlockfile(stream);
739       return;
740 #else
741       CLog::Log(LOGERROR, "%s: funlockfile not available on non-linux platforms",  __FUNCTION__);
742 #endif
743     }
744     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
745   }
746
747   int dll_fclose(FILE * stream)
748   {
749     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
750     if (fd >= 0)
751     {
752       return dll_close(fd);
753     }
754     else if (!IS_STD_STREAM(stream))
755     {
756       // it might be something else than a file, let the operating system handle it
757       return fclose(stream);
758     }
759     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
760     return EOF;
761   }
762
763 #ifndef TARGET_POSIX
764   // should be moved to CFile classes
765   intptr_t dll_findfirst(const char *file, struct _finddata_t *data)
766   {
767     struct _finddata64i32_t data64i32;
768     intptr_t ret = dll_findfirst64i32(file, &data64i32);
769     if (ret != -1)
770     {
771       int size = sizeof(data->name);
772       strncpy(data->name, data64i32.name, size);
773       if (size)
774         data->name[size - 1] = '\0';
775       data->size = (_fsize_t)data64i32.size;
776       data->time_write = (time_t)data64i32.time_write;
777       data->time_access = (time_t)data64i32.time_access;
778     }
779     return ret;
780   }
781
782   intptr_t dll_findfirst64i32(const char *file, struct _finddata64i32_t *data)
783   {
784     char str[1024];
785     int size = sizeof(str);
786     CURL url(CSpecialProtocol::TranslatePath(file));
787     if (url.IsLocal())
788     {
789       // move to CFile classes
790       if (strncmp(file, "\\Device\\Cdrom0", 14) == 0)
791       {
792         // replace "\\Device\\Cdrom0" with "D:"
793         strncpy(str, "D:", size);
794         if (size)
795         {
796           str[size - 1] = '\0';
797           strncat(str, file + 14, size - strlen(str));
798         }
799       }
800       else
801       {
802         strncpy(str, file, size);
803         if (size)
804           str[size - 1] = '\0';
805       }
806
807       // Make sure the slashes are correct & translate the path
808       struct _wfinddata64i32_t wdata;
809       CStdStringW strwfile;
810       g_charsetConverter.utf8ToW(CUtil::ValidatePath(CSpecialProtocol::TranslatePath(str)), strwfile, false);
811       intptr_t ret = _wfindfirst64i32(strwfile.c_str(), &wdata);
812       if (ret != -1)
813         to_finddata64i32(&wdata, data);
814       return ret;
815     }
816     // non-local files. handle through IDirectory-class - only supports '*.bah' or '*.*'
817     CStdString strURL(file);
818     CStdString strMask;
819     if (url.GetFileName().Find("*.*") != string::npos)
820     {
821       CStdString strReplaced = url.GetFileName();
822       strReplaced.Replace("*.*","");
823       url.SetFileName(strReplaced);
824     }
825     else if (url.GetFileName().Find("*.") != string::npos)
826     {
827       strMask = URIUtils::GetExtension(url.GetFileName());
828       url.SetFileName(url.GetFileName().Left(url.GetFileName().Find("*.")));
829     }
830     else if (url.GetFileName().Find("*") != string::npos)
831     {
832       CStdString strReplaced = url.GetFileName();
833       strReplaced.Replace("*","");
834       url.SetFileName(strReplaced);
835     }
836     int iDirSlot=0; // locate next free directory
837     while ((vecDirsOpen[iDirSlot].curr_index != -1) && (iDirSlot<MAX_OPEN_DIRS)) iDirSlot++;
838     if (iDirSlot >= MAX_OPEN_DIRS)
839       return -1; // no free slots
840     if (url.GetProtocol().Equals("filereader"))
841     {
842       CURL url2(url.GetFileName());
843       url = url2;
844     }
845     strURL = url.Get();
846     bVecDirsInited = true;
847     vecDirsOpen[iDirSlot].items.Clear();
848     XFILE::CDirectory::GetDirectory(strURL, vecDirsOpen[iDirSlot].items, strMask);
849     if (vecDirsOpen[iDirSlot].items.Size())
850     {
851       int size = sizeof(data->name);
852       strncpy(data->name,vecDirsOpen[iDirSlot].items[0]->GetLabel().c_str(), size);
853       if (size)
854         data->name[size - 1] = '\0';
855       data->size = static_cast<_fsize_t>(vecDirsOpen[iDirSlot].items[0]->m_dwSize);
856       data->time_write = 0;
857       data->time_access = 0;
858       vecDirsOpen[iDirSlot].curr_index = 0;
859       return (intptr_t)&vecDirsOpen[iDirSlot];
860     }
861     vecDirsOpen[iDirSlot].curr_index = -1;
862     return -1; // whatever != NULL
863   }
864
865   // should be moved to CFile classes
866   int dll_findnext(intptr_t f, _finddata_t* data)
867   {
868     struct _finddata64i32_t data64i32;
869     int ret = dll_findnext64i32(f, &data64i32);
870     if (ret == 0)
871     {
872       int size = sizeof(data->name);
873       strncpy(data->name, data64i32.name, size);
874       if (size)
875         data->name[size - 1] = '\0';
876       data->size = (_fsize_t)data64i32.size;
877       data->time_write = (time_t)data64i32.time_write;
878       data->time_access = (time_t)data64i32.time_access;
879     }
880     return ret;
881   }
882
883   int dll_findnext64i32(intptr_t f, _finddata64i32_t* data)
884   {
885     int found = MAX_OPEN_DIRS;
886     for (int i = 0; i < MAX_OPEN_DIRS; i++)
887     {
888       if (f == (intptr_t)&vecDirsOpen[i] && vecDirsOpen[i].curr_index != -1)
889       {
890         found = i;
891         break;
892       }
893     }
894     if (found >= MAX_OPEN_DIRS)
895     {
896       struct _wfinddata64i32_t wdata;
897       to_wfinddata64i32(data, &wdata);
898       intptr_t ret = _wfindnext64i32(f, &wdata); // local dir
899       if (ret != -1)
900         to_finddata64i32(&wdata, data);
901       return ret;
902     }
903
904     // we have a valid data struture. get next item!
905     int iItem = vecDirsOpen[found].curr_index;
906     if (iItem+1 < vecDirsOpen[found].items.Size()) // we have a winner!
907     {
908       int size = sizeof(data->name);
909       strncpy(data->name,vecDirsOpen[found].items[iItem+1]->GetLabel().c_str(), size);
910       if (size)
911         data->name[size - 1] = '\0';
912       data->size = static_cast<_fsize_t>(vecDirsOpen[found].items[iItem+1]->m_dwSize);
913       vecDirsOpen[found].curr_index++;
914       return 0;
915     }
916
917     vecDirsOpen[found].items.Clear();
918     return -1;
919   }
920
921   int dll_findclose(intptr_t handle)
922   {
923     int found = MAX_OPEN_DIRS;
924     for (int i = 0; i < MAX_OPEN_DIRS; i++)
925     {
926       if (handle == (intptr_t)&vecDirsOpen[i] && vecDirsOpen[i].curr_index != -1)
927       {
928         found = i;
929         break;
930       }
931     }
932     if (found >= MAX_OPEN_DIRS)
933       return _findclose(handle);
934
935     vecDirsOpen[found].items.Clear();
936     vecDirsOpen[found].curr_index = -1;
937     return 0;
938   }
939
940   void dll__security_error_handler(int code, void *data)
941   {
942     //NOTE: __security_error_handler has been removed in VS2005 and up
943     CLog::Log(LOGERROR, "security_error, code %i", code);
944   }
945
946 #endif
947
948   DIR *dll_opendir(const char *file)
949   {
950     CURL url(CSpecialProtocol::TranslatePath(file));
951     if (url.IsLocal())
952     { // Make sure the slashes are correct & translate the path
953       return opendir(CUtil::ValidatePath(url.Get().c_str()));
954     }
955
956     // locate next free directory
957     int iDirSlot=0;
958     while ((iDirSlot<MAX_OPEN_DIRS) && (vecDirsOpen[iDirSlot].curr_index != -1)) iDirSlot++;
959     if (iDirSlot >= MAX_OPEN_DIRS)
960     {
961       CLog::Log(LOGDEBUG, "Dll: Max open dirs reached");
962       return NULL; // no free slots
963     }
964
965     if (url.GetProtocol().Equals("filereader"))
966     {
967       CURL url2(url.GetFileName());
968       url = url2;
969     }
970
971     bVecDirsInited = true;
972     vecDirsOpen[iDirSlot].items.Clear();
973
974     if (XFILE::CDirectory::GetDirectory(url.Get(), vecDirsOpen[iDirSlot].items))
975     {
976       vecDirsOpen[iDirSlot].curr_index = 0;
977       return (DIR *)&vecDirsOpen[iDirSlot];
978     }
979     else
980       return NULL;
981   }
982
983   struct dirent *dll_readdir(DIR *dirp)
984   {
985     if (!dirp)
986       return NULL;
987
988     bool emulated(false);
989     for (int i = 0; i < MAX_OPEN_DIRS; i++)
990     {
991       if (dirp == (DIR*)&vecDirsOpen[i])
992       {
993         emulated = true;
994         break;
995       }
996     }
997     if (!emulated)
998       return readdir(dirp); // local dir
999
1000     // dirp is actually a SDirData*
1001     SDirData* dirData = (SDirData*)dirp;
1002     if (dirData->last_entry)
1003       free(dirData->last_entry);
1004     struct dirent *entry = NULL;
1005     entry = (dirent*) malloc(sizeof(*entry));
1006     if (dirData->curr_index < dirData->items.Size() + 2)
1007     { // simulate the '.' and '..' dir entries
1008       if (dirData->curr_index == 0)
1009         strncpy(entry->d_name, ".\0", 2);
1010       else if (dirData->curr_index == 1)
1011         strncpy(entry->d_name, "..\0", 3);
1012       else
1013       {
1014         strncpy(entry->d_name, dirData->items[dirData->curr_index - 2]->GetLabel().c_str(), sizeof(entry->d_name));
1015         entry->d_name[sizeof(entry->d_name)-1] = '\0'; // null-terminate any truncated paths
1016       }
1017       dirData->last_entry = entry;
1018       dirData->curr_index++;
1019       return entry;
1020     }
1021     free(entry);
1022     return NULL;
1023   }
1024
1025   int dll_closedir(DIR *dirp)
1026   {
1027     bool emulated(false);
1028     for (int i = 0; i < MAX_OPEN_DIRS; i++)
1029     {
1030       if (dirp == (DIR*)&vecDirsOpen[i])
1031       {
1032         emulated = true;
1033         break;
1034       }
1035     }
1036     if (!emulated)
1037       return closedir(dirp);
1038
1039     SDirData* dirData = (SDirData*)dirp;
1040     dirData->items.Clear();
1041     if (dirData->last_entry)
1042     {
1043       dirData->last_entry = NULL;
1044     }
1045     dirData->curr_index = -1;
1046     return 0;
1047   }
1048
1049   void dll_rewinddir(DIR *dirp)
1050   {
1051     bool emulated(false);
1052     for (int i = 0; i < MAX_OPEN_DIRS; i++)
1053     {
1054       if (dirp == (DIR*)&vecDirsOpen[i])
1055       {
1056         emulated = true;
1057         break;
1058       }
1059     }
1060     if (!emulated)
1061     {
1062       rewinddir(dirp);
1063       return;
1064     }
1065
1066     SDirData* dirData = (SDirData*)dirp;
1067     if (dirData->last_entry)
1068     {
1069       dirData->last_entry = NULL;
1070     }
1071     dirData->curr_index = 0;
1072   }
1073
1074   char* dll_fgets(char* pszString, int num ,FILE * stream)
1075   {
1076     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream);
1077     if (pFile != NULL)
1078     {
1079       if (pFile->GetPosition() < pFile->GetLength())
1080       {
1081         bool bRead = pFile->ReadString(pszString, num);
1082         if (bRead)
1083         {
1084           return pszString;
1085         }
1086       }
1087       else return NULL; //eof
1088     }
1089     else if (!IS_STD_STREAM(stream))
1090     {
1091       // it might be something else than a file, or the file is not emulated
1092       // let the operating system handle it
1093       return fgets(pszString, num, stream);
1094     }
1095     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1096     return NULL;
1097   }
1098
1099   int dll_feof(FILE * stream)
1100   {
1101     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream);
1102     if (pFile != NULL)
1103     {
1104       if (pFile->GetPosition() < pFile->GetLength()) return 0;
1105       else return 1;
1106     }
1107     else if (!IS_STD_STREAM(stream))
1108     {
1109       // it might be something else than a file, or the file is not emulated
1110       // let the operating system handle it
1111       return feof(stream);
1112     }
1113     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1114     return 1; // eof by default
1115   }
1116
1117   int dll_fread(void * buffer, size_t size, size_t count, FILE * stream)
1118   {
1119     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
1120     if (fd >= 0)
1121     {
1122       int iItemsRead = dll_read(fd, buffer, count * size);
1123       if (iItemsRead >= 0)
1124       {
1125         if (size)
1126           iItemsRead /= size;
1127         return iItemsRead;
1128       }
1129     }
1130     else if (!IS_STD_STREAM(stream))
1131     {
1132       // it might be something else than a file, let the operating system handle it
1133       return fread(buffer, size, count, stream);
1134     }
1135     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1136     return -1;
1137   }
1138
1139   int dll_fgetc(FILE* stream)
1140   {
1141     if (g_emuFileWrapper.StreamIsEmulatedFile(stream))
1142     {
1143       // it is a emulated file
1144       unsigned char buf;
1145
1146       if (dll_fread(&buf, 1, 1, stream) <= 0)
1147         return EOF;
1148
1149       return (int)buf;
1150     }
1151     else if (!IS_STD_STREAM(stream))
1152     {
1153       // it might be something else than a file, or the file is not emulated
1154       // let the operating system handle it
1155       return getc(stream);
1156     }
1157     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1158     return EOF;
1159   }
1160
1161   int dll_getc(FILE* stream)
1162   {
1163     if (g_emuFileWrapper.StreamIsEmulatedFile(stream))
1164     {
1165       // This routine is normally implemented as a macro with the same result as fgetc().
1166       return dll_fgetc(stream);
1167     }
1168     else if (!IS_STD_STREAM(stream))
1169     {
1170       // it might be something else than a file, or the file is not emulated
1171       // let the operating system handle it
1172       return getc(stream);
1173     }
1174     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1175     return EOF;
1176   }
1177
1178   FILE* dll_fopen(const char* filename, const char* mode)
1179   {
1180     FILE* file = NULL;
1181 #if defined(TARGET_LINUX) && !defined(TARGET_ANDROID)
1182     if (strcmp(filename, MOUNTED) == 0
1183     ||  strcmp(filename, MNTTAB) == 0)
1184     {
1185       CLog::Log(LOGINFO, "%s - something opened the mount file, let's hope it knows what it's doing", __FUNCTION__);
1186       return fopen(filename, mode);
1187     }
1188 #endif
1189     int fd = dll_open(filename, convert_fmode(mode));
1190     if (fd >= 0)
1191     {
1192       file = g_emuFileWrapper.GetStreamByDescriptor(fd);;
1193     }
1194
1195     return file;
1196   }
1197
1198   int dll_putc(int c, FILE *stream)
1199   {
1200     if (g_emuFileWrapper.StreamIsEmulatedFile(stream) || IS_STD_STREAM(stream))
1201     {
1202       return dll_fputc(c, stream);
1203     }
1204     else
1205     {
1206       return putc(c, stream);
1207     }
1208     return EOF;
1209   }
1210
1211   int dll_putchar(int c)
1212   {
1213     return dll_putc(c, stdout);
1214   }
1215
1216   int dll_fputc(int character, FILE* stream)
1217   {
1218     if (IS_STDOUT_STREAM(stream) || IS_STDERR_STREAM(stream))
1219     {
1220       char tmp[2] = { (char)character, 0 };
1221       dllputs(tmp);
1222       return character;
1223     }
1224     else
1225     {
1226       if (g_emuFileWrapper.StreamIsEmulatedFile(stream))
1227       {
1228         int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
1229         if (fd >= 0)
1230         {
1231           int iItemsWritten = dll_write(fd, (char* )&character, 1);
1232           if (iItemsWritten == 1)
1233             return character;
1234         }
1235       }
1236       else if (!IS_STD_STREAM(stream))
1237       {
1238         // it might be something else than a file, or the file is not emulated
1239         // let the operating system handle it
1240         return fputc(character, stream);
1241       }
1242     }
1243     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1244     return EOF;
1245   }
1246
1247   int dll_fputs(const char * szLine, FILE* stream)
1248   {
1249     if (IS_STDOUT_STREAM(stream) || IS_STDERR_STREAM(stream))
1250     {
1251       dllputs(szLine);
1252       return 0;
1253     }
1254     else
1255     {
1256       if (g_emuFileWrapper.StreamIsEmulatedFile(stream))
1257       {
1258         not_implement("msvcrt.dll fake function dll_fputs() called\n");
1259       }
1260       else if (!IS_STD_STREAM(stream))
1261       {
1262         // it might be something else than a file, or the file is not emulated
1263         // let the operating system handle it
1264         return fputs(szLine, stream);
1265       }
1266     }
1267
1268     OutputDebugString(szLine);
1269     OutputDebugString("\n");
1270     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1271     return EOF;
1272   }
1273
1274   int dll_fseek64(FILE* stream, off64_t offset, int origin)
1275   {
1276     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
1277     if (fd >= 0)
1278     {
1279       if (dll_lseeki64(fd, offset, origin) != -1)
1280       {
1281         return 0;
1282       }
1283       else return -1;
1284     }
1285     else if (!IS_STD_STREAM(stream))
1286     {
1287       // it might be something else than a file, or the file is not emulated
1288       // let the operating system handle it
1289 #if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1290       return fseek(stream, offset, origin);
1291 #else
1292       return fseeko64(stream, offset, origin);
1293 #endif
1294     }
1295     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1296     return -1;
1297   }
1298
1299   int dll_fseek(FILE *stream, long offset, int origin)
1300   {
1301     return dll_fseek64(stream, offset, origin);
1302   }
1303
1304   int dll_ungetc(int c, FILE* stream)
1305   {
1306     if (g_emuFileWrapper.StreamIsEmulatedFile(stream))
1307     {
1308       // it is a emulated file
1309       int d;
1310       if (dll_fseek(stream, -1, SEEK_CUR)!=0)
1311         return -1;
1312       d = dll_fgetc(stream);
1313       if (d == EOF)
1314         return -1;
1315
1316       dll_fseek(stream, -1, SEEK_CUR);
1317       if (c != d)
1318       {
1319         CLog::Log(LOGWARNING, "%s: c != d",  __FUNCTION__);
1320         d = fputc(c, stream);
1321         if (d != c)
1322           CLog::Log(LOGERROR, "%s: Write failed!",  __FUNCTION__);
1323         else
1324           dll_fseek(stream, -1, SEEK_CUR);
1325       }
1326       return d;
1327     }
1328     else if (!IS_STD_STREAM(stream))
1329     {
1330       // it might be something else than a file, or the file is not emulated
1331       // let the operating system handle it
1332       return ungetc(c, stream);
1333     }
1334     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1335     return EOF;
1336   }
1337
1338   long dll_ftell(FILE *stream)
1339   {
1340     return (long)dll_ftell64(stream);
1341   }
1342
1343   off64_t dll_ftell64(FILE *stream)
1344   {
1345     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream);
1346     if (pFile != NULL)
1347     {
1348        return (off64_t)pFile->GetPosition();
1349     }
1350     else if (!IS_STD_STREAM(stream))
1351     {
1352       // it might be something else than a file, or the file is not emulated
1353       // let the operating system handle it
1354 #if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1355       return ftello(stream);
1356 #else
1357       return ftello64(stream);
1358 #endif
1359     }
1360     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1361     return -1;
1362   }
1363
1364   long dll_tell(int fd)
1365   {
1366     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
1367     if (pFile != NULL)
1368     {
1369        return (long)pFile->GetPosition();
1370     }
1371     else if (!IS_STD_DESCRIPTOR(fd))
1372     {
1373       // it might be something else than a file, or the file is not emulated
1374       // let the operating system handle it
1375 #ifndef TARGET_POSIX
1376       return tell(fd);
1377 #else
1378       return lseek(fd, 0, SEEK_CUR);
1379 #endif
1380     }
1381     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1382     return -1;
1383   }
1384
1385   __int64 dll_telli64(int fd)
1386   {
1387     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
1388     if (pFile != NULL)
1389     {
1390        return (__int64)pFile->GetPosition();
1391     }
1392     else if (!IS_STD_DESCRIPTOR(fd))
1393     {
1394       // it might be something else than a file, or the file is not emulated
1395       // let the operating system handle it
1396       // not supported return telli64(fd);
1397       CLog::Log(LOGWARNING, "msvcrt.dll: dll_telli64 called, TODO: add 'int64 -> long' type checking");      //warning
1398 #ifndef TARGET_POSIX
1399       return (__int64)tell(fd);
1400 #elif defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1401       return lseek(fd, 0, SEEK_CUR);
1402 #else
1403       return lseek64(fd, 0, SEEK_CUR);
1404 #endif
1405     }
1406     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1407     return -1;
1408   }
1409
1410   size_t dll_fwrite(const void * buffer, size_t size, size_t count, FILE* stream)
1411   {
1412     if (IS_STDOUT_STREAM(stream) || IS_STDERR_STREAM(stream))
1413     {
1414       char* buf = (char*)malloc(size * count + 1);
1415       if (buf)
1416       {
1417         memcpy(buf, buffer, size * count);
1418         buf[size * count] = 0; // string termination
1419
1420         CLog::Log(LOGDEBUG, "%s", buf);
1421
1422         free(buf);
1423         return count;
1424       }
1425     }
1426     else
1427     {
1428       int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
1429       if (fd >= 0)
1430       {
1431         int iItemsWritten = dll_write(fd, buffer, count * size);
1432         if (iItemsWritten >= 0)
1433         {
1434           iItemsWritten /= size;
1435           return iItemsWritten;
1436         }
1437       }
1438       else if (!IS_STD_STREAM(stream))
1439       {
1440         // it might be something else than a file, or the file is not emulated
1441         // let the operating system handle it
1442         return fwrite(buffer, size, count, stream);
1443       }
1444     }
1445     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1446     return -1;
1447   }
1448
1449   int dll_fflush(FILE* stream)
1450   {
1451     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream);
1452     if (pFile != NULL)
1453     {
1454       pFile->Flush();
1455       return 0;
1456     }
1457     else if (!IS_STD_STREAM(stream))
1458     {
1459       // it might be something else than a file, or the file is not emulated
1460       // let the operating system handle it
1461       return fflush(stream);
1462     }
1463
1464     // std stream, no need to flush
1465     return 0;
1466   }
1467
1468   int dll_ferror(FILE* stream)
1469   {
1470     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream);
1471     if (pFile != NULL)
1472     {
1473       // unimplemented
1474       return 0;
1475     }
1476     else if (IS_STD_STREAM(stream))
1477       return 0;
1478     else
1479       return ferror(stream);
1480   }
1481
1482   int dllvprintf(const char *format, va_list va)
1483   {
1484     CStdString buffer;
1485     buffer.FormatV(format, va);
1486     CLog::Log(LOGDEBUG, "  msg: %s", buffer.c_str());
1487     return buffer.length();
1488   }
1489
1490   int dll_vfprintf(FILE *stream, const char *format, va_list va)
1491   {
1492     static char tmp[2048];
1493
1494     if (_vsnprintf(tmp, 2048, format, va) == -1)
1495     {
1496       CLog::Log(LOGWARNING, "dll_vfprintf: Data lost due to undersized buffer");
1497     }
1498     tmp[2048 - 1] = 0;
1499
1500     if (IS_STDOUT_STREAM(stream) || IS_STDERR_STREAM(stream))
1501     {
1502       CLog::Log(LOGINFO, "  msg: %s", tmp);
1503       return strlen(tmp);
1504     }
1505     else
1506     {
1507       CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream);
1508       if (pFile != NULL)
1509       {
1510         int len = strlen(tmp);
1511         // replace all '\n' occurences with '\r\n'...
1512         char tmp2[2048];
1513         int j = 0;
1514         for (int i = 0; i < len; i++)
1515         {
1516           if (j == 2047)
1517           { // out of space
1518             if (i != len-1)
1519               CLog::Log(LOGWARNING, "dll_fprintf: Data lost due to undersized buffer");
1520             break;
1521           }
1522           if (tmp[i] == '\n' && ((i > 0 && tmp[i-1] != '\r') || i == 0) && j < 2047 - 2)
1523           { // need to add a \r
1524             tmp2[j++] = '\r';
1525             tmp2[j++] = '\n';
1526           }
1527           else
1528           { // just add the character as-is
1529             tmp2[j++] = tmp[i];
1530           }
1531         }
1532         // terminate string
1533         tmp2[j] = 0;
1534         len = strlen(tmp2);
1535         pFile->Write(tmp2, len);
1536         return len;
1537       }
1538       else if (!IS_STD_STREAM(stream) && IS_VALID_STREAM(stream))
1539       {
1540         // it might be something else than a file, or the file is not emulated
1541         // let the operating system handle it
1542         return vfprintf(stream, format, va);
1543       }
1544     }
1545
1546     OutputDebugString(tmp);
1547     OutputDebugString("\n");
1548     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1549     return strlen(tmp);
1550   }
1551
1552   int dll_fscanf(FILE* stream, const char* format, ...)
1553   {
1554     CLog::Log(LOGERROR, "%s is not implemented",  __FUNCTION__);
1555     return -1;
1556   }
1557
1558   int dll_fprintf(FILE* stream, const char* format, ...)
1559   {
1560     int res;
1561     va_list va;
1562     va_start(va, format);
1563     res = dll_vfprintf(stream, format, va);
1564     va_end(va);
1565     return res;
1566   }
1567
1568   int dll_fgetpos(FILE* stream, fpos_t* pos)
1569   {
1570     fpos64_t tmpPos;
1571     int ret;
1572
1573     ret = dll_fgetpos64(stream, &tmpPos);
1574 #if !defined(TARGET_POSIX) || defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1575     *pos = (fpos_t)tmpPos;
1576 #else
1577     pos->__pos = (off_t)tmpPos.__pos;
1578 #endif
1579     return ret;
1580   }
1581
1582   int dll_fgetpos64(FILE *stream, fpos64_t *pos)
1583   {
1584     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream);
1585     if (pFile != NULL)
1586     {
1587 #if !defined(TARGET_POSIX) || defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1588       *pos = pFile->GetPosition();
1589 #else
1590       pos->__pos = pFile->GetPosition();
1591 #endif
1592       return 0;
1593     }
1594     else if (!IS_STD_STREAM(stream))
1595     {
1596       // it might be something else than a file, or the file is not emulated
1597       // let the operating system handle it
1598       return fgetpos(stream, pos);
1599     }
1600     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1601     return EINVAL;
1602   }
1603
1604   int dll_fsetpos64(FILE* stream, const fpos64_t* pos)
1605   {
1606     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
1607     if (fd >= 0)
1608     {
1609 #if !defined(TARGET_POSIX) || defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1610       if (dll_lseeki64(fd, *pos, SEEK_SET) >= 0)
1611 #else
1612       if (dll_lseeki64(fd, (__off64_t)pos->__pos, SEEK_SET) >= 0)
1613 #endif
1614       {
1615         return 0;
1616       }
1617       else
1618       {
1619         return EINVAL;
1620       }
1621     }
1622     else if (!IS_STD_STREAM(stream))
1623     {
1624       // it might be something else than a file, or the file is not emulated
1625       // let the operating system handle it
1626 #if !defined(TARGET_POSIX) || defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1627       return fsetpos(stream, pos);
1628 #else
1629       return fsetpos64(stream, pos);
1630 #endif
1631     }
1632     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1633     return EINVAL;
1634   }
1635
1636   int dll_fsetpos(FILE* stream, const fpos_t* pos)
1637   {
1638     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
1639     if (fd >= 0)
1640     {
1641       fpos64_t tmpPos;
1642 #if !defined(TARGET_POSIX) || defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) || defined(TARGET_ANDROID)
1643       tmpPos= *pos;
1644 #else
1645       tmpPos.__pos = (off64_t)(pos->__pos);
1646 #endif
1647       return dll_fsetpos64(stream, &tmpPos);
1648     }
1649     else if (!IS_STD_STREAM(stream))
1650     {
1651       // it might be something else than a file, or the file is not emulated
1652       // let the operating system handle it
1653       return fsetpos(stream, (fpos_t*)pos);
1654     }
1655     CLog::Log(LOGERROR, "%s emulated function failed",  __FUNCTION__);
1656     return EINVAL;
1657   }
1658
1659   int dll_fileno(FILE* stream)
1660   {
1661     int fd = g_emuFileWrapper.GetDescriptorByStream(stream);
1662     if (fd >= 0)
1663     {
1664       return fd;
1665     }
1666     else if (IS_STDIN_STREAM(stream))
1667     {
1668       return 0;
1669     }
1670     else if (IS_STDOUT_STREAM(stream))
1671     {
1672       return 1;
1673     }
1674     else if (IS_STDERR_STREAM(stream))
1675     {
1676       return 2;
1677     }
1678     else
1679     {
1680       return fileno(stream);
1681     }
1682
1683     return -1;
1684   }
1685
1686   void dll_clearerr(FILE* stream)
1687   {
1688     if (g_emuFileWrapper.StreamIsEmulatedFile(stream))
1689     {
1690       // not implemented
1691     }
1692     else if (!IS_STD_STREAM(stream))
1693     {
1694       return clearerr(stream);
1695     }
1696   }
1697
1698   char* dll_strdup( const char* str)
1699   {
1700     char* pdup;
1701     pdup = strdup(str);
1702     return pdup;
1703   }
1704
1705
1706   //Critical Section has been fixed in EMUkernel32.cpp
1707
1708   int dll_initterm(PFV * start, PFV * end)        //pncrt.dll
1709   {
1710     PFV * temp;
1711     for (temp = start; temp < end; temp ++)
1712       if (*temp)
1713         (*temp)(); //call initial function table.
1714     return 0;
1715   }
1716
1717   //SLOW CODE SHOULD BE REVISED
1718   int dll_stat(const char *path, struct stat *buffer)
1719   {
1720     if (!strnicmp(path, "shout://", 8)) // don't stat shoutcast
1721       return -1;
1722     if (!strnicmp(path, "http://", 7)
1723     ||  !strnicmp(path, "https://", 8)) // don't stat http
1724       return -1;
1725     if (!strnicmp(path, "mms://", 6)) // don't stat mms
1726       return -1;
1727
1728 #ifdef TARGET_POSIX
1729     if (!_stricmp(path, "D:") || !_stricmp(path, "D:\\"))
1730     {
1731       buffer->st_mode = S_IFDIR;
1732       return 0;
1733     }
1734 #endif
1735     if (!stricmp(path, "\\Device\\Cdrom0") || !stricmp(path, "\\Device\\Cdrom0\\"))
1736     {
1737       buffer->st_mode = _S_IFDIR;
1738       return 0;
1739     }
1740
1741     struct __stat64 tStat;
1742     if (CFile::Stat(path, &tStat) == 0)
1743     {
1744       CUtil::Stat64ToStat(buffer, &tStat);
1745       return 0;
1746     }
1747     // errno is set by file.Stat(...)
1748     return -1;
1749   }
1750
1751   int dll_stati64(const char *path, struct _stati64 *buffer)
1752   {
1753     struct __stat64 a;
1754     memset(&a, 0, sizeof(a));
1755
1756     if(dll_stat64(path, &a) == 0)
1757     {
1758       CUtil::Stat64ToStatI64(buffer, &a);
1759       return 0;
1760     }
1761     return -1;
1762   }
1763
1764   int dll_stat64(const char *path, struct __stat64 *buffer)
1765   {
1766     if (!strnicmp(path, "shout://", 8)) // don't stat shoutcast
1767       return -1;
1768     if (!strnicmp(path, "http://", 7)
1769     ||  !strnicmp(path, "https://", 8)) // don't stat http
1770       return -1;
1771     if (!strnicmp(path, "mms://", 6)) // don't stat mms
1772       return -1;
1773
1774 #ifdef TARGET_POSIX
1775     if (!_stricmp(path, "D:") || !_stricmp(path, "D:\\"))
1776     {
1777       buffer->st_mode = _S_IFDIR;
1778       return 0;
1779     }
1780 #endif
1781     if (!stricmp(path, "\\Device\\Cdrom0") || !stricmp(path, "\\Device\\Cdrom0\\"))
1782     {
1783       buffer->st_mode = _S_IFDIR;
1784       return 0;
1785     }
1786
1787     return CFile::Stat(path, buffer);
1788   }
1789
1790 #ifdef TARGET_WINDOWS
1791   int dll_stat64i32(const char *path, struct _stat64i32 *buffer)
1792   {
1793     struct __stat64 a;
1794     if(dll_stat64(path, &a) == 0)
1795     {
1796       CUtil::Stat64ToStat64i32(buffer, &a);
1797       return 0;
1798     }
1799     return -1;
1800   }
1801 #endif
1802
1803   int dll_fstat(int fd, struct stat* buffer)
1804   {
1805     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
1806     if (pFile != NULL)
1807     {
1808       struct __stat64 tStat;
1809       if (pFile->Stat(&tStat) == 0)
1810       {
1811         CUtil::Stat64ToStat(buffer, &tStat);
1812         return 0;
1813       }
1814     }
1815     else if (!IS_STD_DESCRIPTOR(fd))
1816     {
1817       return fstat(fd, buffer);
1818     }
1819
1820     // fstat on stdin, stdout or stderr should fail
1821     // this is what python expects
1822     return -1;
1823   }
1824
1825   int dll_fstati64(int fd, struct _stati64 *buffer)
1826   {
1827     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
1828     if (pFile != NULL)
1829     {
1830       CLog::Log(LOGINFO, "Stating open file");
1831
1832       buffer->st_size = pFile->GetLength();
1833       buffer->st_mode = _S_IFREG;
1834       return 0;
1835     }
1836     else if (!IS_STD_DESCRIPTOR(fd))
1837     {
1838       CLog::Log(LOGWARNING, "msvcrt.dll: dll_fstati64 called, TODO: add 'int64 <-> long' type checking");      //warning
1839       // need to use fstat and convert everything
1840       struct stat temp;
1841       int res = fstat(fd, &temp);
1842       if (res == 0)
1843       {
1844         CUtil::StatToStatI64(buffer, &temp);
1845       }
1846       return res;
1847     }
1848
1849     // fstat on stdin, stdout or stderr should fail
1850     // this is what python expects
1851     return -1;
1852   }
1853
1854 #ifdef TARGET_WINDOWS
1855   int dll_fstat64i32(int fd, struct _stat64i32 *buffer)
1856   {
1857     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
1858     if (pFile != NULL)
1859     {
1860       struct __stat64 tStat = {};
1861       if (pFile->Stat(&tStat) == 0)
1862       {
1863         CUtil::Stat64ToStat64i32(buffer, &tStat);
1864         return 0;
1865       }
1866       return -1;
1867     }
1868     else if (!IS_STD_DESCRIPTOR(fd))
1869     {
1870       CLog::Log(LOGWARNING, "msvcrt.dll: dll_fstati64 called, TODO: add 'int64 <-> long' type checking");      //warning
1871       // need to use fstat and convert everything
1872       struct __stat64 temp;
1873       int res = _fstat64(fd, &temp);
1874       if (res == 0)
1875       {
1876         CUtil::Stat64ToStat64i32(buffer, &temp);
1877       }
1878       return res;
1879     }
1880
1881     // fstat on stdin, stdout or stderr should fail
1882     // this is what python expects
1883     return -1;
1884   }
1885 #endif
1886
1887   int dll_setmode ( int handle, int mode )
1888   {
1889     not_implement("msvcrt.dll fake function dll_setmode() called\n");
1890     return -1;
1891   }
1892
1893   void dllperror(const char* s)
1894   {
1895     if (s)
1896     {
1897       CLog::Log(LOGERROR, "perror: %s", s);
1898     }
1899   }
1900
1901   char* dllstrerror(int iErr)
1902   {
1903     static char szError[32];
1904     sprintf(szError, "err:%i", iErr);
1905     return (char*)szError;
1906   }
1907
1908   int dll_mkdir(const char* dir)
1909   {
1910     if (!dir) return -1;
1911
1912     // Make sure the slashes are correct & translate the path
1913     CStdString strPath = CUtil::ValidatePath(CSpecialProtocol::TranslatePath(dir));
1914 #ifndef TARGET_POSIX
1915     CStdStringW strWPath;
1916     g_charsetConverter.utf8ToW(strPath, strWPath, false);
1917     return _wmkdir(strWPath.c_str());
1918 #else
1919     return mkdir(strPath.c_str(), 0755);
1920 #endif
1921   }
1922
1923   char* dll_getcwd(char *buffer, int maxlen)
1924   {
1925     not_implement("msvcrt.dll fake function dll_getcwd() called\n");
1926     return (char*)"special://xbmc/";
1927   }
1928
1929   int dll_putenv(const char* envstring)
1930   {
1931     bool added = false;
1932
1933     if (envstring != NULL)
1934     {
1935       const char *value_start = strchr(envstring, '=');
1936
1937       if (value_start != NULL)
1938       {
1939         char var[64];
1940         int size = strlen(envstring) + 1;
1941         char *value = (char*)malloc(size);
1942
1943         if (!value)
1944           return -1;
1945         value[0] = 0;
1946
1947         memcpy(var, envstring, value_start - envstring);
1948         var[value_start - envstring] = 0;
1949         char* temp = var;
1950         while (*temp)
1951         {
1952           *temp = (char)toupper(*temp);
1953           temp++;
1954         }
1955
1956         strncpy(value, value_start + 1, size);
1957         if (size)
1958           value[size - 1] = '\0';
1959
1960         {
1961           CSingleLock lock(dll_cs_environ);
1962
1963           char** free_position = NULL;
1964           for (int i = 0; i < EMU_MAX_ENVIRONMENT_ITEMS && free_position == NULL; i++)
1965           {
1966             if (dll__environ[i] != NULL)
1967             {
1968               // we only support overwriting the old values
1969               if (strnicmp(dll__environ[i], var, strlen(var)) == 0)
1970               {
1971                 // free it first
1972                 free(dll__environ[i]);
1973                 dll__environ[i] = NULL;
1974                 free_position = &dll__environ[i];
1975               }
1976             }
1977             else
1978             {
1979               free_position = &dll__environ[i];
1980             }
1981           }
1982
1983           if (free_position != NULL)
1984           {
1985             // free position, copy value
1986             size = strlen(var) + strlen(value) + 2;
1987             *free_position = (char*)malloc(size); // for '=' and 0 termination
1988             if ((*free_position))
1989             {
1990               strncpy(*free_position, var, size);
1991               (*free_position)[size - 1] = '\0';
1992               strncat(*free_position, "=", size - strlen(*free_position));
1993               strncat(*free_position, value, size - strlen(*free_position));
1994               added = true;
1995             }
1996           }
1997
1998         }
1999
2000         free(value);
2001       }
2002     }
2003
2004     return added ? 0 : -1;
2005   }
2006
2007
2008
2009   char* dll_getenv(const char* szKey)
2010   {
2011     char* value = NULL;
2012
2013     {
2014       CSingleLock lock(dll_cs_environ);
2015
2016       update_emu_environ();//apply any changes
2017
2018       for (int i = 0; i < EMU_MAX_ENVIRONMENT_ITEMS && value == NULL; i++)
2019       {
2020         if (dll__environ[i])
2021         {
2022           if (strnicmp(dll__environ[i], szKey, strlen(szKey)) == 0)
2023           {
2024             // found it
2025             value = dll__environ[i] + strlen(szKey) + 1;
2026           }
2027         }
2028       }
2029     }
2030
2031     if (value != NULL)
2032     {
2033       return value;
2034     }
2035
2036     return NULL;
2037   }
2038
2039   int dll_ctype(int i)
2040   {
2041     not_implement("msvcrt.dll fake function dll_ctype() called\n");
2042     return 0;
2043   }
2044
2045   int dll_system(const char *command)
2046   {
2047     not_implement("msvcrt.dll fake function dll_system() called\n");
2048     return 0; //system(command);
2049   }
2050
2051   void (__cdecl * dll_signal(int sig, void (__cdecl *func)(int)))(int)
2052   {
2053 #if defined(TARGET_WINDOWS)
2054     //vs2008 asserts for known signals, return err for everything unknown to windows.
2055     if (sig == 5 || sig == 7 || sig == 9 || sig == 10 || sig == 12 || sig == 14 || sig == 18 || sig == 19 || sig == 20)
2056       return SIG_ERR;
2057 #endif
2058     return signal(sig, func);
2059   }
2060
2061   int dll_getpid()
2062   {
2063     return 1;
2064   }
2065
2066   int dll__commit(int fd)
2067   {
2068     CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
2069     if (pFile != NULL)
2070     {
2071       pFile->Flush();
2072       return 0;
2073     }
2074     else if (!IS_STD_DESCRIPTOR(fd))
2075     {
2076       // it might be something else than a file, or the file is not emulated
2077       // let the operating system handle it
2078 #ifndef TARGET_POSIX
2079       return _commit(fd);
2080 #else
2081       return fsync(fd);
2082 #endif
2083     }
2084
2085     // std stream, no need to flush
2086     return 0;
2087   }
2088
2089   char*** dll___p__environ()
2090   {
2091     static char*** t = (char***)&dll__environ;
2092     return (char***)&t;
2093   }
2094
2095 #ifdef TARGET_POSIX
2096 #if defined(TARGET_ANDROID)
2097   volatile int * __cdecl dll_errno(void)
2098   {
2099     return &errno;
2100   }
2101 #else
2102   int * __cdecl dll_errno(void)
2103   {
2104     return &errno;
2105   }
2106 #endif
2107
2108   int __cdecl dll_ioctl(int fd, unsigned long int request, va_list va)
2109   {
2110      int ret;
2111      CFile* pFile = g_emuFileWrapper.GetFileXbmcByDescriptor(fd);
2112      if (!pFile)
2113        return -1;
2114
2115 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_FREEBSD)
2116 #if !defined(TARGET_DARWIN)
2117     if(request == DVD_READ_STRUCT || request == DVD_AUTH)
2118 #else
2119     if(request == DKIOCDVDSENDKEY || request == DKIOCDVDREPORTKEY || request == DKIOCDVDREADSTRUCTURE)
2120 #endif
2121     {
2122       void *p1 = va_arg(va, void*);
2123       SNativeIoControl d;
2124       d.request = request;
2125       d.param   = p1;
2126       ret = pFile->IoControl(IOCTRL_NATIVE, &d);
2127       if(ret<0)
2128         CLog::Log(LOGWARNING, "%s - %ld request failed with error [%d] %s", __FUNCTION__, request, errno, strerror(errno));
2129     }
2130     else
2131 #endif
2132     {
2133       CLog::Log(LOGWARNING, "%s - Unknown request type %ld", __FUNCTION__, request);
2134       ret = -1;
2135     }
2136     return ret;
2137   }
2138 #endif
2139
2140   int dll_setvbuf(FILE *stream, char *buf, int type, size_t size)
2141   {
2142     CLog::Log(LOGWARNING, "%s - May not be implemented correctly",
2143               __FUNCTION__);
2144     return 0;
2145   }
2146
2147   struct mntent *dll_getmntent(FILE *fp)
2148   {
2149     if (fp == NULL)
2150       return NULL;
2151
2152     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(fp);
2153     if (pFile)
2154     {
2155       CLog::Log(LOGERROR, "%s - getmntent is not implemented for our virtual filesystem", __FUNCTION__);
2156       return NULL;
2157     }
2158 #if defined(TARGET_LINUX)
2159     return getmntent(fp);
2160 #else
2161     CLog::Log(LOGWARNING, "%s - unimplemented function called", __FUNCTION__);
2162     return NULL;
2163 #endif
2164   }
2165
2166   int dll_filbuf(FILE *fp)
2167   {
2168     if (fp == NULL)
2169       return 0;
2170
2171     if(IS_STD_STREAM(fp))
2172       return 0;
2173
2174     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(fp);
2175     if (pFile)
2176     {
2177       int data;
2178       if(pFile->Read(&data, 1) == 1)
2179         return data;
2180       else
2181         return 0;
2182     }
2183 #ifdef TARGET_POSIX
2184     return 0;
2185 #else
2186     return _filbuf(fp);
2187 #endif
2188   }
2189
2190   int dll_flsbuf(int data, FILE *fp)
2191   {
2192     if (fp == NULL)
2193       return 0;
2194
2195     if(IS_STDERR_STREAM(fp) || IS_STDOUT_STREAM(fp))
2196     {
2197       CLog::Log(LOGDEBUG, "dll_flsbuf() - %c", data);
2198       return 1;
2199     }
2200
2201     if(IS_STD_STREAM(fp))
2202       return 0;
2203
2204     CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(fp);
2205     if (pFile)
2206     {
2207       if(pFile->Write(&data, 1) == 1)
2208         return 1;
2209       else
2210         return 0;
2211     }
2212 #ifdef TARGET_POSIX
2213     return 0;
2214 #else
2215     return _flsbuf(data, fp);
2216 #endif
2217   }
2218
2219   // this needs to be wrapped, since dll's have their own file
2220   // descriptor list, but we always use app's list with our wrappers
2221   int __cdecl dll_open_osfhandle(intptr_t _OSFileHandle, int _Flags)
2222   {
2223 #ifdef TARGET_WINDOWS
2224     return _open_osfhandle(_OSFileHandle, _Flags);
2225 #else
2226     return -1;
2227 #endif
2228   }
2229
2230 }