fixed: GetFullPathName must be wrapped on windows since python uses it for out specia...
[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 "utils/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 #ifndef _XBOX
319 #ifdef _LINUX
320   return (DWORD)getppid();
321 #else
322   return GetCurrentProcessId();
323 #endif
324 #else
325 #ifdef API_DEBUG
326   CLog::Log(LOGDEBUG, "GetCurrentProcessId(void) => 31337");
327 #endif
328   return 31337;
329 #endif
330 }
331
332 extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
333 {
334   // since the xbox has only one process, we just take the current thread
335   HANDLE h = GetCurrentThread();
336   BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
337
338   return res;
339 }
340
341 extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle,   // handle to source process
342       HANDLE hSourceHandle,          // handle to duplicate
343       HANDLE hTargetProcessHandle,   // handle to target process
344       HANDLE* lpTargetHandle,       // duplicate handle
345       DWORD dwDesiredAccess,         // requested access
346       int bInheritHandle,           // handle inheritance option
347       DWORD dwOptions               // optional actions
348                                           )
349 {
350 #ifdef API_DEBUG
351   CLog::Log(LOGDEBUG, "DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
352             hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
353             lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
354 #endif
355 #if defined (_XBOX) || defined (_LINUX)
356   *lpTargetHandle = hSourceHandle;
357   return 1;
358 #else
359   return DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
360 #endif
361 }
362
363 extern "C" BOOL WINAPI dllDisableThreadLibraryCalls(HMODULE h)
364 {
365 #ifdef _WIN32
366   return DisableThreadLibraryCalls(h);
367 #endif
368   not_implement("kernel32.dll fake function DisableThreadLibraryCalls called\n"); //warning
369   return TRUE;
370 }
371
372 #ifndef _LINUX
373 static void DumpSystemInfo(const SYSTEM_INFO* si)
374 {
375   CLog::Log(LOGDEBUG, "  Processor architecture %d\n", si->wProcessorArchitecture);
376   CLog::Log(LOGDEBUG, "  Page size: %d\n", si->dwPageSize);
377   CLog::Log(LOGDEBUG, "  Minimum app address: %d\n", si->lpMinimumApplicationAddress);
378   CLog::Log(LOGDEBUG, "  Maximum app address: %d\n", si->lpMaximumApplicationAddress);
379   CLog::Log(LOGDEBUG, "  Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
380   CLog::Log(LOGDEBUG, "  Number of processors: %d\n", si->dwNumberOfProcessors);
381   CLog::Log(LOGDEBUG, "  Processor type: 0x%x\n", si->dwProcessorType);
382   CLog::Log(LOGDEBUG, "  Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
383   CLog::Log(LOGDEBUG, "  Processor level: 0x%x\n", si->wProcessorLevel);
384   CLog::Log(LOGDEBUG, "  Processor revision: 0x%x\n", si->wProcessorRevision);
385 }
386 #endif
387
388 extern "C" void WINAPI dllGetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
389 {
390 #ifdef API_DEBUG
391   CLog::Log(LOGDEBUG, "GetSystemInfo(0x%x) =>", lpSystemInfo);
392 #endif
393 #ifdef _WIN32
394   // VS 2003 complains about x even so it's defined
395   lpSystemInfo->wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
396 #else
397   lpSystemInfo->x.wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
398 #endif
399   lpSystemInfo->dwPageSize = 4096;   //Xbox page size
400   lpSystemInfo->lpMinimumApplicationAddress = (void *)0x00000000;
401   lpSystemInfo->lpMaximumApplicationAddress = (void *)0x7fffffff;
402   lpSystemInfo->dwActiveProcessorMask = 1;
403   lpSystemInfo->dwNumberOfProcessors = 1;
404   lpSystemInfo->dwProcessorType = 586;  //#define PROCESSOR_INTEL_PENTIUM 586
405   lpSystemInfo->wProcessorLevel = 6;
406   //lpSystemInfo->wProcessorLevel = 5;
407   lpSystemInfo->wProcessorRevision = 0x080A;
408   lpSystemInfo->dwAllocationGranularity = 0x10000; //virtualalloc reserve block size
409 #ifdef API_DEBUG
410   DumpSystemInfo(lpSystemInfo);
411 #endif
412 }  //hardcode for xbox processor type;
413
414 extern "C" UINT WINAPI dllGetPrivateProfileIntA(
415     LPCSTR lpAppName,
416     LPCSTR lpKeyName,
417     INT nDefault,
418     LPCSTR lpFileName)
419 {
420   not_implement("kernel32.dll fake function GetPrivateProfileIntA called\n"); //warning
421   return nDefault;
422 }
423
424 //globals for memory leak hack, no need for well-behaved dlls call init/del in pair
425 //We can free the sections if applications does not call deletecriticalsection
426 //need to initialize the list head NULL at mplayer_open_file, and free memory at close file.
427 std::map<LPCRITICAL_SECTION, LPCRITICAL_SECTION> g_mapCriticalSection;
428
429 extern "C" void WINAPI dllDeleteCriticalSection(LPCRITICAL_SECTION cs)
430 {
431 #ifdef API_DEBUG
432   CLog::Log(LOGDEBUG, "DeleteCriticalSection(0x%x)", cs);
433 #endif
434   if (g_mapCriticalSection.find(cs) != g_mapCriticalSection.end())
435   {
436     LPCRITICAL_SECTION cs_new = g_mapCriticalSection[cs];
437     DeleteCriticalSection(cs_new);
438     delete cs_new;
439     g_mapCriticalSection.erase(cs);
440   }
441 }
442
443 extern "C" void WINAPI dllInitializeCriticalSection(LPCRITICAL_SECTION cs)
444 {
445 #ifdef API_DEBUG
446   CLog::Log(LOGDEBUG, "InitializeCriticalSection(0x%x)", cs);
447 #endif
448   LPCRITICAL_SECTION cs_new = new CRITICAL_SECTION;
449   memset(cs_new, 0, sizeof(CRITICAL_SECTION));
450   InitializeCriticalSection(cs_new);
451
452   // just take the first member of the CRITICAL_SECTION to save ourdata in, this will be used to
453   // get fast access to the new critial section in dllLeaveCriticalSection and dllEnterCriticalSection
454   ((LPCRITICAL_SECTION*)cs)[0] = cs_new;
455   g_mapCriticalSection[cs] = cs_new;
456 }
457
458 extern "C" void WINAPI dllLeaveCriticalSection(LPCRITICAL_SECTION cs)
459 {
460 #ifdef API_DEBUG
461   CLog::Log(LOGDEBUG, "LeaveCriticalSection(0x%x) %p\n", ((LPCRITICAL_SECTION*)cs)[0]);
462 #endif
463   LeaveCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
464 }
465
466 extern "C" void WINAPI dllEnterCriticalSection(LPCRITICAL_SECTION cs)
467 {
468 #ifdef API_DEBUG
469   CLog::Log(LOGDEBUG, "EnterCriticalSection(0x%x) %p\n", cs, ((LPCRITICAL_SECTION*)cs)[0]);
470 #endif
471 #ifndef _LINUX
472   if (!(LPCRITICAL_SECTION)cs->OwningThread)
473   {
474 #ifdef API_DEBUG
475     CLog::Log(LOGDEBUG, "entered uninitialized critisec!\n");
476 #endif
477     dllInitializeCriticalSection(cs);
478   }
479 #endif
480   EnterCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
481 }
482
483 extern "C" DWORD WINAPI dllGetVersion()
484 {
485 #ifdef API_DEBUG
486   CLog::Log(LOGDEBUG, "GetVersion() => 0xC0000004 (Windows 95)\n");
487 #endif
488   //return 0x0a280105; //Windows XP
489   return 0xC0000004; //Windows 95
490 }
491
492 extern "C" BOOL WINAPI dllGetVersionExA(LPOSVERSIONINFO lpVersionInfo)
493 {
494 #ifdef API_DEBUG
495   CLog::Log(LOGDEBUG, "GetVersionExA()\n");
496 #endif
497   lpVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
498   lpVersionInfo->dwMajorVersion = 4;
499   lpVersionInfo->dwMinorVersion = 0;
500   lpVersionInfo->dwBuildNumber = 0x4000457;
501   // leave it here for testing win9x-only codecs
502   lpVersionInfo->dwPlatformId = 1; //VER_PLATFORM_WIN32_WINDOWS
503   lpVersionInfo->szCSDVersion[0] = 0;
504 #ifdef API_DEBUG
505   CLog::Log(LOGDEBUG, "  Major version: %d\n  Minor version: %d\n  Build number: %x\n"
506             "  Platform Id: %d\n Version string: '%s'\n",
507             lpVersionInfo->dwMajorVersion, lpVersionInfo->dwMinorVersion,
508             lpVersionInfo->dwBuildNumber, lpVersionInfo->dwPlatformId, lpVersionInfo->szCSDVersion);
509 #endif
510   return TRUE;
511 }
512
513 extern "C" BOOL WINAPI dllGetVersionExW(LPOSVERSIONINFOW lpVersionInfo)
514 {
515 #ifdef API_DEBUG
516   CLog::Log(LOGDEBUG, "GetVersionExW()\n");
517 #endif
518   if(!dllGetVersionExA((LPOSVERSIONINFO)lpVersionInfo))
519     return FALSE;
520
521   lpVersionInfo->szCSDVersion[0] = 0;
522   lpVersionInfo->szCSDVersion[1] = 0;
523   return TRUE;
524 }
525
526 extern "C" UINT WINAPI dllGetProfileIntA(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault)
527 {
528   //  CLog::Log(LOGDEBUG,"GetProfileIntA:%s %s %i", lpAppName,lpKeyName,nDefault);
529   not_implement("kernel32.dll fake function GetProfileIntA called\n"); //warning
530   return nDefault;
531 }
532
533 extern "C" BOOL WINAPI dllFreeEnvironmentStringsW(LPWSTR lpString)
534 {
535   // we don't have anything to clean up here, just return.
536 #ifdef API_DEBUG
537   CLog::Log(LOGDEBUG, "FreeEnvironmentStringsA(0x%x) => 1", lpString);
538 #endif
539   return true;
540 }
541
542 extern "C" HMODULE WINAPI dllGetOEMCP()
543 {
544   not_implement("kernel32.dll fake function GetOEMCP called\n"); //warning
545   return NULL;
546 }
547
548 extern "C" HMODULE WINAPI dllRtlUnwind(PVOID TargetFrame OPTIONAL, PVOID TargetIp OPTIONAL, PEXCEPTION_RECORD ExceptionRecord OPTIONAL, PVOID ReturnValue)
549 {
550   not_implement("kernel32.dll fake function RtlUnwind called\n"); //warning
551   return NULL;
552 }
553 extern "C" LPTSTR WINAPI dllGetCommandLineA()
554 {
555 #ifdef API_DEBUG
556   CLog::Log(LOGDEBUG, "GetCommandLineA() => \"c:\\xbmc.xbe\"\n");
557 #endif
558   return (LPTSTR)"c:\\xbmc.xbe";
559 }
560
561 extern "C" HMODULE WINAPI dllExitProcess(UINT uExitCode)
562 {
563   not_implement("kernel32.dll fake function ExitProcess called\n"); //warning
564   return NULL;
565 }
566 extern "C" HMODULE WINAPI dllTerminateProcess(HANDLE hProcess, UINT uExitCode)
567 {
568   not_implement("kernel32.dll fake function TerminateProcess called\n"); //warning
569   return NULL;
570 }
571 extern "C" HANDLE WINAPI dllGetCurrentProcess()
572 {
573 #if !defined (_XBOX) && !defined(_LINUX)
574   return GetCurrentProcess();
575 #else
576 #ifdef _WIN32
577   return GetCurrentProcess();
578 #endif
579 #ifdef API_DEBUG
580   CLog::Log(LOGDEBUG, "GetCurrentProcess(void) => 9375");
581 #endif
582   return (HANDLE)9375;
583 #endif
584 }
585
586 extern "C" UINT WINAPI dllGetACP()
587 {
588 #ifdef API_DEBUG
589   CLog::Log(LOGDEBUG, "GetACP() => 0");
590 #endif
591   return CP_ACP;
592 }
593
594 extern "C" UINT WINAPI dllSetHandleCount(UINT uNumber)
595 {
596   //Under Windows NT and Windows 95, this function simply returns the value specified in the uNumber parameter.
597   //return uNumber;
598 #ifdef API_DEBUG
599   CLog::Log(LOGDEBUG, "SetHandleCount(0x%x) => 1\n", uNumber);
600 #endif
601   return uNumber;
602 }
603
604 extern "C" HANDLE WINAPI dllGetStdHandle(DWORD nStdHandle)
605 {
606   switch (nStdHandle)
607   {
608   case STD_INPUT_HANDLE: return (HANDLE)0;
609   case STD_OUTPUT_HANDLE: return (HANDLE)1;
610   case STD_ERROR_HANDLE: return (HANDLE)2;
611   }
612   SetLastError( ERROR_INVALID_PARAMETER );
613   return INVALID_HANDLE_VALUE;
614 }
615
616 #ifdef _XBOX
617 #define FILE_TYPE_UNKNOWN       0
618 #define FILE_TYPE_DISK          1
619 #define FILE_TYPE_CHAR          2
620 #endif
621
622 extern "C" DWORD WINAPI dllGetFileType(HANDLE hFile)
623 {
624 #ifdef API_DEBUG
625   CLog::Log(LOGDEBUG, "GetFileType(0x%x) => 0x3 = pipe", hFile);
626 #endif
627   return 3;
628 }
629
630 extern "C" int WINAPI dllGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
631 {
632 #ifdef API_DEBUG
633   CLog::Log(LOGDEBUG, "GetStartupInfoA(0x%x) => 1\n");
634 #endif
635   lpStartupInfo->cb = sizeof(_STARTUPINFOA);
636   lpStartupInfo->cbReserved2 = 0;
637   lpStartupInfo->dwFillAttribute = 0;
638   lpStartupInfo->dwFlags = 0;
639   lpStartupInfo->dwX = 50; //
640   lpStartupInfo->dwXCountChars = 0;
641   lpStartupInfo->dwXSize = 0;
642   lpStartupInfo->dwY = 50; //
643   lpStartupInfo->dwYCountChars = 0;
644   lpStartupInfo->dwYSize = 0;
645   lpStartupInfo->hStdError = (HANDLE)2;
646   lpStartupInfo->hStdInput = (HANDLE)0;
647   lpStartupInfo->hStdOutput = (HANDLE)1;
648   lpStartupInfo->lpDesktop = NULL;
649   lpStartupInfo->lpReserved = NULL;
650   lpStartupInfo->lpReserved2 = 0;
651   lpStartupInfo->lpTitle = (LPTSTR)"XBMC";
652   lpStartupInfo->wShowWindow = 0;
653   return 1;
654 }
655
656 extern "C" BOOL WINAPI dllFreeEnvironmentStringsA(LPSTR lpString)
657 {
658   // we don't have anything to clean up here, just return.
659   return true;
660 }
661
662 static const char ch_envs[] =
663   "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELETED,1\r\n"
664   "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
665
666 extern "C" LPVOID WINAPI dllGetEnvironmentStrings()
667 {
668 #ifdef _WIN32
669   return GetEnvironmentStrings();
670 #endif
671 #ifdef API_DEBUG
672   CLog::Log(LOGDEBUG, "GetEnvironmentStrings() => 0x%x = %p", ch_envs, ch_envs);
673 #endif
674   return (LPVOID)ch_envs;
675 }
676
677 extern "C" LPVOID WINAPI dllGetEnvironmentStringsW()
678 {
679 #ifdef _WIN32
680   return GetEnvironmentStringsW();
681 #endif
682   return 0;
683 }
684
685 extern "C" int WINAPI dllGetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
686 {
687 #ifdef _WIN32
688   return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
689 #endif
690   if (lpBuffer) lpBuffer[0] = 0;
691
692   if (strcmp(lpName, "__MSVCRT_HEAP_SELECT") == 0)
693     strcpy(lpBuffer, "__GLOBAL_HEAP_SELECTED,1");
694 #ifdef API_DEBUG
695   CLog::Log(LOGDEBUG, "GetEnvironmentVariableA('%s', 0x%x, %d) => %d", lpName, lpBuffer, nSize, strlen(lpBuffer));
696 #endif
697   return strlen(lpBuffer);
698 }
699
700 extern "C" HMODULE WINAPI dllLCMapStringA(LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest)
701 {
702   not_implement("kernel32.dll fake function LCMapStringA called\n"); //warning
703   return NULL;
704 }
705
706 extern "C" HMODULE WINAPI dllLCMapStringW(LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest)
707 {
708   not_implement("kernel32.dll fake function LCMapStringW called\n"); //warning
709   return NULL;
710 }
711
712 extern "C" HMODULE WINAPI dllSetStdHandle(DWORD nStdHandle, HANDLE hHandle)
713 {
714   not_implement("kernel32.dll fake function SetStdHandle called\n"); //warning
715   return NULL;
716 }
717
718 extern "C" HMODULE WINAPI dllGetStringTypeA(LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
719 {
720   not_implement("kernel32.dll fake function GetStringTypeA called\n"); //warning
721   return NULL;
722 }
723
724 extern "C" HMODULE WINAPI dllGetStringTypeW(DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
725 {
726   not_implement("kernel32.dll fake function GetStringTypeW called\n"); //warning
727   return NULL;
728 }
729
730 extern "C" HMODULE WINAPI dllGetCPInfo(UINT CodePage, LPCPINFO lpCPInfo)
731 {
732   not_implement("kernel32.dll fake function GetCPInfo called\n"); //warning
733   return NULL;
734 }
735
736 extern "C" LCID WINAPI dllGetThreadLocale(void)
737 {
738   // primary language identifier, sublanguage identifier, sorting identifier
739   return MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
740 }
741
742 extern "C" BOOL WINAPI dllSetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass)
743 {
744   not_implement("kernel32.dll fake function SetPriorityClass called\n"); //warning
745   return false;
746 }
747
748 extern "C" DWORD WINAPI dllFormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, va_list* Arguments)
749 {
750 #ifdef _WIN32
751   return FormatMessageA(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
752 #else
753   not_implement("kernel32.dll fake function FormatMessage called\n"); //warning
754   return 0;
755 #endif
756 }
757
758 extern "C" DWORD WINAPI dllGetFullPathNameA(LPCTSTR lpFileName, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR* lpFilePart)
759 {
760 #ifdef _WIN32
761   if (!lpFileName) return 0;
762   if(strstr(lpFileName, "://"))
763   {
764     unsigned int length = strlen(lpFileName);
765     if (nBufferLength < (length + 1))
766       return length + 1;
767     else
768     {
769       strcpy(lpBuffer, lpFileName);
770       if(lpFilePart)
771       {
772         char* s1 = strrchr(lpBuffer, '\\');
773         char* s2 = strrchr(lpBuffer, '/');
774         if(s2 && s1 > s2)
775           *lpFilePart = s1 + 1;
776         else if(s1 && s2 > s1)
777           *lpFilePart = s2 + 1;
778         else
779           *lpFilePart = lpBuffer;
780       }
781       return length;
782     }
783   }
784   return GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, lpFilePart);
785 #else
786   not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
787   return 0;
788 #endif
789 }
790
791 extern "C" DWORD WINAPI dllGetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart)
792 {
793 #ifdef _WIN32
794   if (!lpFileName) return 0;
795   if(wcsstr(lpFileName, L"://"))
796   {
797     size_t length = wcslen(lpFileName);
798     if (nBufferLength < (length + 1))
799       return length + 1;
800     else
801     {
802       wcscpy(lpBuffer, lpFileName);
803       if(lpFilePart)
804       {
805         wchar_t* s1 = wcsrchr(lpBuffer, '\\');
806         wchar_t* s2 = wcsrchr(lpBuffer, '/');
807         if(s2 && s1 > s2)
808           *lpFilePart = s1 + 1;
809         else if(s1 && s2 > s1)
810           *lpFilePart = s2 + 1;
811         else
812           *lpFilePart = lpBuffer;
813       }
814       return length;
815     }
816   }
817   return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
818 #else
819   not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
820   return 0;
821 #endif
822 }
823
824 extern "C" DWORD WINAPI dllExpandEnvironmentStringsA(LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize)
825 {
826 #ifdef _WIN32
827   return ExpandEnvironmentStringsA(lpSrc, lpDst, nSize);
828 #else
829   not_implement("kernel32.dll fake function ExpandEnvironmentStringsA called\n"); //warning
830 #endif
831   return 0;
832 }
833
834 extern "C" UINT WINAPI dllGetWindowsDirectoryA(LPTSTR lpBuffer, UINT uSize)
835 {
836   not_implement("kernel32.dll fake function dllGetWindowsDirectory called\n"); //warning
837   return 0;
838 }
839
840 extern "C" UINT WINAPI dllGetSystemDirectoryA(LPTSTR lpBuffer, UINT uSize)
841 {
842   //char* systemdir = "special://xbmc/system/mplayer/codecs";
843   //unsigned int len = strlen(systemdir);
844   //if (len > uSize) return 0;
845   //strcpy(lpBuffer, systemdir);
846   //not_implement("kernel32.dll incompete function dllGetSystemDirectory called\n"); //warning
847   //CLog::Log(LOGDEBUG,"KERNEL32!GetSystemDirectoryA(0x%x, %d) => %s", lpBuffer, uSize, systemdir);
848   //return len;
849 #ifdef API_DEBUG
850   CLog::Log(LOGDEBUG, "GetSystemDirectoryA(%p,%d)\n", lpBuffer, uSize);
851 #endif
852   if (!lpBuffer) strcpy(lpBuffer, ".");
853   return 1;
854 }
855
856
857 extern "C" UINT WINAPI dllGetShortPathName(LPTSTR lpszLongPath, LPTSTR lpszShortPath, UINT cchBuffer)
858 {
859   if (!lpszLongPath) return 0;
860   if (strlen(lpszLongPath) == 0)
861   {
862     //strcpy(lpszLongPath, "special://xbmc/system/mplayer/codecs/QuickTime.qts");
863   }
864 #ifdef API_DEBUG
865   CLog::Log(LOGDEBUG, "KERNEL32!GetShortPathNameA('%s',%p,%d)\n", lpszLongPath, lpszShortPath, cchBuffer);
866 #endif
867   strcpy(lpszShortPath, lpszLongPath);
868   return strlen(lpszShortPath);
869 }
870
871 extern "C" HANDLE WINAPI dllGetProcessHeap()
872 {
873 #ifdef  _LINUX
874   CLog::Log(LOGWARNING, "KERNEL32!GetProcessHeap() linux cant provide this service!");
875   return 0;
876 #else
877   HANDLE hHeap;
878   hHeap = GetProcessHeap();
879 #ifdef API_DEBUG
880   CLog::Log(LOGDEBUG, "KERNEL32!GetProcessHeap() => 0x%x", hHeap);
881 #endif
882   return hHeap;
883 #endif
884 }
885
886 extern "C" UINT WINAPI dllSetErrorMode(UINT i)
887 {
888 #ifdef API_DEBUG
889   CLog::Log(LOGDEBUG, "SetErrorMode(%d) => 0\n", i);
890 #endif
891   return 0;
892 }
893
894 extern "C" BOOL WINAPI dllIsProcessorFeaturePresent(DWORD ProcessorFeature)
895 {
896   BOOL result = 0;
897   switch (ProcessorFeature)
898   {
899   case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
900     result = false;
901     break;
902   case PF_COMPARE_EXCHANGE_DOUBLE:
903     result = true;
904     break;
905   case PF_FLOATING_POINT_EMULATED:
906     result = true;
907     break;
908   case PF_FLOATING_POINT_PRECISION_ERRATA:
909     result = false;
910     break;
911   case PF_MMX_INSTRUCTIONS_AVAILABLE:
912     result = true;
913     break;
914   case PF_PAE_ENABLED:
915     result = false;
916     break;
917   case PF_RDTSC_INSTRUCTION_AVAILABLE:
918     result = true;
919     break;
920   case PF_XMMI_INSTRUCTIONS_AVAILABLE:
921     result = true;
922     break;
923   case 10: //PF_XMMI64_INSTRUCTIONS_AVAILABLE
924     result = false;
925     break;
926   }
927
928 #ifdef API_DEBUG
929   CLog::Log(LOGDEBUG, "IsProcessorFeaturePresent(0x%x) => 0x%x\n", ProcessorFeature, result);
930 #endif
931   return result;
932 }
933
934 extern "C" DWORD WINAPI dllTlsAlloc()
935 {
936   DWORD retval = TlsAlloc();
937 #ifdef API_DEBUG
938   CLog::Log(LOGDEBUG, "TlsAlloc() => %d\n", retval);
939 #endif
940   return retval;
941 }
942
943 extern "C" BOOL WINAPI dllTlsFree(DWORD dwTlsIndex)
944 {
945   BOOL retval = TlsFree(dwTlsIndex);
946 #ifdef API_DEBUG
947   CLog::Log(LOGDEBUG, "KERNEL32!TlsFree(%d) => %d", dwTlsIndex, retval);
948 #endif
949   return retval;
950 }
951
952 extern "C" BOOL WINAPI dllTlsSetValue(int dwTlsIndex, LPVOID lpTlsValue)
953 {
954   if (dwTlsIndex == -1)
955     return FALSE;
956   BOOL retval = TlsSetValue(dwTlsIndex, lpTlsValue);
957
958 #ifdef API_DEBUG
959   CLog::Log(LOGDEBUG, "KERNEL32!TlsSetValue(%d, 0x%x) => %d", dwTlsIndex, lpTlsValue, retval);
960 #endif
961   return retval;
962 }
963
964 extern "C" LPVOID WINAPI dllTlsGetValue(DWORD dwTlsIndex)
965 {
966   if(dwTlsIndex == (DWORD)(-1))
967     return NULL;
968   LPVOID retval = TlsGetValue(dwTlsIndex);
969
970 #ifdef API_DEBUG
971   CLog::Log(LOGDEBUG, "KERNEL32!TlsGetValue(%d) => 0x%x", dwTlsIndex, retval);
972 #endif
973   return retval;
974 }
975
976 extern "C" UINT WINAPI dllGetCurrentDirectoryA(UINT c, LPSTR s)
977 {
978   char curdir[] = "special://xbmc/";
979   int result;
980   strncpy(s, curdir, c);
981   result = 1 + ((c < strlen(curdir)) ? c : strlen(curdir));
982 #ifdef API_DEBUG
983   CLog::Log(LOGDEBUG, "GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
984 #endif
985   return result;
986 }
987
988 extern "C" UINT WINAPI dllSetCurrentDirectoryA(const char *pathname)
989 {
990 #ifdef API_DEBUG
991   CLog::Log(LOGDEBUG, "SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
992 #endif
993   return 1;
994 }
995
996 extern "C" int WINAPI dllSetUnhandledExceptionFilter(void* filter)
997 {
998 #ifdef API_DEBUG
999   CLog::Log(LOGDEBUG, "SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
1000 #endif
1001   return 1; //unsupported and probably won't ever be supported
1002 }
1003
1004 extern "C" int WINAPI dllSetEnvironmentVariableA(const char *name, const char *value)
1005 {
1006 #ifdef API_DEBUG
1007   CLog::Log(LOGDEBUG, "SetEnvironmentVariableA(%s, %s)\n", name, value);
1008 #endif
1009   return 0;
1010 }
1011
1012 extern "C" int WINAPI dllCreateDirectoryA(const char *pathname, void *sa)
1013 {
1014 #ifdef API_DEBUG
1015   CLog::Log(LOGDEBUG, "CreateDirectory(0x%x = %s, 0x%x) => 1\n", pathname, pathname, sa);
1016 #endif
1017   return 1;
1018 }
1019
1020 extern "C" DWORD WINAPI dllWaitForSingleObject(HANDLE hHandle, DWORD dwMiliseconds)
1021 {
1022 #ifdef API_DEBUG
1023   CLog::Log(LOGDEBUG, "WaitForSingleObject(0x%x, %d)", hHandle, dwMiliseconds);
1024 #endif
1025   return WaitForSingleObject(hHandle, dwMiliseconds);
1026 }
1027
1028 #ifdef _LINUX
1029 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
1030 #else
1031 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
1032 #endif
1033 {
1034 #ifdef API_DEBUG
1035   CLog::Log(LOGDEBUG, "WaitForMultipleObjects(..)");
1036 #endif
1037
1038   return WaitForMultipleObjects(nCount, lpHandles, fWaitAll, dwMilliseconds);
1039 }
1040
1041 extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProcessAffinityMask, LPDWORD lpSystemAffinityMask)
1042 {
1043   CLog::Log(LOGDEBUG, "GetProcessAffinityMask(%p, %p, %p) => 1\n",
1044             (void*)hProcess, (void*)lpProcessAffinityMask, (void*)lpSystemAffinityMask);
1045   if (lpProcessAffinityMask)*lpProcessAffinityMask = 1;
1046   if (lpSystemAffinityMask)*lpSystemAffinityMask = 1;
1047   return 1;
1048 }
1049
1050 extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData)
1051 {
1052   if (Locale == LOCALE_SYSTEM_DEFAULT || Locale == LOCALE_USER_DEFAULT)
1053   {
1054     if (LCType == LOCALE_SISO639LANGNAME)
1055     {
1056       if (cchData > 3)
1057       {
1058         strcpy(lpLCData, "eng");
1059         return 4;
1060       }
1061     }
1062     else if (LCType == LOCALE_SISO3166CTRYNAME)
1063     {
1064       if (cchData > 2)
1065       {
1066         strcpy(lpLCData, "US");
1067         return 3;
1068       }
1069     }
1070     else if (LCType == LOCALE_IDEFAULTLANGUAGE)
1071     {
1072       if (cchData > 5)
1073       {
1074         strcpy(lpLCData, "en-US");
1075         return 6;
1076       }
1077     }
1078   }
1079
1080   not_implement("kernel32.dll incomplete function GetLocaleInfoA called\n");  //warning
1081   SetLastError(ERROR_INVALID_FUNCTION);
1082   return 0;
1083 }
1084
1085 extern "C" UINT WINAPI dllGetConsoleCP()
1086 {
1087   return 437; // OEM - United States
1088 }
1089
1090 extern "C" UINT WINAPI dllGetConsoleOutputCP()
1091 {
1092   return 437; // OEM - United States
1093 }
1094
1095 // emulated because windows expects different behaviour
1096 // the xbox calculates always 1 character extra for 0 termination
1097 // however, this is only desired when cbMultiByte has the value -1
1098 extern "C" int WINAPI dllMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
1099 {
1100   // first fix, on windows cchWideChar and cbMultiByte may be the same.
1101   // xbox fails, because it expects cbMultiByte to be at least one character bigger
1102   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1103   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1104   int destinationBufferSize = cchWideChar;
1105   LPWSTR destinationBuffer = lpWideCharStr;
1106   if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1107     destinationBufferSize++;
1108     destinationBuffer = (LPWSTR)malloc(destinationBufferSize * sizeof(WCHAR));
1109   }
1110
1111   int ret = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, destinationBuffer, destinationBufferSize);
1112
1113   if (ret > 0)
1114   {
1115     // second fix, but only if cchWideChar == 0, and ofcours ret > 0 indicating the function
1116     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1117     if (cchWideChar == 0) {
1118       ret--;
1119     }
1120
1121     // revert the first fix again
1122     if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1123       // the 0 termination character could never have been written on a windows machine
1124       // because of cchWideChar == cbMultiByte, again xbox added one for it.
1125       ret--;
1126
1127       memcpy(lpWideCharStr, destinationBuffer, ret * sizeof(WCHAR));
1128       free(destinationBuffer);
1129     }
1130   }
1131
1132   return ret;
1133 }
1134
1135 // same reason as above
1136 extern "C" int WINAPI dllWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
1137 {
1138   // first fix, on windows cchWideChar and cbMultiByte may be the same.
1139   // xbox fails, because it expects cbMultiByte to be at least one character bigger
1140   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1141   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1142   int destinationBufferSize = cbMultiByte;
1143   LPSTR destinationBuffer = lpMultiByteStr;
1144   if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1145     destinationBufferSize++;
1146     destinationBuffer = (LPSTR)malloc(destinationBufferSize * sizeof(char));
1147   }
1148
1149   int ret = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, destinationBuffer, destinationBufferSize, lpDefaultChar, lpUsedDefaultChar);
1150
1151   if (ret > 0)
1152   {
1153     // second fix, but only if cbMultiByte == 0, and ofcours ret > 0 indicating the function
1154     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1155     if (cbMultiByte == 0) {
1156       ret--;
1157     }
1158
1159     // revert the first fix again
1160     if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1161       // the 0 termination character could never have been written on a windows machine
1162       // because of cchWideChar == cbMultiByte, again xbox added one for it.
1163       ret--;
1164
1165       memcpy(lpMultiByteStr, destinationBuffer, ret);
1166       free(destinationBuffer);
1167     }
1168   }
1169
1170   return ret;
1171 }
1172
1173 extern "C" UINT WINAPI dllSetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
1174 {
1175 #ifdef _WIN32
1176   return SetConsoleCtrlHandler(HandlerRoutine, Add);
1177 #else
1178   // no consoles exists on the xbox, do nothing
1179   not_implement("kernel32.dll fake function SetConsoleCtrlHandler called\n");  //warning
1180   SetLastError(ERROR_INVALID_FUNCTION);
1181   return 0;
1182 #endif
1183 }
1184
1185 typedef struct _SFlsSlot
1186 {
1187   LONG lInUse;
1188   PVOID pData;
1189   PFLS_CALLBACK_FUNCTION pCallback;
1190 }
1191 SFlsSlot, *LPSFlsSlot;
1192
1193 #define FLS_NUM_SLOTS 5
1194 #if defined (_XBOX) || defined (_LINUX)
1195 #define FLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
1196 #endif
1197 SFlsSlot flsSlots[FLS_NUM_SLOTS] = { { false, NULL, NULL } };
1198
1199 extern "C" DWORD WINAPI dllFlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
1200 {
1201   DWORD i;
1202 #ifdef API_DEBUG
1203   CLog::Log(LOGDEBUG, "FlsAlloc(0x%x)\n", lpCallback);
1204 #endif
1205   for (i = 0; i < FLS_NUM_SLOTS; i++) {
1206     if( InterlockedCompareExchange(&flsSlots[i].lInUse, 1, 0) == 0 ) {
1207       flsSlots[i].pData = NULL;
1208       flsSlots[i].pCallback = lpCallback;
1209       return i;
1210     }
1211   }
1212   SetLastError(ERROR_INVALID_PARAMETER);
1213   CLog::Log(LOGERROR, " - Out of fls slots");
1214   return FLS_OUT_OF_INDEXES; // "
1215 }
1216
1217 static LPSFlsSlot FlsGetSlot(DWORD dwFlsIndex)
1218 {
1219   if (dwFlsIndex >= FLS_NUM_SLOTS) {
1220     SetLastError(ERROR_INVALID_PARAMETER);
1221     return NULL;
1222   }
1223   if (flsSlots[dwFlsIndex].lInUse != 1) {
1224     SetLastError(ERROR_INVALID_PARAMETER); // actually ERROR_NO_MEMORY would be correct
1225     return NULL;
1226   }
1227   return &(flsSlots[dwFlsIndex]);
1228 }
1229
1230 extern "C" BOOL WINAPI dllFlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
1231 {
1232 #ifdef API_DEBUG
1233   CLog::Log(LOGDEBUG, "FlsSetValue(%d, 0x%x) => 0x%x\n", dwFlsIndex, lpFlsData);
1234 #endif
1235   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1236   if (slot == NULL)
1237     return false;
1238   slot->pData = lpFlsData;
1239   return true;
1240 }
1241
1242 extern "C" PVOID WINAPI dllFlsGetValue(DWORD dwFlsIndex)
1243 {
1244 #ifdef API_DEBUG
1245   CLog::Log(LOGDEBUG, "FlsGetValue(%d)\n", dwFlsIndex);
1246 #endif
1247   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1248   return (slot == NULL) ? NULL : slot->pData;
1249 }
1250
1251 extern "C" BOOL WINAPI dllFlsFree(DWORD dwFlsIndex)
1252 {
1253 #ifdef API_DEBUG
1254   CLog::Log(LOGDEBUG, "FlsFree(%d)\n", dwFlsIndex);
1255 #endif
1256   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1257   if (slot == NULL)
1258     return false;
1259
1260   if( slot->pCallback )
1261     slot->pCallback(slot->pData);
1262
1263   slot->pData = NULL;
1264   slot->lInUse = 0;
1265
1266   return true;
1267 }
1268
1269
1270 extern "C" PVOID WINAPI dllEncodePointer(PVOID ptr)
1271 {
1272   return ptr;
1273 }
1274
1275 extern "C" PVOID WINAPI dllDecodePointer(PVOID ptr)
1276 {
1277   return ptr;
1278 }
1279
1280
1281 extern "C" HANDLE WINAPI dllCreateFileA(
1282     IN LPCSTR lpFileName,
1283     IN DWORD dwDesiredAccess,
1284     IN DWORD dwShareMode,
1285     IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1286     IN DWORD dwCreationDisposition,
1287     IN DWORD dwFlagsAndAttributes,
1288     IN HANDLE hTemplateFile
1289     )
1290 {
1291   return CreateFileA(_P(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
1292 }
1293
1294 extern "C" BOOL WINAPI dllLockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh)
1295 {
1296   //return LockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh);
1297   return TRUE;
1298 }
1299
1300 extern "C" BOOL WINAPI dllLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh, LPOVERLAPPED lpOverlapped)
1301 {
1302   //return LockFileEx(hFile, dwFlags, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh, lpOverlapped);
1303   return TRUE;
1304 }
1305
1306 extern "C" BOOL WINAPI dllUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1307 {
1308   //return UnlockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1309   return TRUE;
1310 }
1311
1312 extern "C" DWORD WINAPI dllGetTempPathA(DWORD nBufferLength, LPTSTR lpBuffer)
1313 {
1314   // If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer,
1315   // not including the terminating null character. If the return value is greater than nBufferLength,
1316   // the return value is the size of the buffer required to hold the path.
1317   const char* tempPath = "special://temp/temp/";
1318   unsigned int len = strlen(tempPath);
1319
1320   if (nBufferLength > len)
1321   {
1322     strcpy(lpBuffer, tempPath);
1323   }
1324
1325   return len;
1326 }
1327
1328 extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE hModule, HRSRC hResInfo)
1329 {
1330   not_implement("kernel32.dll fake function LoadResource called\n");
1331   return NULL;
1332 }
1333
1334 extern "C" HRSRC WINAPI dllFindResourceA(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
1335 {
1336   not_implement("kernel32.dll fake function FindResource called\n");
1337   return NULL;
1338 }
1339
1340
1341 /*
1342
1343 The following routine was hacked up by JM while looking at why the DVD player was failing
1344 in the middle of the movie.  The symptoms were:
1345
1346 1. DVD player returned error about expecting a NAV packet but none found.
1347 2. Resulted in DVD player closing.
1348 3. Always occured in the same place.
1349 4. Occured on every DVD I tried (originals)
1350 5. Approximately where I would expect the layer change to be (ie just over half way
1351    through the movie)
1352 6. Resulted in the last chunk of the requested data to be NULL'd out completely.  ReadFile()
1353    returns correctly, but the last chunk is completely zero'd out.
1354
1355 This routine checks the last chunk for zeros, and re-reads if necessary.
1356 */
1357 #define DVD_CHUNK_SIZE 2048
1358
1359 extern "C" BOOL WINAPI dllDVDReadFileLayerChangeHack(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
1360 {
1361   BOOL ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
1362   if (!ret || !lpNumberOfBytesRead || *lpNumberOfBytesRead < DVD_CHUNK_SIZE) return ret;
1363   DWORD numChecked = *lpNumberOfBytesRead;
1364   while (numChecked >= DVD_CHUNK_SIZE)
1365   {
1366     BYTE *p = (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE;
1367     // test for a NULL block
1368     while (*p == 0 && p < (BYTE *)lpBuffer + numChecked)
1369       p++;
1370     if (p == (BYTE *)lpBuffer + numChecked)
1371     { // fully NULL block - reread
1372 #ifdef _WIN32
1373       LONG low = 0;
1374       LONG high = 0;
1375 #else
1376       int32_t low = 0;
1377       int32_t high = 0;
1378 #endif
1379       low = SetFilePointer(hFile, low, &high, FILE_CURRENT);
1380       CLog::Log(LOGWARNING,
1381                 "DVDReadFile() warning - "
1382                 "invalid data read from block at %i (%i) - rereading",
1383                 low, high);
1384       SetFilePointer(hFile, (int)numChecked - (int)*lpNumberOfBytesRead - DVD_CHUNK_SIZE, NULL, FILE_CURRENT);
1385       DWORD numRead;
1386       ret = ReadFile(hFile, (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE, DVD_CHUNK_SIZE, &numRead, lpOverlapped);
1387       if (!ret) return FALSE;
1388       SetFilePointer(hFile, low, &high, FILE_BEGIN);
1389     }
1390     numChecked -= DVD_CHUNK_SIZE;
1391   }
1392   return ret;
1393 }
1394
1395 extern "C" LPVOID WINAPI dllLockResource(HGLOBAL hResData)
1396 {
1397 #ifdef _WIN32
1398   return LockResource(hResData);
1399 #else
1400   not_implement("kernel32.dll fake function LockResource called\n"); //warning
1401   return 0;
1402 #endif
1403 }
1404
1405 extern "C" SIZE_T WINAPI dllGlobalSize(HGLOBAL hMem)
1406 {
1407 #ifdef _WIN32
1408   return GlobalSize(hMem);
1409 #else
1410   not_implement("kernel32.dll fake function GlobalSize called\n"); //warning
1411   return 0;
1412 #endif
1413 }
1414
1415 extern "C" DWORD WINAPI dllSizeofResource(HMODULE hModule, HRSRC hResInfo)
1416 {
1417 #ifdef _WIN32
1418   return SizeofResource(hModule, hResInfo);
1419 #else
1420   not_implement("kernel32.dll fake function SizeofResource called\n"); //warning
1421   return 0;
1422 #endif
1423 }