Removed currently unused Tls functionality.
[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 #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" UINT WINAPI dllGetCurrentDirectoryA(UINT c, LPSTR s)
935 {
936   char curdir[] = "special://xbmc/";
937   int result;
938   strncpy(s, curdir, c);
939   result = 1 + ((c < strlen(curdir)) ? c : strlen(curdir));
940 #ifdef API_DEBUG
941   CLog::Log(LOGDEBUG, "GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
942 #endif
943   return result;
944 }
945
946 extern "C" UINT WINAPI dllSetCurrentDirectoryA(const char *pathname)
947 {
948 #ifdef API_DEBUG
949   CLog::Log(LOGDEBUG, "SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
950 #endif
951   return 1;
952 }
953
954 extern "C" int WINAPI dllSetUnhandledExceptionFilter(void* filter)
955 {
956 #ifdef API_DEBUG
957   CLog::Log(LOGDEBUG, "SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
958 #endif
959   return 1; //unsupported and probably won't ever be supported
960 }
961
962 extern "C" int WINAPI dllSetEnvironmentVariableA(const char *name, const char *value)
963 {
964 #ifdef API_DEBUG
965   CLog::Log(LOGDEBUG, "SetEnvironmentVariableA(%s, %s)\n", name, value);
966 #endif
967   return 0;
968 }
969
970 extern "C" int WINAPI dllCreateDirectoryA(const char *pathname, void *sa)
971 {
972 #ifdef API_DEBUG
973   CLog::Log(LOGDEBUG, "CreateDirectory(0x%x = %s, 0x%x) => 1\n", pathname, pathname, sa);
974 #endif
975   return 1;
976 }
977
978 extern "C" DWORD WINAPI dllWaitForSingleObject(HANDLE hHandle, DWORD dwMiliseconds)
979 {
980 #ifdef API_DEBUG
981   CLog::Log(LOGDEBUG, "WaitForSingleObject(0x%x, %d)", hHandle, dwMiliseconds);
982 #endif
983   return WaitForSingleObject(hHandle, dwMiliseconds);
984 }
985
986 #ifdef _LINUX
987 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
988 #else
989 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
990 #endif
991 {
992 #ifdef API_DEBUG
993   CLog::Log(LOGDEBUG, "WaitForMultipleObjects(..)");
994 #endif
995
996   return WaitForMultipleObjects(nCount, lpHandles, fWaitAll, dwMilliseconds);
997 }
998
999 extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProcessAffinityMask, LPDWORD lpSystemAffinityMask)
1000 {
1001   CLog::Log(LOGDEBUG, "GetProcessAffinityMask(%p, %p, %p) => 1\n",
1002             (void*)hProcess, (void*)lpProcessAffinityMask, (void*)lpSystemAffinityMask);
1003   if (lpProcessAffinityMask)*lpProcessAffinityMask = 1;
1004   if (lpSystemAffinityMask)*lpSystemAffinityMask = 1;
1005   return 1;
1006 }
1007
1008 extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData)
1009 {
1010   if (Locale == LOCALE_SYSTEM_DEFAULT || Locale == LOCALE_USER_DEFAULT)
1011   {
1012     if (LCType == LOCALE_SISO639LANGNAME)
1013     {
1014       if (cchData > 3)
1015       {
1016         strcpy(lpLCData, "eng");
1017         return 4;
1018       }
1019     }
1020     else if (LCType == LOCALE_SISO3166CTRYNAME)
1021     {
1022       if (cchData > 2)
1023       {
1024         strcpy(lpLCData, "US");
1025         return 3;
1026       }
1027     }
1028     else if (LCType == LOCALE_IDEFAULTLANGUAGE)
1029     {
1030       if (cchData > 5)
1031       {
1032         strcpy(lpLCData, "en-US");
1033         return 6;
1034       }
1035     }
1036   }
1037
1038   not_implement("kernel32.dll incomplete function GetLocaleInfoA called\n");  //warning
1039   SetLastError(ERROR_INVALID_FUNCTION);
1040   return 0;
1041 }
1042
1043 extern "C" UINT WINAPI dllGetConsoleCP()
1044 {
1045   return 437; // OEM - United States
1046 }
1047
1048 extern "C" UINT WINAPI dllGetConsoleOutputCP()
1049 {
1050   return 437; // OEM - United States
1051 }
1052
1053 // emulated because windows expects different behaviour
1054 // the xbox calculates always 1 character extra for 0 termination
1055 // however, this is only desired when cbMultiByte has the value -1
1056 extern "C" int WINAPI dllMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
1057 {
1058   // first fix, on windows cchWideChar and cbMultiByte may be the same.
1059   // xbox fails, because it expects cbMultiByte to be at least one character bigger
1060   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1061   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1062   int destinationBufferSize = cchWideChar;
1063   LPWSTR destinationBuffer = lpWideCharStr;
1064   if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1065     destinationBufferSize++;
1066     destinationBuffer = (LPWSTR)malloc(destinationBufferSize * sizeof(WCHAR));
1067   }
1068
1069   int ret = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, destinationBuffer, destinationBufferSize);
1070
1071   if (ret > 0)
1072   {
1073     // second fix, but only if cchWideChar == 0, and ofcours ret > 0 indicating the function
1074     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1075     if (cchWideChar == 0) {
1076       ret--;
1077     }
1078
1079     // revert the first fix again
1080     if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1081       // the 0 termination character could never have been written on a windows machine
1082       // because of cchWideChar == cbMultiByte, again xbox added one for it.
1083       ret--;
1084
1085       memcpy(lpWideCharStr, destinationBuffer, ret * sizeof(WCHAR));
1086       free(destinationBuffer);
1087     }
1088   }
1089
1090   return ret;
1091 }
1092
1093 // same reason as above
1094 extern "C" int WINAPI dllWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
1095 {
1096   // first fix, on windows cchWideChar and cbMultiByte may be the same.
1097   // xbox fails, because it expects cbMultiByte to be at least one character bigger
1098   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1099   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1100   int destinationBufferSize = cbMultiByte;
1101   LPSTR destinationBuffer = lpMultiByteStr;
1102   if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1103     destinationBufferSize++;
1104     destinationBuffer = (LPSTR)malloc(destinationBufferSize * sizeof(char));
1105   }
1106
1107   int ret = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, destinationBuffer, destinationBufferSize, lpDefaultChar, lpUsedDefaultChar);
1108
1109   if (ret > 0)
1110   {
1111     // second fix, but only if cbMultiByte == 0, and ofcours ret > 0 indicating the function
1112     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1113     if (cbMultiByte == 0) {
1114       ret--;
1115     }
1116
1117     // revert the first fix again
1118     if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1119       // the 0 termination character could never have been written on a windows machine
1120       // because of cchWideChar == cbMultiByte, again xbox added one for it.
1121       ret--;
1122
1123       memcpy(lpMultiByteStr, destinationBuffer, ret);
1124       free(destinationBuffer);
1125     }
1126   }
1127
1128   return ret;
1129 }
1130
1131 extern "C" UINT WINAPI dllSetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
1132 {
1133 #ifdef _WIN32
1134   return SetConsoleCtrlHandler(HandlerRoutine, Add);
1135 #else
1136   // no consoles exists on the xbox, do nothing
1137   not_implement("kernel32.dll fake function SetConsoleCtrlHandler called\n");  //warning
1138   SetLastError(ERROR_INVALID_FUNCTION);
1139   return 0;
1140 #endif
1141 }
1142
1143 typedef struct _SFlsSlot
1144 {
1145   LONG lInUse;
1146   PVOID pData;
1147   PFLS_CALLBACK_FUNCTION pCallback;
1148 }
1149 SFlsSlot, *LPSFlsSlot;
1150
1151 #define FLS_NUM_SLOTS 5
1152 #if defined (_XBOX) || defined (_LINUX)
1153 #define FLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
1154 #endif
1155 SFlsSlot flsSlots[FLS_NUM_SLOTS] = { { false, NULL, NULL } };
1156
1157 extern "C" DWORD WINAPI dllFlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
1158 {
1159   DWORD i;
1160 #ifdef API_DEBUG
1161   CLog::Log(LOGDEBUG, "FlsAlloc(0x%x)\n", lpCallback);
1162 #endif
1163   for (i = 0; i < FLS_NUM_SLOTS; i++) {
1164     if( InterlockedCompareExchange(&flsSlots[i].lInUse, 1, 0) == 0 ) {
1165       flsSlots[i].pData = NULL;
1166       flsSlots[i].pCallback = lpCallback;
1167       return i;
1168     }
1169   }
1170   SetLastError(ERROR_INVALID_PARAMETER);
1171   CLog::Log(LOGERROR, " - Out of fls slots");
1172   return FLS_OUT_OF_INDEXES; // "
1173 }
1174
1175 static LPSFlsSlot FlsGetSlot(DWORD dwFlsIndex)
1176 {
1177   if (dwFlsIndex >= FLS_NUM_SLOTS) {
1178     SetLastError(ERROR_INVALID_PARAMETER);
1179     return NULL;
1180   }
1181   if (flsSlots[dwFlsIndex].lInUse != 1) {
1182     SetLastError(ERROR_INVALID_PARAMETER); // actually ERROR_NO_MEMORY would be correct
1183     return NULL;
1184   }
1185   return &(flsSlots[dwFlsIndex]);
1186 }
1187
1188 extern "C" BOOL WINAPI dllFlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
1189 {
1190 #ifdef API_DEBUG
1191   CLog::Log(LOGDEBUG, "FlsSetValue(%d, 0x%x) => 0x%x\n", dwFlsIndex, lpFlsData);
1192 #endif
1193   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1194   if (slot == NULL)
1195     return false;
1196   slot->pData = lpFlsData;
1197   return true;
1198 }
1199
1200 extern "C" PVOID WINAPI dllFlsGetValue(DWORD dwFlsIndex)
1201 {
1202 #ifdef API_DEBUG
1203   CLog::Log(LOGDEBUG, "FlsGetValue(%d)\n", dwFlsIndex);
1204 #endif
1205   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1206   return (slot == NULL) ? NULL : slot->pData;
1207 }
1208
1209 extern "C" BOOL WINAPI dllFlsFree(DWORD dwFlsIndex)
1210 {
1211 #ifdef API_DEBUG
1212   CLog::Log(LOGDEBUG, "FlsFree(%d)\n", dwFlsIndex);
1213 #endif
1214   LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1215   if (slot == NULL)
1216     return false;
1217
1218   if( slot->pCallback )
1219     slot->pCallback(slot->pData);
1220
1221   slot->pData = NULL;
1222   slot->lInUse = 0;
1223
1224   return true;
1225 }
1226
1227
1228 extern "C" PVOID WINAPI dllEncodePointer(PVOID ptr)
1229 {
1230   return ptr;
1231 }
1232
1233 extern "C" PVOID WINAPI dllDecodePointer(PVOID ptr)
1234 {
1235   return ptr;
1236 }
1237
1238
1239 extern "C" HANDLE WINAPI dllCreateFileA(
1240     IN LPCSTR lpFileName,
1241     IN DWORD dwDesiredAccess,
1242     IN DWORD dwShareMode,
1243     IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1244     IN DWORD dwCreationDisposition,
1245     IN DWORD dwFlagsAndAttributes,
1246     IN HANDLE hTemplateFile
1247     )
1248 {
1249   return CreateFileA(_P(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
1250 }
1251
1252 extern "C" BOOL WINAPI dllLockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh)
1253 {
1254   //return LockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh);
1255   return TRUE;
1256 }
1257
1258 extern "C" BOOL WINAPI dllLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh, LPOVERLAPPED lpOverlapped)
1259 {
1260   //return LockFileEx(hFile, dwFlags, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh, lpOverlapped);
1261   return TRUE;
1262 }
1263
1264 extern "C" BOOL WINAPI dllUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1265 {
1266   //return UnlockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1267   return TRUE;
1268 }
1269
1270 extern "C" DWORD WINAPI dllGetTempPathA(DWORD nBufferLength, LPTSTR lpBuffer)
1271 {
1272   // If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer,
1273   // not including the terminating null character. If the return value is greater than nBufferLength,
1274   // the return value is the size of the buffer required to hold the path.
1275   const char* tempPath = "special://temp/temp/";
1276   unsigned int len = strlen(tempPath);
1277
1278   if (nBufferLength > len)
1279   {
1280     strcpy(lpBuffer, tempPath);
1281   }
1282
1283   return len;
1284 }
1285
1286 extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE hModule, HRSRC hResInfo)
1287 {
1288   not_implement("kernel32.dll fake function LoadResource called\n");
1289   return NULL;
1290 }
1291
1292 extern "C" HRSRC WINAPI dllFindResourceA(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
1293 {
1294   not_implement("kernel32.dll fake function FindResource called\n");
1295   return NULL;
1296 }
1297
1298
1299 /*
1300
1301 The following routine was hacked up by JM while looking at why the DVD player was failing
1302 in the middle of the movie.  The symptoms were:
1303
1304 1. DVD player returned error about expecting a NAV packet but none found.
1305 2. Resulted in DVD player closing.
1306 3. Always occured in the same place.
1307 4. Occured on every DVD I tried (originals)
1308 5. Approximately where I would expect the layer change to be (ie just over half way
1309    through the movie)
1310 6. Resulted in the last chunk of the requested data to be NULL'd out completely.  ReadFile()
1311    returns correctly, but the last chunk is completely zero'd out.
1312
1313 This routine checks the last chunk for zeros, and re-reads if necessary.
1314 */
1315 #define DVD_CHUNK_SIZE 2048
1316
1317 extern "C" BOOL WINAPI dllDVDReadFileLayerChangeHack(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
1318 {
1319   BOOL ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
1320   if (!ret || !lpNumberOfBytesRead || *lpNumberOfBytesRead < DVD_CHUNK_SIZE) return ret;
1321   DWORD numChecked = *lpNumberOfBytesRead;
1322   while (numChecked >= DVD_CHUNK_SIZE)
1323   {
1324     BYTE *p = (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE;
1325     // test for a NULL block
1326     while (*p == 0 && p < (BYTE *)lpBuffer + numChecked)
1327       p++;
1328     if (p == (BYTE *)lpBuffer + numChecked)
1329     { // fully NULL block - reread
1330 #ifdef _WIN32
1331       LONG low = 0;
1332       LONG high = 0;
1333 #else
1334       int32_t low = 0;
1335       int32_t high = 0;
1336 #endif
1337       low = SetFilePointer(hFile, low, &high, FILE_CURRENT);
1338       CLog::Log(LOGWARNING,
1339                 "DVDReadFile() warning - "
1340                 "invalid data read from block at %i (%i) - rereading",
1341                 low, high);
1342       SetFilePointer(hFile, (int)numChecked - (int)*lpNumberOfBytesRead - DVD_CHUNK_SIZE, NULL, FILE_CURRENT);
1343       DWORD numRead;
1344       ret = ReadFile(hFile, (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE, DVD_CHUNK_SIZE, &numRead, lpOverlapped);
1345       if (!ret) return FALSE;
1346       SetFilePointer(hFile, low, &high, FILE_BEGIN);
1347     }
1348     numChecked -= DVD_CHUNK_SIZE;
1349   }
1350   return ret;
1351 }
1352
1353 extern "C" LPVOID WINAPI dllLockResource(HGLOBAL hResData)
1354 {
1355 #ifdef _WIN32
1356   return LockResource(hResData);
1357 #else
1358   not_implement("kernel32.dll fake function LockResource called\n"); //warning
1359   return 0;
1360 #endif
1361 }
1362
1363 extern "C" SIZE_T WINAPI dllGlobalSize(HGLOBAL hMem)
1364 {
1365 #ifdef _WIN32
1366   return GlobalSize(hMem);
1367 #else
1368   not_implement("kernel32.dll fake function GlobalSize called\n"); //warning
1369   return 0;
1370 #endif
1371 }
1372
1373 extern "C" DWORD WINAPI dllSizeofResource(HMODULE hModule, HRSRC hResInfo)
1374 {
1375 #ifdef _WIN32
1376   return SizeofResource(hModule, hResInfo);
1377 #else
1378   not_implement("kernel32.dll fake function SizeofResource called\n"); //warning
1379   return 0;
1380 #endif
1381 }