Merge pull request #184 from pieh/python_editControl
[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" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProcessAffinityMask, LPDWORD lpSystemAffinityMask)
825 {
826   CLog::Log(LOGDEBUG, "GetProcessAffinityMask(%p, %p, %p) => 1\n",
827             (void*)hProcess, (void*)lpProcessAffinityMask, (void*)lpSystemAffinityMask);
828   if (lpProcessAffinityMask)*lpProcessAffinityMask = 1;
829   if (lpSystemAffinityMask)*lpSystemAffinityMask = 1;
830   return 1;
831 }
832
833 extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData)
834 {
835   if (Locale == LOCALE_SYSTEM_DEFAULT || Locale == LOCALE_USER_DEFAULT)
836   {
837     if (LCType == LOCALE_SISO639LANGNAME)
838     {
839       if (cchData > 3)
840       {
841         strcpy(lpLCData, "eng");
842         return 4;
843       }
844     }
845     else if (LCType == LOCALE_SISO3166CTRYNAME)
846     {
847       if (cchData > 2)
848       {
849         strcpy(lpLCData, "US");
850         return 3;
851       }
852     }
853     else if (LCType == LOCALE_IDEFAULTLANGUAGE)
854     {
855       if (cchData > 5)
856       {
857         strcpy(lpLCData, "en-US");
858         return 6;
859       }
860     }
861   }
862
863   not_implement("kernel32.dll incomplete function GetLocaleInfoA called\n");  //warning
864   SetLastError(ERROR_INVALID_FUNCTION);
865   return 0;
866 }
867
868 extern "C" UINT WINAPI dllGetConsoleCP()
869 {
870   return 437; // OEM - United States
871 }
872
873 extern "C" UINT WINAPI dllGetConsoleOutputCP()
874 {
875   return 437; // OEM - United States
876 }
877
878 // emulated because windows expects different behaviour
879 // the xbox calculates always 1 character extra for 0 termination
880 // however, this is only desired when cbMultiByte has the value -1
881 extern "C" int WINAPI dllMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
882 {
883   // first fix, on windows cchWideChar and cbMultiByte may be the same.
884   // xbox fails, because it expects cbMultiByte to be at least one character bigger
885   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
886   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
887   int destinationBufferSize = cchWideChar;
888   LPWSTR destinationBuffer = lpWideCharStr;
889   if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
890     destinationBufferSize++;
891     destinationBuffer = (LPWSTR)malloc(destinationBufferSize * sizeof(WCHAR));
892   }
893
894   int ret = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, destinationBuffer, destinationBufferSize);
895
896   if (ret > 0)
897   {
898     // second fix, but only if cchWideChar == 0, and ofcours ret > 0 indicating the function
899     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
900     if (cchWideChar == 0) {
901       ret--;
902     }
903
904     // revert the first fix again
905     if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
906       // the 0 termination character could never have been written on a windows machine
907       // because of cchWideChar == cbMultiByte, again xbox added one for it.
908       ret--;
909
910       memcpy(lpWideCharStr, destinationBuffer, ret * sizeof(WCHAR));
911       free(destinationBuffer);
912     }
913   }
914
915   return ret;
916 }
917
918 // same reason as above
919 extern "C" int WINAPI dllWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
920 {
921   // first fix, on windows cchWideChar and cbMultiByte may be the same.
922   // xbox fails, because it expects cbMultiByte to be at least one character bigger
923   // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
924   // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
925   int destinationBufferSize = cbMultiByte;
926   LPSTR destinationBuffer = lpMultiByteStr;
927   if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
928     destinationBufferSize++;
929     destinationBuffer = (LPSTR)malloc(destinationBufferSize * sizeof(char));
930   }
931
932   int ret = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, destinationBuffer, destinationBufferSize, lpDefaultChar, lpUsedDefaultChar);
933
934   if (ret > 0)
935   {
936     // second fix, but only if cbMultiByte == 0, and ofcours ret > 0 indicating the function
937     // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
938     if (cbMultiByte == 0) {
939       ret--;
940     }
941
942     // revert the first fix again
943     if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
944       // the 0 termination character could never have been written on a windows machine
945       // because of cchWideChar == cbMultiByte, again xbox added one for it.
946       ret--;
947
948       memcpy(lpMultiByteStr, destinationBuffer, ret);
949       free(destinationBuffer);
950     }
951   }
952
953   return ret;
954 }
955
956 extern "C" UINT WINAPI dllSetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
957 {
958 #ifdef _WIN32
959   return SetConsoleCtrlHandler(HandlerRoutine, Add);
960 #else
961   // no consoles exists on the xbox, do nothing
962   not_implement("kernel32.dll fake function SetConsoleCtrlHandler called\n");  //warning
963   SetLastError(ERROR_INVALID_FUNCTION);
964   return 0;
965 #endif
966 }
967
968 extern "C" PVOID WINAPI dllEncodePointer(PVOID ptr)
969 {
970   return ptr;
971 }
972
973 extern "C" PVOID WINAPI dllDecodePointer(PVOID ptr)
974 {
975   return ptr;
976 }
977
978
979 extern "C" HANDLE WINAPI dllCreateFileA(
980     IN LPCSTR lpFileName,
981     IN DWORD dwDesiredAccess,
982     IN DWORD dwShareMode,
983     IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
984     IN DWORD dwCreationDisposition,
985     IN DWORD dwFlagsAndAttributes,
986     IN HANDLE hTemplateFile
987     )
988 {
989   return CreateFileA(_P(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
990 }
991
992 extern "C" BOOL WINAPI dllLockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh)
993 {
994   //return LockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh);
995   return TRUE;
996 }
997
998 extern "C" BOOL WINAPI dllLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh, LPOVERLAPPED lpOverlapped)
999 {
1000   //return LockFileEx(hFile, dwFlags, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh, lpOverlapped);
1001   return TRUE;
1002 }
1003
1004 extern "C" BOOL WINAPI dllUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1005 {
1006   //return UnlockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1007   return TRUE;
1008 }
1009
1010 extern "C" DWORD WINAPI dllGetTempPathA(DWORD nBufferLength, LPTSTR lpBuffer)
1011 {
1012   // If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer,
1013   // not including the terminating null character. If the return value is greater than nBufferLength,
1014   // the return value is the size of the buffer required to hold the path.
1015   const char* tempPath = "special://temp/temp/";
1016   unsigned int len = strlen(tempPath);
1017
1018   if (nBufferLength > len)
1019   {
1020     strcpy(lpBuffer, tempPath);
1021   }
1022
1023   return len;
1024 }
1025
1026 extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE hModule, HRSRC hResInfo)
1027 {
1028   not_implement("kernel32.dll fake function LoadResource called\n");
1029   return NULL;
1030 }
1031
1032 extern "C" HRSRC WINAPI dllFindResourceA(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
1033 {
1034   not_implement("kernel32.dll fake function FindResource called\n");
1035   return NULL;
1036 }
1037
1038
1039 /*
1040
1041 The following routine was hacked up by JM while looking at why the DVD player was failing
1042 in the middle of the movie.  The symptoms were:
1043
1044 1. DVD player returned error about expecting a NAV packet but none found.
1045 2. Resulted in DVD player closing.
1046 3. Always occured in the same place.
1047 4. Occured on every DVD I tried (originals)
1048 5. Approximately where I would expect the layer change to be (ie just over half way
1049    through the movie)
1050 6. Resulted in the last chunk of the requested data to be NULL'd out completely.  ReadFile()
1051    returns correctly, but the last chunk is completely zero'd out.
1052
1053 This routine checks the last chunk for zeros, and re-reads if necessary.
1054 */
1055 #define DVD_CHUNK_SIZE 2048
1056
1057 extern "C" BOOL WINAPI dllDVDReadFileLayerChangeHack(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
1058 {
1059   BOOL ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
1060   if (!ret || !lpNumberOfBytesRead || *lpNumberOfBytesRead < DVD_CHUNK_SIZE) return ret;
1061   DWORD numChecked = *lpNumberOfBytesRead;
1062   while (numChecked >= DVD_CHUNK_SIZE)
1063   {
1064     BYTE *p = (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE;
1065     // test for a NULL block
1066     while (*p == 0 && p < (BYTE *)lpBuffer + numChecked)
1067       p++;
1068     if (p == (BYTE *)lpBuffer + numChecked)
1069     { // fully NULL block - reread
1070 #ifdef _WIN32
1071       LONG low = 0;
1072       LONG high = 0;
1073 #else
1074       int32_t low = 0;
1075       int32_t high = 0;
1076 #endif
1077       low = SetFilePointer(hFile, low, &high, FILE_CURRENT);
1078       CLog::Log(LOGWARNING,
1079                 "DVDReadFile() warning - "
1080                 "invalid data read from block at %i (%i) - rereading",
1081                 low, high);
1082       SetFilePointer(hFile, (int)numChecked - (int)*lpNumberOfBytesRead - DVD_CHUNK_SIZE, NULL, FILE_CURRENT);
1083       DWORD numRead;
1084       ret = ReadFile(hFile, (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE, DVD_CHUNK_SIZE, &numRead, lpOverlapped);
1085       if (!ret) return FALSE;
1086       SetFilePointer(hFile, low, &high, FILE_BEGIN);
1087     }
1088     numChecked -= DVD_CHUNK_SIZE;
1089   }
1090   return ret;
1091 }
1092
1093 extern "C" LPVOID WINAPI dllLockResource(HGLOBAL hResData)
1094 {
1095 #ifdef _WIN32
1096   return LockResource(hResData);
1097 #else
1098   not_implement("kernel32.dll fake function LockResource called\n"); //warning
1099   return 0;
1100 #endif
1101 }
1102
1103 extern "C" SIZE_T WINAPI dllGlobalSize(HGLOBAL hMem)
1104 {
1105 #ifdef _WIN32
1106   return GlobalSize(hMem);
1107 #else
1108   not_implement("kernel32.dll fake function GlobalSize called\n"); //warning
1109   return 0;
1110 #endif
1111 }
1112
1113 extern "C" DWORD WINAPI dllSizeofResource(HMODULE hModule, HRSRC hResInfo)
1114 {
1115 #ifdef _WIN32
1116   return SizeofResource(hModule, hResInfo);
1117 #else
1118   not_implement("kernel32.dll fake function SizeofResource called\n"); //warning
1119   return 0;
1120 #endif
1121 }