Merge branch 'xbox_cleanup' of github.com:amet/xbmc into amet-xbox_cleanup
[vuplus_xbmc] / xbmc / cores / DllLoader / exports / emu_kernel32.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "emu_kernel32.h"
23 #include "emu_dummy.h"
24 #include "utils/log.h"
25
26 #include "storage/IoSupport.h"
27
28 #ifndef _LINUX
29 #include <process.h>
30 #include "utils/CharsetConverter.h"
31 #endif
32
33 #include "../dll_tracker.h"
34 #include "filesystem/SpecialProtocol.h"
35
36 #ifdef _LINUX
37 #include "../../../linux/PlatformInclude.h"
38 #define __except catch
39 #endif
40
41 using namespace std;
42
43 vector<string> m_vecAtoms;
44
45 //#define API_DEBUG
46
47 extern "C" HANDLE xboxopendvdrom()
48 {
49   return CIoSupport::OpenCDROM();
50 }
51
52 extern "C" UINT WINAPI dllGetAtomNameA( ATOM nAtom, LPTSTR lpBuffer, int nSize)
53 {
54   if (nAtom < 1 || nAtom > m_vecAtoms.size() ) return 0;
55   nAtom--;
56   string& strAtom = m_vecAtoms[nAtom];
57   strcpy(lpBuffer, strAtom.c_str());
58   return strAtom.size();
59 }
60
61 extern "C" ATOM WINAPI dllFindAtomA( LPCTSTR lpString)
62 {
63   for (int i = 0; i < (int)m_vecAtoms.size(); ++i)
64   {
65     string& strAtom = m_vecAtoms[i];
66     if (strAtom == lpString) return i + 1;
67   }
68   return 0;
69 }
70
71 extern "C" ATOM WINAPI dllAddAtomA( LPCTSTR lpString)
72 {
73   m_vecAtoms.push_back(lpString);
74   return m_vecAtoms.size();
75 }
76 /*
77 extern "C" ATOM WINAPI dllDeleteAtomA(ATOM nAtom)
78 {
79 }*/
80
81 extern "C" BOOL WINAPI dllFindClose(HANDLE hFile)
82 {
83   return FindClose(hFile);
84 }
85
86 #ifdef _WIN32
87 #define CORRECT_SEP_STR(str) \
88   if (strstr(str, "://") == NULL) \
89   { \
90     int iSize_##str = strlen(str); \
91     for (int pos = 0; pos < iSize_##str; pos++) \
92       if (str[pos] == '/') str[pos] = '\\'; \
93   } \
94   else \
95   { \
96     int iSize_##str = strlen(str); \
97     for (int pos = 0; pos < iSize_##str; pos++) \
98       if (str[pos] == '\\') str[pos] = '/'; \
99   }
100 #else
101 #define CORRECT_SEP_STR(str)
102 #endif
103
104 #ifdef _WIN32
105 static void to_WIN32_FIND_DATA(LPWIN32_FIND_DATAW wdata, LPWIN32_FIND_DATA data)
106 {
107   CStdString strname;
108   g_charsetConverter.wToUTF8(wdata->cFileName, strname);
109   size_t size = sizeof(data->cFileName) / sizeof(char);
110   strncpy(data->cFileName, strname.c_str(), size);
111   if (size)
112     data->cFileName[size - 1] = '\0';
113
114   g_charsetConverter.wToUTF8(wdata->cAlternateFileName, strname);
115   size = sizeof(data->cAlternateFileName) / sizeof(char);
116   strncpy(data->cAlternateFileName, strname.c_str(), size);
117   if (size)
118     data->cAlternateFileName[size - 1] = '\0';
119
120   data->dwFileAttributes = wdata->dwFileAttributes;
121   data->ftCreationTime = wdata->ftCreationTime;
122   data->ftLastAccessTime = wdata->ftLastAccessTime;
123   data->ftLastWriteTime = wdata->ftLastWriteTime;
124   data->nFileSizeHigh = wdata->nFileSizeHigh;
125   data->nFileSizeLow = wdata->nFileSizeLow;
126   data->dwReserved0 = wdata->dwReserved0;
127   data->dwReserved1 = wdata->dwReserved1;
128 }
129
130 static void to_WIN32_FIND_DATAW(LPWIN32_FIND_DATA data, LPWIN32_FIND_DATAW wdata)
131 {
132   CStdStringW strwname;
133   g_charsetConverter.utf8ToW(data->cFileName, strwname, false);
134   size_t size = sizeof(wdata->cFileName) / sizeof(wchar_t);
135   wcsncpy(wdata->cFileName, strwname.c_str(), size);
136   if (size)
137     wdata->cFileName[size - 1] = '\0';
138
139   g_charsetConverter.utf8ToW(data->cAlternateFileName, strwname, false);
140   size = sizeof(wdata->cAlternateFileName) / sizeof(wchar_t);
141   wcsncpy(wdata->cAlternateFileName, strwname.c_str(), size);
142   if (size)
143     data->cAlternateFileName[size - 1] = '\0';
144
145   wdata->dwFileAttributes = data->dwFileAttributes;
146   wdata->ftCreationTime = data->ftCreationTime;
147   wdata->ftLastAccessTime = data->ftLastAccessTime;
148   wdata->ftLastWriteTime = data->ftLastWriteTime;
149   wdata->nFileSizeHigh = data->nFileSizeHigh;
150   wdata->nFileSizeLow = data->nFileSizeLow;
151   wdata->dwReserved0 = data->dwReserved0;
152   wdata->dwReserved1 = data->dwReserved1;
153 }
154 #endif
155
156 extern "C" HANDLE WINAPI dllFindFirstFileA(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData)
157 {
158   char* p = strdup(lpFileName);
159   CORRECT_SEP_STR(p);
160
161   // change default \\*.* into \\* which the xbox is using
162   char* e = strrchr(p, '.');
163   if (e != NULL && strlen(e) > 1 && e[1] == '*')
164   {
165     e[0] = '\0';
166   }
167
168 #ifdef _WIN32
169   struct _WIN32_FIND_DATAW FindFileDataW;
170   CStdStringW strwfile;
171   g_charsetConverter.utf8ToW(_P(p), strwfile, false);
172   HANDLE res = FindFirstFileW(strwfile.c_str(), &FindFileDataW);
173   if (res != INVALID_HANDLE_VALUE)
174     to_WIN32_FIND_DATA(&FindFileDataW, lpFindFileData);
175 #else
176   HANDLE res = FindFirstFile(_P(p).c_str(), lpFindFileData);
177 #endif
178   free(p);
179   return res;
180 }
181
182 extern "C" BOOL WINAPI dllFindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
183 {
184 #ifdef _WIN32
185   struct _WIN32_FIND_DATAW FindFileDataW;
186   to_WIN32_FIND_DATAW(lpFindFileData, &FindFileDataW);
187   BOOL res = FindNextFileW(hFindFile, &FindFileDataW);
188   if (res)
189     to_WIN32_FIND_DATA(&FindFileDataW, lpFindFileData);
190   return res;
191 #else
192   return FindNextFile(hFindFile, lpFindFileData);
193 #endif
194 }
195
196 // should be moved to CFile! or use CFile::stat
197 extern "C" DWORD WINAPI dllGetFileAttributesA(LPCSTR lpFileName)
198 {
199   char str[1024];
200
201   if (!strcmp(lpFileName, "\\Device\\Cdrom0")) return (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY);
202
203   // move to CFile classes
204   if (strncmp(lpFileName, "\\Device\\Cdrom0", 14) == 0)
205   {
206     // replace "\\Device\\Cdrom0" with "D:"
207     strcpy(str, "D:");
208     strcat(str, lpFileName + 14);
209   }
210   else strcpy(str, lpFileName);
211
212 #ifndef _LINUX
213   // convert '/' to '\\'
214   char *p = str;
215   while (p = strchr(p, '/')) * p = '\\';
216   return GetFileAttributesA(str);
217 #else
218   return GetFileAttributes(str);
219 #endif
220 }
221
222 struct SThreadWrapper
223 {
224   LPTHREAD_START_ROUTINE lpStartAddress;
225   LPVOID lpParameter;
226   PCHAR lpDLL;
227 };
228
229 #ifdef _DEBUG
230 #define MS_VC_EXCEPTION 0x406d1388
231 typedef struct tagTHREADNAME_INFO
232 {
233   DWORD dwType; // must be 0x1000
234   LPCSTR szName; // pointer to name (in same addr space)
235   DWORD dwThreadID; // thread ID (-1 caller thread)
236   DWORD dwFlags; // reserved for future use, most be zero
237 } THREADNAME_INFO;
238 #endif
239
240 #ifdef _LINUX
241 int dllThreadWrapper(LPVOID lpThreadParameter)
242 #else
243 unsigned int __stdcall dllThreadWrapper(LPVOID lpThreadParameter)
244 #endif
245 {
246   SThreadWrapper *param = (SThreadWrapper*)lpThreadParameter;
247   DWORD result;
248
249 #if defined(_DEBUG) && !defined(_LINUX)
250   THREADNAME_INFO info;
251   info.dwType = 0x1000;
252   info.szName = "DLL";
253   info.dwThreadID = ::GetCurrentThreadId();
254   info.dwFlags = 0;
255   __try
256   {
257     RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (DWORD *)&info);
258   }
259   __except (EXCEPTION_CONTINUE_EXECUTION)
260   {
261   }
262 #endif
263
264   __try
265   {
266     result = param->lpStartAddress(param->lpParameter);
267   }
268   __except (EXCEPTION_EXECUTE_HANDLER)
269   {
270     CLog::Log(LOGERROR, "DLL:%s - Unhandled exception in thread created by dll", param->lpDLL );
271     result = 0;
272   }
273
274   delete param;
275   return result;
276
277 }
278
279 extern "C" HANDLE WINAPI dllCreateThread(
280   LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
281   DWORD dwStackSize,                        // initial stack size
282   LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
283   LPVOID lpParameter,                       // thread argument
284   DWORD dwCreationFlags,                    // creation option
285   LPDWORD lpThreadId                        // thread identifier
286 )
287 {
288   uintptr_t loc = (uintptr_t)_ReturnAddress();
289
290   SThreadWrapper *param = new SThreadWrapper;
291   param->lpStartAddress = lpStartAddress;
292   param->lpParameter = lpParameter;
293   param->lpDLL = tracker_getdllname(loc);
294
295   return (HANDLE)_beginthreadex(lpThreadAttributes, dwStackSize, dllThreadWrapper, param, dwCreationFlags, (unsigned int *)lpThreadId);
296 }
297
298
299 extern "C" BOOL WINAPI dllTerminateThread(HANDLE tHread, DWORD dwExitCode)
300 {
301   not_implement("kernel32.dll fake function TerminateThread called\n");  //warning
302   return TRUE;
303 }
304
305 extern "C" void WINAPI dllSleep(DWORD dwTime)
306 {
307   return ::Sleep(dwTime);
308 }
309
310 extern "C" HANDLE WINAPI dllGetCurrentThread(void)
311 {
312   HANDLE retval = GetCurrentThread();
313   return retval;
314 }
315
316 extern "C" DWORD WINAPI dllGetCurrentProcessId(void)
317 {
318 #ifdef _LINUX
319   return (DWORD)getppid();
320 #else
321   return GetCurrentProcessId();
322 #endif
323 }
324
325 extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
326 {
327   // since the xbox has only one process, we just take the current thread
328   HANDLE h = GetCurrentThread();
329   BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
330
331   return res;
332 }
333
334 extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle,   // handle to source process
335       HANDLE hSourceHandle,          // handle to duplicate
336       HANDLE hTargetProcessHandle,   // handle to target process
337       HANDLE* lpTargetHandle,       // duplicate handle
338       DWORD dwDesiredAccess,         // requested access
339       int bInheritHandle,           // handle inheritance option
340       DWORD dwOptions               // optional actions
341                                           )
342 {
343 #ifdef API_DEBUG
344   CLog::Log(LOGDEBUG, "DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
345             hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
346             lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
347 #endif
348 #if defined (_LINUX)
349   *lpTargetHandle = hSourceHandle;
350   return 1;
351 #else
352   return DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
353 #endif
354 }
355
356 extern "C" BOOL WINAPI dllDisableThreadLibraryCalls(HMODULE h)
357 {
358 #ifdef _WIN32
359   return DisableThreadLibraryCalls(h);
360 #endif
361   not_implement("kernel32.dll fake function DisableThreadLibraryCalls called\n"); //warning
362   return TRUE;
363 }
364
365 #ifndef _LINUX
366 static void DumpSystemInfo(const SYSTEM_INFO* si)
367 {
368   CLog::Log(LOGDEBUG, "  Processor architecture %d\n", si->wProcessorArchitecture);
369   CLog::Log(LOGDEBUG, "  Page size: %d\n", si->dwPageSize);
370   CLog::Log(LOGDEBUG, "  Minimum app address: %d\n", si->lpMinimumApplicationAddress);
371   CLog::Log(LOGDEBUG, "  Maximum app address: %d\n", si->lpMaximumApplicationAddress);
372   CLog::Log(LOGDEBUG, "  Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
373   CLog::Log(LOGDEBUG, "  Number of processors: %d\n", si->dwNumberOfProcessors);
374   CLog::Log(LOGDEBUG, "  Processor type: 0x%x\n", si->dwProcessorType);
375   CLog::Log(LOGDEBUG, "  Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
376   CLog::Log(LOGDEBUG, "  Processor level: 0x%x\n", si->wProcessorLevel);
377   CLog::Log(LOGDEBUG, "  Processor revision: 0x%x\n", si->wProcessorRevision);
378 }
379 #endif
380
381 extern "C" void WINAPI dllGetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
382 {
383 #ifdef API_DEBUG
384   CLog::Log(LOGDEBUG, "GetSystemInfo(0x%x) =>", lpSystemInfo);
385 #endif
386 #ifdef _WIN32
387   // VS 2003 complains about x even so it's defined
388   lpSystemInfo->wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
389 #else
390   lpSystemInfo->x.wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
391 #endif
392   lpSystemInfo->dwPageSize = 4096;   //Xbox page size
393   lpSystemInfo->lpMinimumApplicationAddress = (void *)0x00000000;
394   lpSystemInfo->lpMaximumApplicationAddress = (void *)0x7fffffff;
395   lpSystemInfo->dwActiveProcessorMask = 1;
396   lpSystemInfo->dwNumberOfProcessors = 1;
397   lpSystemInfo->dwProcessorType = 586;  //#define PROCESSOR_INTEL_PENTIUM 586
398   lpSystemInfo->wProcessorLevel = 6;
399   //lpSystemInfo->wProcessorLevel = 5;
400   lpSystemInfo->wProcessorRevision = 0x080A;
401   lpSystemInfo->dwAllocationGranularity = 0x10000; //virtualalloc reserve block size
402 #ifdef API_DEBUG
403   DumpSystemInfo(lpSystemInfo);
404 #endif
405 }  //hardcode for xbox processor type;
406
407 extern "C" UINT WINAPI dllGetPrivateProfileIntA(
408     LPCSTR lpAppName,
409     LPCSTR lpKeyName,
410     INT nDefault,
411     LPCSTR lpFileName)
412 {
413   not_implement("kernel32.dll fake function GetPrivateProfileIntA called\n"); //warning
414   return nDefault;
415 }
416
417 //globals for memory leak hack, no need for well-behaved dlls call init/del in pair
418 //We can free the sections if applications does not call deletecriticalsection
419 //need to initialize the list head NULL at mplayer_open_file, and free memory at close file.
420 std::map<LPCRITICAL_SECTION, LPCRITICAL_SECTION> g_mapCriticalSection;
421
422 extern "C" void WINAPI dllDeleteCriticalSection(LPCRITICAL_SECTION cs)
423 {
424 #ifdef API_DEBUG
425   CLog::Log(LOGDEBUG, "DeleteCriticalSection(0x%x)", cs);
426 #endif
427   if (g_mapCriticalSection.find(cs) != g_mapCriticalSection.end())
428   {
429     LPCRITICAL_SECTION cs_new = g_mapCriticalSection[cs];
430     DeleteCriticalSection(cs_new);
431     delete cs_new;
432     g_mapCriticalSection.erase(cs);
433   }
434 }
435
436 extern "C" void WINAPI dllInitializeCriticalSection(LPCRITICAL_SECTION cs)
437 {
438 #ifdef API_DEBUG
439   CLog::Log(LOGDEBUG, "InitializeCriticalSection(0x%x)", cs);
440 #endif
441   LPCRITICAL_SECTION cs_new = new CRITICAL_SECTION;
442   memset(cs_new, 0, sizeof(CRITICAL_SECTION));
443   InitializeCriticalSection(cs_new);
444
445   // just take the first member of the CRITICAL_SECTION to save ourdata in, this will be used to
446   // get fast access to the new critial section in dllLeaveCriticalSection and dllEnterCriticalSection
447   ((LPCRITICAL_SECTION*)cs)[0] = cs_new;
448   g_mapCriticalSection[cs] = cs_new;
449 }
450
451 extern "C" void WINAPI dllLeaveCriticalSection(LPCRITICAL_SECTION cs)
452 {
453 #ifdef API_DEBUG
454   CLog::Log(LOGDEBUG, "LeaveCriticalSection(0x%x) %p\n", ((LPCRITICAL_SECTION*)cs)[0]);
455 #endif
456   LeaveCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
457 }
458
459 extern "C" void WINAPI dllEnterCriticalSection(LPCRITICAL_SECTION cs)
460 {
461 #ifdef API_DEBUG
462   CLog::Log(LOGDEBUG, "EnterCriticalSection(0x%x) %p\n", cs, ((LPCRITICAL_SECTION*)cs)[0]);
463 #endif
464 #ifndef _LINUX
465   if (!(LPCRITICAL_SECTION)cs->OwningThread)
466   {
467 #ifdef API_DEBUG
468     CLog::Log(LOGDEBUG, "entered uninitialized critisec!\n");
469 #endif
470     dllInitializeCriticalSection(cs);
471   }
472 #endif
473   EnterCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
474 }
475
476 extern "C" DWORD WINAPI dllGetVersion()
477 {
478 #ifdef API_DEBUG
479   CLog::Log(LOGDEBUG, "GetVersion() => 0xC0000004 (Windows 95)\n");
480 #endif
481   //return 0x0a280105; //Windows XP
482   return 0xC0000004; //Windows 95
483 }
484
485 extern "C" BOOL WINAPI dllGetVersionExA(LPOSVERSIONINFO lpVersionInfo)
486 {
487 #ifdef API_DEBUG
488   CLog::Log(LOGDEBUG, "GetVersionExA()\n");
489 #endif
490   lpVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
491   lpVersionInfo->dwMajorVersion = 4;
492   lpVersionInfo->dwMinorVersion = 0;
493   lpVersionInfo->dwBuildNumber = 0x4000457;
494   // leave it here for testing win9x-only codecs
495   lpVersionInfo->dwPlatformId = 1; //VER_PLATFORM_WIN32_WINDOWS
496   lpVersionInfo->szCSDVersion[0] = 0;
497 #ifdef API_DEBUG
498   CLog::Log(LOGDEBUG, "  Major version: %d\n  Minor version: %d\n  Build number: %x\n"
499             "  Platform Id: %d\n Version string: '%s'\n",
500             lpVersionInfo->dwMajorVersion, lpVersionInfo->dwMinorVersion,
501             lpVersionInfo->dwBuildNumber, lpVersionInfo->dwPlatformId, lpVersionInfo->szCSDVersion);
502 #endif
503   return TRUE;
504 }
505
506 extern "C" BOOL WINAPI dllGetVersionExW(LPOSVERSIONINFOW lpVersionInfo)
507 {
508 #ifdef API_DEBUG
509   CLog::Log(LOGDEBUG, "GetVersionExW()\n");
510 #endif
511   if(!dllGetVersionExA((LPOSVERSIONINFO)lpVersionInfo))
512     return FALSE;
513
514   lpVersionInfo->szCSDVersion[0] = 0;
515   lpVersionInfo->szCSDVersion[1] = 0;
516   return TRUE;
517 }
518
519 extern "C" UINT WINAPI dllGetProfileIntA(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault)
520 {
521   //  CLog::Log(LOGDEBUG,"GetProfileIntA:%s %s %i", lpAppName,lpKeyName,nDefault);
522   not_implement("kernel32.dll fake function GetProfileIntA called\n"); //warning
523   return nDefault;
524 }
525
526 extern "C" BOOL WINAPI dllFreeEnvironmentStringsW(LPWSTR lpString)
527 {
528   // we don't have anything to clean up here, just return.
529 #ifdef API_DEBUG
530   CLog::Log(LOGDEBUG, "FreeEnvironmentStringsA(0x%x) => 1", lpString);
531 #endif
532   return true;
533 }
534
535 extern "C" HMODULE WINAPI dllGetOEMCP()
536 {
537   not_implement("kernel32.dll fake function GetOEMCP called\n"); //warning
538   return NULL;
539 }
540
541 extern "C" HMODULE WINAPI dllRtlUnwind(PVOID TargetFrame OPTIONAL, PVOID TargetIp OPTIONAL, PEXCEPTION_RECORD ExceptionRecord OPTIONAL, PVOID ReturnValue)
542 {
543   not_implement("kernel32.dll fake function RtlUnwind called\n"); //warning
544   return NULL;
545 }
546 extern "C" LPTSTR WINAPI dllGetCommandLineA()
547 {
548 #ifdef API_DEBUG
549   CLog::Log(LOGDEBUG, "GetCommandLineA() => \"c:\\xbmc.xbe\"\n");
550 #endif
551   return (LPTSTR)"c:\\xbmc.xbe";
552 }
553
554 extern "C" HMODULE WINAPI dllExitProcess(UINT uExitCode)
555 {
556   not_implement("kernel32.dll fake function ExitProcess called\n"); //warning
557   return NULL;
558 }
559 extern "C" HMODULE WINAPI dllTerminateProcess(HANDLE hProcess, UINT uExitCode)
560 {
561   not_implement("kernel32.dll fake function TerminateProcess called\n"); //warning
562   return NULL;
563 }
564 extern "C" HANDLE WINAPI dllGetCurrentProcess()
565 {
566 #if !defined(_LINUX)
567   return GetCurrentProcess();
568 #else
569 #ifdef _WIN32
570   return GetCurrentProcess();
571 #endif
572 #ifdef API_DEBUG
573   CLog::Log(LOGDEBUG, "GetCurrentProcess(void) => 9375");
574 #endif
575   return (HANDLE)9375;
576 #endif
577 }
578
579 extern "C" UINT WINAPI dllGetACP()
580 {
581 #ifdef API_DEBUG
582   CLog::Log(LOGDEBUG, "GetACP() => 0");
583 #endif
584   return CP_ACP;
585 }
586
587 extern "C" UINT WINAPI dllSetHandleCount(UINT uNumber)
588 {
589   //Under Windows NT and Windows 95, this function simply returns the value specified in the uNumber parameter.
590   //return uNumber;
591 #ifdef API_DEBUG
592   CLog::Log(LOGDEBUG, "SetHandleCount(0x%x) => 1\n", uNumber);
593 #endif
594   return uNumber;
595 }
596
597 extern "C" HANDLE WINAPI dllGetStdHandle(DWORD nStdHandle)
598 {
599   switch (nStdHandle)
600   {
601   case STD_INPUT_HANDLE: return (HANDLE)0;
602   case STD_OUTPUT_HANDLE: return (HANDLE)1;
603   case STD_ERROR_HANDLE: return (HANDLE)2;
604   }
605   SetLastError( ERROR_INVALID_PARAMETER );
606   return INVALID_HANDLE_VALUE;
607 }
608
609 extern "C" DWORD WINAPI dllGetFileType(HANDLE hFile)
610 {
611 #ifdef API_DEBUG
612   CLog::Log(LOGDEBUG, "GetFileType(0x%x) => 0x3 = pipe", hFile);
613 #endif
614   return 3;
615 }
616
617 extern "C" int WINAPI dllGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
618 {
619 #ifdef API_DEBUG
620   CLog::Log(LOGDEBUG, "GetStartupInfoA(0x%x) => 1\n");
621 #endif
622   lpStartupInfo->cb = sizeof(_STARTUPINFOA);
623   lpStartupInfo->cbReserved2 = 0;
624   lpStartupInfo->dwFillAttribute = 0;
625   lpStartupInfo->dwFlags = 0;
626   lpStartupInfo->dwX = 50; //
627   lpStartupInfo->dwXCountChars = 0;
628   lpStartupInfo->dwXSize = 0;
629   lpStartupInfo->dwY = 50; //
630   lpStartupInfo->dwYCountChars = 0;
631   lpStartupInfo->dwYSize = 0;
632   lpStartupInfo->hStdError = (HANDLE)2;
633   lpStartupInfo->hStdInput = (HANDLE)0;
634   lpStartupInfo->hStdOutput = (HANDLE)1;
635   lpStartupInfo->lpDesktop = NULL;
636   lpStartupInfo->lpReserved = NULL;
637   lpStartupInfo->lpReserved2 = 0;
638   lpStartupInfo->lpTitle = (LPTSTR)"XBMC";
639   lpStartupInfo->wShowWindow = 0;
640   return 1;
641 }
642
643 extern "C" BOOL WINAPI dllFreeEnvironmentStringsA(LPSTR lpString)
644 {
645   // we don't have anything to clean up here, just return.
646   return true;
647 }
648
649 static const char ch_envs[] =
650   "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELETED,1\r\n"
651   "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
652
653 extern "C" LPVOID WINAPI dllGetEnvironmentStrings()
654 {
655 #ifdef _WIN32
656   return GetEnvironmentStrings();
657 #endif
658 #ifdef API_DEBUG
659   CLog::Log(LOGDEBUG, "GetEnvironmentStrings() => 0x%x = %p", ch_envs, ch_envs);
660 #endif
661   return (LPVOID)ch_envs;
662 }
663
664 extern "C" LPVOID WINAPI dllGetEnvironmentStringsW()
665 {
666 #ifdef _WIN32
667   return GetEnvironmentStringsW();
668 #endif
669   return 0;
670 }
671
672 extern "C" int WINAPI dllGetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
673 {
674 #ifdef _WIN32
675   return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
676 #endif
677   if (lpBuffer) lpBuffer[0] = 0;
678
679   if (strcmp(lpName, "__MSVCRT_HEAP_SELECT") == 0)
680     strcpy(lpBuffer, "__GLOBAL_HEAP_SELECTED,1");
681 #ifdef API_DEBUG
682   CLog::Log(LOGDEBUG, "GetEnvironmentVariableA('%s', 0x%x, %d) => %d", lpName, lpBuffer, nSize, strlen(lpBuffer));
683 #endif
684   return strlen(lpBuffer);
685 }
686
687 extern "C" HMODULE WINAPI dllLCMapStringA(LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest)
688 {
689   not_implement("kernel32.dll fake function LCMapStringA called\n"); //warning
690   return NULL;
691 }
692
693 extern "C" HMODULE WINAPI dllLCMapStringW(LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest)
694 {
695   not_implement("kernel32.dll fake function LCMapStringW called\n"); //warning
696   return NULL;
697 }
698
699 extern "C" HMODULE WINAPI dllSetStdHandle(DWORD nStdHandle, HANDLE hHandle)
700 {
701   not_implement("kernel32.dll fake function SetStdHandle called\n"); //warning
702   return NULL;
703 }
704
705 extern "C" HMODULE WINAPI dllGetStringTypeA(LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
706 {
707   not_implement("kernel32.dll fake function GetStringTypeA called\n"); //warning
708   return NULL;
709 }
710
711 extern "C" HMODULE WINAPI dllGetStringTypeW(DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
712 {
713   not_implement("kernel32.dll fake function GetStringTypeW called\n"); //warning
714   return NULL;
715 }
716
717 extern "C" HMODULE WINAPI dllGetCPInfo(UINT CodePage, LPCPINFO lpCPInfo)
718 {
719   not_implement("kernel32.dll fake function GetCPInfo called\n"); //warning
720   return NULL;
721 }
722
723 extern "C" LCID WINAPI dllGetThreadLocale(void)
724 {
725   // primary language identifier, sublanguage identifier, sorting identifier
726   return MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
727 }
728
729 extern "C" BOOL WINAPI dllSetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass)
730 {
731   not_implement("kernel32.dll fake function SetPriorityClass called\n"); //warning
732   return false;
733 }
734
735 extern "C" DWORD WINAPI dllFormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, va_list* Arguments)
736 {
737 #ifdef _WIN32
738   return FormatMessageA(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
739 #else
740   not_implement("kernel32.dll fake function FormatMessage called\n"); //warning
741   return 0;
742 #endif
743 }
744
745 extern "C" DWORD WINAPI dllGetFullPathNameA(LPCTSTR lpFileName, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR* lpFilePart)
746 {
747 #ifdef _WIN32
748   if (!lpFileName) return 0;
749   if(strstr(lpFileName, "://"))
750   {
751     unsigned int length = strlen(lpFileName);
752     if (nBufferLength < (length + 1))
753       return length + 1;
754     else
755     {
756       strcpy(lpBuffer, lpFileName);
757       if(lpFilePart)
758       {
759         char* s1 = strrchr(lpBuffer, '\\');
760         char* s2 = strrchr(lpBuffer, '/');
761         if(s2 && s1 > s2)
762           *lpFilePart = s1 + 1;
763         else if(s1 && s2 > s1)
764           *lpFilePart = s2 + 1;
765         else
766           *lpFilePart = lpBuffer;
767       }
768       return length;
769     }
770   }
771   return GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, lpFilePart);
772 #else
773   not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
774   return 0;
775 #endif
776 }
777
778 extern "C" DWORD WINAPI dllGetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart)
779 {
780 #ifdef _WIN32
781   if (!lpFileName) return 0;
782   if(wcsstr(lpFileName, L"://"))
783   {
784     size_t length = wcslen(lpFileName);
785     if (nBufferLength < (length + 1))
786       return length + 1;
787     else
788     {
789       wcscpy(lpBuffer, lpFileName);
790       if(lpFilePart)
791       {
792         wchar_t* s1 = wcsrchr(lpBuffer, '\\');
793         wchar_t* s2 = wcsrchr(lpBuffer, '/');
794         if(s2 && s1 > s2)
795           *lpFilePart = s1 + 1;
796         else if(s1 && s2 > s1)
797           *lpFilePart = s2 + 1;
798         else
799           *lpFilePart = lpBuffer;
800       }
801       return length;
802     }
803   }
804   return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
805 #else
806   not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
807   return 0;
808 #endif
809 }
810
811 extern "C" DWORD WINAPI dllExpandEnvironmentStringsA(LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize)
812 {
813 #ifdef _WIN32
814   return ExpandEnvironmentStringsA(lpSrc, lpDst, nSize);
815 #else
816   not_implement("kernel32.dll fake function ExpandEnvironmentStringsA called\n"); //warning
817 #endif
818   return 0;
819 }
820
821 extern "C" UINT WINAPI dllGetWindowsDirectoryA(LPTSTR lpBuffer, UINT uSize)
822 {
823   not_implement("kernel32.dll fake function dllGetWindowsDirectory called\n"); //warning
824   return 0;
825 }
826
827 extern "C" UINT WINAPI dllGetSystemDirectoryA(LPTSTR lpBuffer, UINT uSize)
828 {
829   //char* systemdir = "special://xbmc/system/mplayer/codecs";
830   //unsigned int len = strlen(systemdir);
831   //if (len > uSize) return 0;
832   //strcpy(lpBuffer, systemdir);
833   //not_implement("kernel32.dll incompete function dllGetSystemDirectory called\n"); //warning
834   //CLog::Log(LOGDEBUG,"KERNEL32!GetSystemDirectoryA(0x%x, %d) => %s", lpBuffer, uSize, systemdir);
835   //return len;
836 #ifdef API_DEBUG
837   CLog::Log(LOGDEBUG, "GetSystemDirectoryA(%p,%d)\n", lpBuffer, uSize);
838 #endif
839   if (!lpBuffer) strcpy(lpBuffer, ".");
840   return 1;
841 }
842
843
844 extern "C" UINT WINAPI dllGetShortPathName(LPTSTR lpszLongPath, LPTSTR lpszShortPath, UINT cchBuffer)
845 {
846   if (!lpszLongPath) return 0;
847   if (strlen(lpszLongPath) == 0)
848   {
849     //strcpy(lpszLongPath, "special://xbmc/system/mplayer/codecs/QuickTime.qts");
850   }
851 #ifdef API_DEBUG
852   CLog::Log(LOGDEBUG, "KERNEL32!GetShortPathNameA('%s',%p,%d)\n", lpszLongPath, lpszShortPath, cchBuffer);
853 #endif
854   strcpy(lpszShortPath, lpszLongPath);
855   return strlen(lpszShortPath);
856 }
857
858 extern "C" HANDLE WINAPI dllGetProcessHeap()
859 {
860 #ifdef  _LINUX
861   CLog::Log(LOGWARNING, "KERNEL32!GetProcessHeap() linux cant provide this service!");
862   return 0;
863 #else
864   HANDLE hHeap;
865   hHeap = GetProcessHeap();
866 #ifdef API_DEBUG
867   CLog::Log(LOGDEBUG, "KERNEL32!GetProcessHeap() => 0x%x", hHeap);
868 #endif
869   return hHeap;
870 #endif
871 }
872
873 extern "C" UINT WINAPI dllSetErrorMode(UINT i)
874 {
875 #ifdef API_DEBUG
876   CLog::Log(LOGDEBUG, "SetErrorMode(%d) => 0\n", i);
877 #endif
878   return 0;
879 }
880
881 extern "C" BOOL WINAPI dllIsProcessorFeaturePresent(DWORD ProcessorFeature)
882 {
883   BOOL result = 0;
884   switch (ProcessorFeature)
885   {
886   case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
887     result = false;
888     break;
889   case PF_COMPARE_EXCHANGE_DOUBLE:
890     result = true;
891     break;
892   case PF_FLOATING_POINT_EMULATED:
893     result = true;
894     break;
895   case PF_FLOATING_POINT_PRECISION_ERRATA:
896     result = false;
897     break;
898   case PF_MMX_INSTRUCTIONS_AVAILABLE:
899     result = true;
900     break;
901   case PF_PAE_ENABLED:
902     result = false;
903     break;
904   case PF_RDTSC_INSTRUCTION_AVAILABLE:
905     result = true;
906     break;
907   case PF_XMMI_INSTRUCTIONS_AVAILABLE:
908     result = true;
909     break;
910   case 10: //PF_XMMI64_INSTRUCTIONS_AVAILABLE
911     result = false;
912     break;
913   }
914
915 #ifdef API_DEBUG
916   CLog::Log(LOGDEBUG, "IsProcessorFeaturePresent(0x%x) => 0x%x\n", ProcessorFeature, result);
917 #endif
918   return result;
919 }
920
921 extern "C" UINT WINAPI dllGetCurrentDirectoryA(UINT c, LPSTR s)
922 {
923   char curdir[] = "special://xbmc/";
924   int result;
925   strncpy(s, curdir, c);
926   result = 1 + ((c < strlen(curdir)) ? c : strlen(curdir));
927 #ifdef API_DEBUG
928   CLog::Log(LOGDEBUG, "GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
929 #endif
930   return result;
931 }
932
933 extern "C" UINT WINAPI dllSetCurrentDirectoryA(const char *pathname)
934 {
935 #ifdef API_DEBUG
936   CLog::Log(LOGDEBUG, "SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
937 #endif
938   return 1;
939 }
940
941 extern "C" int WINAPI dllSetUnhandledExceptionFilter(void* filter)
942 {
943 #ifdef API_DEBUG
944   CLog::Log(LOGDEBUG, "SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
945 #endif
946   return 1; //unsupported and probably won't ever be supported
947 }
948
949 extern "C" int WINAPI dllSetEnvironmentVariableA(const char *name, const char *value)
950 {
951 #ifdef API_DEBUG
952   CLog::Log(LOGDEBUG, "SetEnvironmentVariableA(%s, %s)\n", name, value);
953 #endif
954   return 0;
955 }
956
957 extern "C" int WINAPI dllCreateDirectoryA(const char *pathname, void *sa)
958 {
959 #ifdef API_DEBUG
960   CLog::Log(LOGDEBUG, "CreateDirectory(0x%x = %s, 0x%x) => 1\n", pathname, pathname, sa);
961 #endif
962   return 1;
963 }
964
965 extern "C" DWORD WINAPI dllWaitForSingleObject(HANDLE hHandle, DWORD dwMiliseconds)
966 {
967 #ifdef API_DEBUG
968   CLog::Log(LOGDEBUG, "WaitForSingleObject(0x%x, %d)", hHandle, dwMiliseconds);
969 #endif
970   return WaitForSingleObject(hHandle, dwMiliseconds);
971 }
972
973 #ifdef _LINUX
974 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
975 #else
976 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
977 #endif
978 {
979 #ifdef API_DEBUG
980   CLog::Log(LOGDEBUG, "WaitForMultipleObjects(..)");
981 #endif
982
983   return WaitForMultipleObjects(nCount, lpHandles, fWaitAll, dwMilliseconds);
984 }
985
986 extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProcessAffinityMask, LPDWORD lpSystemAffinityMask)
987 {
988   CLog::Log(LOGDEBUG, "GetProcessAffinityMask(%p, %p, %p) => 1\n",
989             (void*)hProcess, (void*)lpProcessAffinityMask, (void*)lpSystemAffinityMask);
990   if (lpProcessAffinityMask)*lpProcessAffinityMask = 1;
991   if (lpSystemAffinityMask)*lpSystemAffinityMask = 1;
992   return 1;
993 }
994
995 extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData)
996 {
997   if (Locale == LOCALE_SYSTEM_DEFAULT || Locale == LOCALE_USER_DEFAULT)
998   {
999     if (LCType == LOCALE_SISO639LANGNAME)
1000     {
1001       if (cchData > 3)
1002       {
1003         strcpy(lpLCData, "eng");
1004         return 4;
1005       }
1006     }
1007     else if (LCType == LOCALE_SISO3166CTRYNAME)
1008     {
1009       if (cchData > 2)
1010       {
1011         strcpy(lpLCData, "US");
1012         return 3;
1013       }
1014     }
1015     else if (LCType == LOCALE_IDEFAULTLANGUAGE)
1016     {
1017       if (cchData > 5)
1018       {
1019         strcpy(lpLCData, "en-US");
1020         return 6;
1021       }
1022     }
1023   }
1024
1025   not_implement("kernel32.dll incomplete function GetLocaleInfoA called\n");  //warning
1026   SetLastError(ERROR_INVALID_FUNCTION);
1027   return 0;
1028 }
1029
1030 extern "C" UINT WINAPI dllGetConsoleCP()
1031 {
1032   return 437; // OEM - United States
1033 }
1034
1035 extern "C" UINT WINAPI dllGetConsoleOutputCP()
1036 {
1037   return 437; // OEM - United States
1038 }
1039
1040 // emulated because windows expects different behaviour
1041 // the xbox calculates always 1 character extra for 0 termination
1042 // however, this is only desired when cbMultiByte has the value -1
1043 extern "C" int WINAPI dllMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
1044 {
1045   // first fix, on windows cchWideChar and cbMultiByte may be the same.
1046   // xbox fails, because it expects cbMultiByte to be at least one character bigger
1047   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1048   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1049   int destinationBufferSize = cchWideChar;
1050   LPWSTR destinationBuffer = lpWideCharStr;
1051   if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1052     destinationBufferSize++;
1053     destinationBuffer = (LPWSTR)malloc(destinationBufferSize * sizeof(WCHAR));
1054   }
1055
1056   int ret = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, destinationBuffer, destinationBufferSize);
1057
1058   if (ret > 0)
1059   {
1060     // second fix, but only if cchWideChar == 0, and ofcours ret > 0 indicating the function
1061     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1062     if (cchWideChar == 0) {
1063       ret--;
1064     }
1065
1066     // revert the first fix again
1067     if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1068       // the 0 termination character could never have been written on a windows machine
1069       // because of cchWideChar == cbMultiByte, again xbox added one for it.
1070       ret--;
1071
1072       memcpy(lpWideCharStr, destinationBuffer, ret * sizeof(WCHAR));
1073       free(destinationBuffer);
1074     }
1075   }
1076
1077   return ret;
1078 }
1079
1080 // same reason as above
1081 extern "C" int WINAPI dllWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
1082 {
1083   // first fix, on windows cchWideChar and cbMultiByte may be the same.
1084   // xbox fails, because it expects cbMultiByte to be at least one character bigger
1085   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1086   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1087   int destinationBufferSize = cbMultiByte;
1088   LPSTR destinationBuffer = lpMultiByteStr;
1089   if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1090     destinationBufferSize++;
1091     destinationBuffer = (LPSTR)malloc(destinationBufferSize * sizeof(char));
1092   }
1093
1094   int ret = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, destinationBuffer, destinationBufferSize, lpDefaultChar, lpUsedDefaultChar);
1095
1096   if (ret > 0)
1097   {
1098     // second fix, but only if cbMultiByte == 0, and ofcours ret > 0 indicating the function
1099     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1100     if (cbMultiByte == 0) {
1101       ret--;
1102     }
1103
1104     // revert the first fix again
1105     if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1106       // the 0 termination character could never have been written on a windows machine
1107       // because of cchWideChar == cbMultiByte, again xbox added one for it.
1108       ret--;
1109
1110       memcpy(lpMultiByteStr, destinationBuffer, ret);
1111       free(destinationBuffer);
1112     }
1113   }
1114
1115   return ret;
1116 }
1117
1118 extern "C" UINT WINAPI dllSetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
1119 {
1120 #ifdef _WIN32
1121   return SetConsoleCtrlHandler(HandlerRoutine, Add);
1122 #else
1123   // no consoles exists on the xbox, do nothing
1124   not_implement("kernel32.dll fake function SetConsoleCtrlHandler called\n");  //warning
1125   SetLastError(ERROR_INVALID_FUNCTION);
1126   return 0;
1127 #endif
1128 }
1129
1130 typedef struct _SFlsSlot
1131 {
1132   LONG lInUse;
1133   PVOID pData;
1134   PFLS_CALLBACK_FUNCTION pCallback;
1135 }
1136 SFlsSlot, *LPSFlsSlot;
1137
1138 #define FLS_NUM_SLOTS 5
1139 #if defined (_LINUX)
1140 #define FLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
1141 #endif
1142 SFlsSlot flsSlots[FLS_NUM_SLOTS] = { { false, NULL, NULL } };
1143
1144 extern "C" DWORD WINAPI dllFlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
1145 {
1146   DWORD i;
1147 #ifdef API_DEBUG
1148   CLog::Log(LOGDEBUG, "FlsAlloc(0x%x)\n", lpCallback);
1149 #endif
1150   for (i = 0; i < FLS_NUM_SLOTS; i++) {
1151     if( InterlockedCompareExchange(&flsSlots[i].lInUse, 1, 0) == 0 ) {
1152       flsSlots[i].pData = NULL;
1153       flsSlots[i].pCallback = lpCallback;
1154       return i;
1155     }
1156   }
1157   SetLastError(ERROR_INVALID_PARAMETER);
1158   CLog::Log(LOGERROR, " - Out of fls slots");
1159   return FLS_OUT_OF_INDEXES; // "
1160 }
1161
1162 static LPSFlsSlot FlsGetSlot(DWORD dwFlsIndex)
1163 {
1164   if (dwFlsIndex >= FLS_NUM_SLOTS) {
1165     SetLastError(ERROR_INVALID_PARAMETER);
1166     return NULL;
1167   }
1168   if (flsSlots[dwFlsIndex].lInUse != 1) {
1169     SetLastError(ERROR_INVALID_PARAMETER); // actually ERROR_NO_MEMORY would be correct
1170     return NULL;
1171   }
1172   return &(flsSlots[dwFlsIndex]);
1173 }
1174
1175 extern "C" BOOL WINAPI dllFlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
1176 {
1177 #ifdef API_DEBUG
1178   CLog::Log(LOGDEBUG, "FlsSetValue(%d, 0x%x) => 0x%x\n", dwFlsIndex, lpFlsData);
1179 #endif
1180   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1181   if (slot == NULL)
1182     return false;
1183   slot->pData = lpFlsData;
1184   return true;
1185 }
1186
1187 extern "C" PVOID WINAPI dllFlsGetValue(DWORD dwFlsIndex)
1188 {
1189 #ifdef API_DEBUG
1190   CLog::Log(LOGDEBUG, "FlsGetValue(%d)\n", dwFlsIndex);
1191 #endif
1192   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1193   return (slot == NULL) ? NULL : slot->pData;
1194 }
1195
1196 extern "C" BOOL WINAPI dllFlsFree(DWORD dwFlsIndex)
1197 {
1198 #ifdef API_DEBUG
1199   CLog::Log(LOGDEBUG, "FlsFree(%d)\n", dwFlsIndex);
1200 #endif
1201   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1202   if (slot == NULL)
1203     return false;
1204
1205   if( slot->pCallback )
1206     slot->pCallback(slot->pData);
1207
1208   slot->pData = NULL;
1209   slot->lInUse = 0;
1210
1211   return true;
1212 }
1213
1214
1215 extern "C" PVOID WINAPI dllEncodePointer(PVOID ptr)
1216 {
1217   return ptr;
1218 }
1219
1220 extern "C" PVOID WINAPI dllDecodePointer(PVOID ptr)
1221 {
1222   return ptr;
1223 }
1224
1225
1226 extern "C" HANDLE WINAPI dllCreateFileA(
1227     IN LPCSTR lpFileName,
1228     IN DWORD dwDesiredAccess,
1229     IN DWORD dwShareMode,
1230     IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1231     IN DWORD dwCreationDisposition,
1232     IN DWORD dwFlagsAndAttributes,
1233     IN HANDLE hTemplateFile
1234     )
1235 {
1236   return CreateFileA(_P(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
1237 }
1238
1239 extern "C" BOOL WINAPI dllLockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh)
1240 {
1241   //return LockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh);
1242   return TRUE;
1243 }
1244
1245 extern "C" BOOL WINAPI dllLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh, LPOVERLAPPED lpOverlapped)
1246 {
1247   //return LockFileEx(hFile, dwFlags, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh, lpOverlapped);
1248   return TRUE;
1249 }
1250
1251 extern "C" BOOL WINAPI dllUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1252 {
1253   //return UnlockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1254   return TRUE;
1255 }
1256
1257 extern "C" DWORD WINAPI dllGetTempPathA(DWORD nBufferLength, LPTSTR lpBuffer)
1258 {
1259   // If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer,
1260   // not including the terminating null character. If the return value is greater than nBufferLength,
1261   // the return value is the size of the buffer required to hold the path.
1262   const char* tempPath = "special://temp/temp/";
1263   unsigned int len = strlen(tempPath);
1264
1265   if (nBufferLength > len)
1266   {
1267     strcpy(lpBuffer, tempPath);
1268   }
1269
1270   return len;
1271 }
1272
1273 extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE hModule, HRSRC hResInfo)
1274 {
1275   not_implement("kernel32.dll fake function LoadResource called\n");
1276   return NULL;
1277 }
1278
1279 extern "C" HRSRC WINAPI dllFindResourceA(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
1280 {
1281   not_implement("kernel32.dll fake function FindResource called\n");
1282   return NULL;
1283 }
1284
1285
1286 /*
1287
1288 The following routine was hacked up by JM while looking at why the DVD player was failing
1289 in the middle of the movie.  The symptoms were:
1290
1291 1. DVD player returned error about expecting a NAV packet but none found.
1292 2. Resulted in DVD player closing.
1293 3. Always occured in the same place.
1294 4. Occured on every DVD I tried (originals)
1295 5. Approximately where I would expect the layer change to be (ie just over half way
1296    through the movie)
1297 6. Resulted in the last chunk of the requested data to be NULL'd out completely.  ReadFile()
1298    returns correctly, but the last chunk is completely zero'd out.
1299
1300 This routine checks the last chunk for zeros, and re-reads if necessary.
1301 */
1302 #define DVD_CHUNK_SIZE 2048
1303
1304 extern "C" BOOL WINAPI dllDVDReadFileLayerChangeHack(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
1305 {
1306   BOOL ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
1307   if (!ret || !lpNumberOfBytesRead || *lpNumberOfBytesRead < DVD_CHUNK_SIZE) return ret;
1308   DWORD numChecked = *lpNumberOfBytesRead;
1309   while (numChecked >= DVD_CHUNK_SIZE)
1310   {
1311     BYTE *p = (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE;
1312     // test for a NULL block
1313     while (*p == 0 && p < (BYTE *)lpBuffer + numChecked)
1314       p++;
1315     if (p == (BYTE *)lpBuffer + numChecked)
1316     { // fully NULL block - reread
1317 #ifdef _WIN32
1318       LONG low = 0;
1319       LONG high = 0;
1320 #else
1321       int32_t low = 0;
1322       int32_t high = 0;
1323 #endif
1324       low = SetFilePointer(hFile, low, &high, FILE_CURRENT);
1325       CLog::Log(LOGWARNING,
1326                 "DVDReadFile() warning - "
1327                 "invalid data read from block at %i (%i) - rereading",
1328                 low, high);
1329       SetFilePointer(hFile, (int)numChecked - (int)*lpNumberOfBytesRead - DVD_CHUNK_SIZE, NULL, FILE_CURRENT);
1330       DWORD numRead;
1331       ret = ReadFile(hFile, (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE, DVD_CHUNK_SIZE, &numRead, lpOverlapped);
1332       if (!ret) return FALSE;
1333       SetFilePointer(hFile, low, &high, FILE_BEGIN);
1334     }
1335     numChecked -= DVD_CHUNK_SIZE;
1336   }
1337   return ret;
1338 }
1339
1340 extern "C" LPVOID WINAPI dllLockResource(HGLOBAL hResData)
1341 {
1342 #ifdef _WIN32
1343   return LockResource(hResData);
1344 #else
1345   not_implement("kernel32.dll fake function LockResource called\n"); //warning
1346   return 0;
1347 #endif
1348 }
1349
1350 extern "C" SIZE_T WINAPI dllGlobalSize(HGLOBAL hMem)
1351 {
1352 #ifdef _WIN32
1353   return GlobalSize(hMem);
1354 #else
1355   not_implement("kernel32.dll fake function GlobalSize called\n"); //warning
1356   return 0;
1357 #endif
1358 }
1359
1360 extern "C" DWORD WINAPI dllSizeofResource(HMODULE hModule, HRSRC hResInfo)
1361 {
1362 #ifdef _WIN32
1363   return SizeofResource(hModule, hResInfo);
1364 #else
1365   not_implement("kernel32.dll fake function SizeofResource called\n"); //warning
1366   return 0;
1367 #endif
1368 }