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