2 * Copyright (C) 2005-2008 Team XBMC
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)
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.
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
22 #include "emu_kernel32.h"
23 #include "emu_dummy.h"
24 #include "utils/log.h"
26 #include "storage/IoSupport.h"
30 #include "utils/CharsetConverter.h"
33 #include "../dll_tracker.h"
34 #include "filesystem/SpecialProtocol.h"
37 #include "../../../linux/PlatformInclude.h"
38 #define __except catch
43 vector<string> m_vecAtoms;
47 extern "C" HANDLE xboxopendvdrom()
49 return CIoSupport::OpenCDROM();
52 extern "C" UINT WINAPI dllGetAtomNameA( ATOM nAtom, LPTSTR lpBuffer, int nSize)
54 if (nAtom < 1 || nAtom > m_vecAtoms.size() ) return 0;
56 string& strAtom = m_vecAtoms[nAtom];
57 strcpy(lpBuffer, strAtom.c_str());
58 return strAtom.size();
61 extern "C" ATOM WINAPI dllFindAtomA( LPCTSTR lpString)
63 for (int i = 0; i < (int)m_vecAtoms.size(); ++i)
65 string& strAtom = m_vecAtoms[i];
66 if (strAtom == lpString) return i + 1;
71 extern "C" ATOM WINAPI dllAddAtomA( LPCTSTR lpString)
73 m_vecAtoms.push_back(lpString);
74 return m_vecAtoms.size();
77 extern "C" ATOM WINAPI dllDeleteAtomA(ATOM nAtom)
81 extern "C" BOOL WINAPI dllFindClose(HANDLE hFile)
83 return FindClose(hFile);
87 #define CORRECT_SEP_STR(str) \
88 if (strstr(str, "://") == NULL) \
90 int iSize_##str = strlen(str); \
91 for (int pos = 0; pos < iSize_##str; pos++) \
92 if (str[pos] == '/') str[pos] = '\\'; \
96 int iSize_##str = strlen(str); \
97 for (int pos = 0; pos < iSize_##str; pos++) \
98 if (str[pos] == '\\') str[pos] = '/'; \
101 #define CORRECT_SEP_STR(str)
105 static void to_WIN32_FIND_DATA(LPWIN32_FIND_DATAW wdata, LPWIN32_FIND_DATA data)
108 g_charsetConverter.wToUTF8(wdata->cFileName, strname);
109 size_t size = sizeof(data->cFileName) / sizeof(char);
110 strncpy(data->cFileName, strname.c_str(), size);
112 data->cFileName[size - 1] = '\0';
114 g_charsetConverter.wToUTF8(wdata->cAlternateFileName, strname);
115 size = sizeof(data->cAlternateFileName) / sizeof(char);
116 strncpy(data->cAlternateFileName, strname.c_str(), size);
118 data->cAlternateFileName[size - 1] = '\0';
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;
130 static void to_WIN32_FIND_DATAW(LPWIN32_FIND_DATA data, LPWIN32_FIND_DATAW wdata)
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);
137 wdata->cFileName[size - 1] = '\0';
139 g_charsetConverter.utf8ToW(data->cAlternateFileName, strwname, false);
140 size = sizeof(wdata->cAlternateFileName) / sizeof(wchar_t);
141 wcsncpy(wdata->cAlternateFileName, strwname.c_str(), size);
143 data->cAlternateFileName[size - 1] = '\0';
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;
156 extern "C" HANDLE WINAPI dllFindFirstFileA(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData)
158 char* p = strdup(lpFileName);
161 // change default \\*.* into \\* which the xbox is using
162 char* e = strrchr(p, '.');
163 if (e != NULL && strlen(e) > 1 && e[1] == '*')
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);
176 HANDLE res = FindFirstFile(_P(p).c_str(), lpFindFileData);
182 extern "C" BOOL WINAPI dllFindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
185 struct _WIN32_FIND_DATAW FindFileDataW;
186 to_WIN32_FIND_DATAW(lpFindFileData, &FindFileDataW);
187 BOOL res = FindNextFileW(hFindFile, &FindFileDataW);
189 to_WIN32_FIND_DATA(&FindFileDataW, lpFindFileData);
192 return FindNextFile(hFindFile, lpFindFileData);
196 // should be moved to CFile! or use CFile::stat
197 extern "C" DWORD WINAPI dllGetFileAttributesA(LPCSTR lpFileName)
201 if (!strcmp(lpFileName, "\\Device\\Cdrom0")) return (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY);
203 // move to CFile classes
204 if (strncmp(lpFileName, "\\Device\\Cdrom0", 14) == 0)
206 // replace "\\Device\\Cdrom0" with "D:"
208 strcat(str, lpFileName + 14);
210 else strcpy(str, lpFileName);
213 // convert '/' to '\\'
215 while (p = strchr(p, '/')) * p = '\\';
216 return GetFileAttributesA(str);
218 return GetFileAttributes(str);
222 struct SThreadWrapper
224 LPTHREAD_START_ROUTINE lpStartAddress;
230 #define MS_VC_EXCEPTION 0x406d1388
231 typedef struct tagTHREADNAME_INFO
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
241 int dllThreadWrapper(LPVOID lpThreadParameter)
243 unsigned int __stdcall dllThreadWrapper(LPVOID lpThreadParameter)
246 SThreadWrapper *param = (SThreadWrapper*)lpThreadParameter;
249 #if defined(_DEBUG) && !defined(_LINUX)
250 THREADNAME_INFO info;
251 info.dwType = 0x1000;
253 info.dwThreadID = ::GetCurrentThreadId();
257 RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (DWORD *)&info);
259 __except (EXCEPTION_CONTINUE_EXECUTION)
266 result = param->lpStartAddress(param->lpParameter);
268 __except (EXCEPTION_EXECUTE_HANDLER)
270 CLog::Log(LOGERROR, "DLL:%s - Unhandled exception in thread created by dll", param->lpDLL );
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
288 uintptr_t loc = (uintptr_t)_ReturnAddress();
290 SThreadWrapper *param = new SThreadWrapper;
291 param->lpStartAddress = lpStartAddress;
292 param->lpParameter = lpParameter;
293 param->lpDLL = tracker_getdllname(loc);
295 return (HANDLE)_beginthreadex(lpThreadAttributes, dwStackSize, dllThreadWrapper, param, dwCreationFlags, (unsigned int *)lpThreadId);
299 extern "C" BOOL WINAPI dllTerminateThread(HANDLE tHread, DWORD dwExitCode)
301 not_implement("kernel32.dll fake function TerminateThread called\n"); //warning
305 extern "C" void WINAPI dllSleep(DWORD dwTime)
307 return ::Sleep(dwTime);
310 extern "C" HANDLE WINAPI dllGetCurrentThread(void)
312 HANDLE retval = GetCurrentThread();
316 extern "C" DWORD WINAPI dllGetCurrentProcessId(void)
319 return (DWORD)getppid();
321 return GetCurrentProcessId();
325 extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
327 // since the xbox has only one process, we just take the current thread
328 HANDLE h = GetCurrentThread();
329 BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
334 extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
335 HANDLE hSourceHandle, // handle to duplicate
336 HANDLE hTargetProcessHandle, // handle to target process
337 HANDLE* lpTargetHandle, // duplicate handle
338 DWORD dwDesiredAccess, // requested access
339 int bInheritHandle, // handle inheritance option
340 DWORD dwOptions // optional actions
344 CLog::Log(LOGDEBUG, "DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
345 hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
346 lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
349 *lpTargetHandle = hSourceHandle;
352 return DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
356 extern "C" BOOL WINAPI dllDisableThreadLibraryCalls(HMODULE h)
359 return DisableThreadLibraryCalls(h);
361 not_implement("kernel32.dll fake function DisableThreadLibraryCalls called\n"); //warning
366 static void DumpSystemInfo(const SYSTEM_INFO* si)
368 CLog::Log(LOGDEBUG, " Processor architecture %d\n", si->wProcessorArchitecture);
369 CLog::Log(LOGDEBUG, " Page size: %d\n", si->dwPageSize);
370 CLog::Log(LOGDEBUG, " Minimum app address: %d\n", si->lpMinimumApplicationAddress);
371 CLog::Log(LOGDEBUG, " Maximum app address: %d\n", si->lpMaximumApplicationAddress);
372 CLog::Log(LOGDEBUG, " Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
373 CLog::Log(LOGDEBUG, " Number of processors: %d\n", si->dwNumberOfProcessors);
374 CLog::Log(LOGDEBUG, " Processor type: 0x%x\n", si->dwProcessorType);
375 CLog::Log(LOGDEBUG, " Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
376 CLog::Log(LOGDEBUG, " Processor level: 0x%x\n", si->wProcessorLevel);
377 CLog::Log(LOGDEBUG, " Processor revision: 0x%x\n", si->wProcessorRevision);
381 extern "C" void WINAPI dllGetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
384 CLog::Log(LOGDEBUG, "GetSystemInfo(0x%x) =>", lpSystemInfo);
387 // VS 2003 complains about x even so it's defined
388 lpSystemInfo->wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
390 lpSystemInfo->x.wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
392 lpSystemInfo->dwPageSize = 4096; //Xbox page size
393 lpSystemInfo->lpMinimumApplicationAddress = (void *)0x00000000;
394 lpSystemInfo->lpMaximumApplicationAddress = (void *)0x7fffffff;
395 lpSystemInfo->dwActiveProcessorMask = 1;
396 lpSystemInfo->dwNumberOfProcessors = 1;
397 lpSystemInfo->dwProcessorType = 586; //#define PROCESSOR_INTEL_PENTIUM 586
398 lpSystemInfo->wProcessorLevel = 6;
399 //lpSystemInfo->wProcessorLevel = 5;
400 lpSystemInfo->wProcessorRevision = 0x080A;
401 lpSystemInfo->dwAllocationGranularity = 0x10000; //virtualalloc reserve block size
403 DumpSystemInfo(lpSystemInfo);
405 } //hardcode for xbox processor type;
407 extern "C" UINT WINAPI dllGetPrivateProfileIntA(
413 not_implement("kernel32.dll fake function GetPrivateProfileIntA called\n"); //warning
417 //globals for memory leak hack, no need for well-behaved dlls call init/del in pair
418 //We can free the sections if applications does not call deletecriticalsection
419 //need to initialize the list head NULL at mplayer_open_file, and free memory at close file.
420 std::map<LPCRITICAL_SECTION, LPCRITICAL_SECTION> g_mapCriticalSection;
422 extern "C" void WINAPI dllDeleteCriticalSection(LPCRITICAL_SECTION cs)
425 CLog::Log(LOGDEBUG, "DeleteCriticalSection(0x%x)", cs);
427 if (g_mapCriticalSection.find(cs) != g_mapCriticalSection.end())
429 LPCRITICAL_SECTION cs_new = g_mapCriticalSection[cs];
430 DeleteCriticalSection(cs_new);
432 g_mapCriticalSection.erase(cs);
436 extern "C" void WINAPI dllInitializeCriticalSection(LPCRITICAL_SECTION cs)
439 CLog::Log(LOGDEBUG, "InitializeCriticalSection(0x%x)", cs);
441 LPCRITICAL_SECTION cs_new = new CRITICAL_SECTION;
442 memset(cs_new, 0, sizeof(CRITICAL_SECTION));
443 InitializeCriticalSection(cs_new);
445 // just take the first member of the CRITICAL_SECTION to save ourdata in, this will be used to
446 // get fast access to the new critial section in dllLeaveCriticalSection and dllEnterCriticalSection
447 ((LPCRITICAL_SECTION*)cs)[0] = cs_new;
448 g_mapCriticalSection[cs] = cs_new;
451 extern "C" void WINAPI dllLeaveCriticalSection(LPCRITICAL_SECTION cs)
454 CLog::Log(LOGDEBUG, "LeaveCriticalSection(0x%x) %p\n", ((LPCRITICAL_SECTION*)cs)[0]);
456 LeaveCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
459 extern "C" void WINAPI dllEnterCriticalSection(LPCRITICAL_SECTION cs)
462 CLog::Log(LOGDEBUG, "EnterCriticalSection(0x%x) %p\n", cs, ((LPCRITICAL_SECTION*)cs)[0]);
465 if (!(LPCRITICAL_SECTION)cs->OwningThread)
468 CLog::Log(LOGDEBUG, "entered uninitialized critisec!\n");
470 dllInitializeCriticalSection(cs);
473 EnterCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
476 extern "C" DWORD WINAPI dllGetVersion()
479 CLog::Log(LOGDEBUG, "GetVersion() => 0xC0000004 (Windows 95)\n");
481 //return 0x0a280105; //Windows XP
482 return 0xC0000004; //Windows 95
485 extern "C" BOOL WINAPI dllGetVersionExA(LPOSVERSIONINFO lpVersionInfo)
488 CLog::Log(LOGDEBUG, "GetVersionExA()\n");
490 lpVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
491 lpVersionInfo->dwMajorVersion = 4;
492 lpVersionInfo->dwMinorVersion = 0;
493 lpVersionInfo->dwBuildNumber = 0x4000457;
494 // leave it here for testing win9x-only codecs
495 lpVersionInfo->dwPlatformId = 1; //VER_PLATFORM_WIN32_WINDOWS
496 lpVersionInfo->szCSDVersion[0] = 0;
498 CLog::Log(LOGDEBUG, " Major version: %d\n Minor version: %d\n Build number: %x\n"
499 " Platform Id: %d\n Version string: '%s'\n",
500 lpVersionInfo->dwMajorVersion, lpVersionInfo->dwMinorVersion,
501 lpVersionInfo->dwBuildNumber, lpVersionInfo->dwPlatformId, lpVersionInfo->szCSDVersion);
506 extern "C" BOOL WINAPI dllGetVersionExW(LPOSVERSIONINFOW lpVersionInfo)
509 CLog::Log(LOGDEBUG, "GetVersionExW()\n");
511 if(!dllGetVersionExA((LPOSVERSIONINFO)lpVersionInfo))
514 lpVersionInfo->szCSDVersion[0] = 0;
515 lpVersionInfo->szCSDVersion[1] = 0;
519 extern "C" UINT WINAPI dllGetProfileIntA(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault)
521 // CLog::Log(LOGDEBUG,"GetProfileIntA:%s %s %i", lpAppName,lpKeyName,nDefault);
522 not_implement("kernel32.dll fake function GetProfileIntA called\n"); //warning
526 extern "C" BOOL WINAPI dllFreeEnvironmentStringsW(LPWSTR lpString)
528 // we don't have anything to clean up here, just return.
530 CLog::Log(LOGDEBUG, "FreeEnvironmentStringsA(0x%x) => 1", lpString);
535 extern "C" HMODULE WINAPI dllGetOEMCP()
537 not_implement("kernel32.dll fake function GetOEMCP called\n"); //warning
541 extern "C" HMODULE WINAPI dllRtlUnwind(PVOID TargetFrame OPTIONAL, PVOID TargetIp OPTIONAL, PEXCEPTION_RECORD ExceptionRecord OPTIONAL, PVOID ReturnValue)
543 not_implement("kernel32.dll fake function RtlUnwind called\n"); //warning
546 extern "C" LPTSTR WINAPI dllGetCommandLineA()
549 CLog::Log(LOGDEBUG, "GetCommandLineA() => \"c:\\xbmc.xbe\"\n");
551 return (LPTSTR)"c:\\xbmc.xbe";
554 extern "C" HMODULE WINAPI dllExitProcess(UINT uExitCode)
556 not_implement("kernel32.dll fake function ExitProcess called\n"); //warning
559 extern "C" HMODULE WINAPI dllTerminateProcess(HANDLE hProcess, UINT uExitCode)
561 not_implement("kernel32.dll fake function TerminateProcess called\n"); //warning
564 extern "C" HANDLE WINAPI dllGetCurrentProcess()
567 return GetCurrentProcess();
570 return GetCurrentProcess();
573 CLog::Log(LOGDEBUG, "GetCurrentProcess(void) => 9375");
579 extern "C" UINT WINAPI dllGetACP()
582 CLog::Log(LOGDEBUG, "GetACP() => 0");
587 extern "C" UINT WINAPI dllSetHandleCount(UINT uNumber)
589 //Under Windows NT and Windows 95, this function simply returns the value specified in the uNumber parameter.
592 CLog::Log(LOGDEBUG, "SetHandleCount(0x%x) => 1\n", uNumber);
597 extern "C" HANDLE WINAPI dllGetStdHandle(DWORD nStdHandle)
601 case STD_INPUT_HANDLE: return (HANDLE)0;
602 case STD_OUTPUT_HANDLE: return (HANDLE)1;
603 case STD_ERROR_HANDLE: return (HANDLE)2;
605 SetLastError( ERROR_INVALID_PARAMETER );
606 return INVALID_HANDLE_VALUE;
609 extern "C" DWORD WINAPI dllGetFileType(HANDLE hFile)
612 CLog::Log(LOGDEBUG, "GetFileType(0x%x) => 0x3 = pipe", hFile);
617 extern "C" int WINAPI dllGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
620 CLog::Log(LOGDEBUG, "GetStartupInfoA(0x%x) => 1\n");
622 lpStartupInfo->cb = sizeof(_STARTUPINFOA);
623 lpStartupInfo->cbReserved2 = 0;
624 lpStartupInfo->dwFillAttribute = 0;
625 lpStartupInfo->dwFlags = 0;
626 lpStartupInfo->dwX = 50; //
627 lpStartupInfo->dwXCountChars = 0;
628 lpStartupInfo->dwXSize = 0;
629 lpStartupInfo->dwY = 50; //
630 lpStartupInfo->dwYCountChars = 0;
631 lpStartupInfo->dwYSize = 0;
632 lpStartupInfo->hStdError = (HANDLE)2;
633 lpStartupInfo->hStdInput = (HANDLE)0;
634 lpStartupInfo->hStdOutput = (HANDLE)1;
635 lpStartupInfo->lpDesktop = NULL;
636 lpStartupInfo->lpReserved = NULL;
637 lpStartupInfo->lpReserved2 = 0;
638 lpStartupInfo->lpTitle = (LPTSTR)"XBMC";
639 lpStartupInfo->wShowWindow = 0;
643 extern "C" BOOL WINAPI dllFreeEnvironmentStringsA(LPSTR lpString)
645 // we don't have anything to clean up here, just return.
649 static const char ch_envs[] =
650 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELETED,1\r\n"
651 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
653 extern "C" LPVOID WINAPI dllGetEnvironmentStrings()
656 return GetEnvironmentStrings();
659 CLog::Log(LOGDEBUG, "GetEnvironmentStrings() => 0x%x = %p", ch_envs, ch_envs);
661 return (LPVOID)ch_envs;
664 extern "C" LPVOID WINAPI dllGetEnvironmentStringsW()
667 return GetEnvironmentStringsW();
672 extern "C" int WINAPI dllGetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
675 return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
677 if (lpBuffer) lpBuffer[0] = 0;
679 if (strcmp(lpName, "__MSVCRT_HEAP_SELECT") == 0)
680 strcpy(lpBuffer, "__GLOBAL_HEAP_SELECTED,1");
682 CLog::Log(LOGDEBUG, "GetEnvironmentVariableA('%s', 0x%x, %d) => %d", lpName, lpBuffer, nSize, strlen(lpBuffer));
684 return strlen(lpBuffer);
687 extern "C" HMODULE WINAPI dllLCMapStringA(LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest)
689 not_implement("kernel32.dll fake function LCMapStringA called\n"); //warning
693 extern "C" HMODULE WINAPI dllLCMapStringW(LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest)
695 not_implement("kernel32.dll fake function LCMapStringW called\n"); //warning
699 extern "C" HMODULE WINAPI dllSetStdHandle(DWORD nStdHandle, HANDLE hHandle)
701 not_implement("kernel32.dll fake function SetStdHandle called\n"); //warning
705 extern "C" HMODULE WINAPI dllGetStringTypeA(LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
707 not_implement("kernel32.dll fake function GetStringTypeA called\n"); //warning
711 extern "C" HMODULE WINAPI dllGetStringTypeW(DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
713 not_implement("kernel32.dll fake function GetStringTypeW called\n"); //warning
717 extern "C" HMODULE WINAPI dllGetCPInfo(UINT CodePage, LPCPINFO lpCPInfo)
719 not_implement("kernel32.dll fake function GetCPInfo called\n"); //warning
723 extern "C" LCID WINAPI dllGetThreadLocale(void)
725 // primary language identifier, sublanguage identifier, sorting identifier
726 return MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
729 extern "C" BOOL WINAPI dllSetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass)
731 not_implement("kernel32.dll fake function SetPriorityClass called\n"); //warning
735 extern "C" DWORD WINAPI dllFormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, va_list* Arguments)
738 return FormatMessageA(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
740 not_implement("kernel32.dll fake function FormatMessage called\n"); //warning
745 extern "C" DWORD WINAPI dllGetFullPathNameA(LPCTSTR lpFileName, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR* lpFilePart)
748 if (!lpFileName) return 0;
749 if(strstr(lpFileName, "://"))
751 unsigned int length = strlen(lpFileName);
752 if (nBufferLength < (length + 1))
756 strcpy(lpBuffer, lpFileName);
759 char* s1 = strrchr(lpBuffer, '\\');
760 char* s2 = strrchr(lpBuffer, '/');
762 *lpFilePart = s1 + 1;
763 else if(s1 && s2 > s1)
764 *lpFilePart = s2 + 1;
766 *lpFilePart = lpBuffer;
771 return GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, lpFilePart);
773 not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
778 extern "C" DWORD WINAPI dllGetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart)
781 if (!lpFileName) return 0;
782 if(wcsstr(lpFileName, L"://"))
784 size_t length = wcslen(lpFileName);
785 if (nBufferLength < (length + 1))
789 wcscpy(lpBuffer, lpFileName);
792 wchar_t* s1 = wcsrchr(lpBuffer, '\\');
793 wchar_t* s2 = wcsrchr(lpBuffer, '/');
795 *lpFilePart = s1 + 1;
796 else if(s1 && s2 > s1)
797 *lpFilePart = s2 + 1;
799 *lpFilePart = lpBuffer;
804 return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
806 not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
811 extern "C" DWORD WINAPI dllExpandEnvironmentStringsA(LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize)
814 return ExpandEnvironmentStringsA(lpSrc, lpDst, nSize);
816 not_implement("kernel32.dll fake function ExpandEnvironmentStringsA called\n"); //warning
821 extern "C" UINT WINAPI dllGetWindowsDirectoryA(LPTSTR lpBuffer, UINT uSize)
823 not_implement("kernel32.dll fake function dllGetWindowsDirectory called\n"); //warning
827 extern "C" UINT WINAPI dllGetSystemDirectoryA(LPTSTR lpBuffer, UINT uSize)
829 //char* systemdir = "special://xbmc/system/mplayer/codecs";
830 //unsigned int len = strlen(systemdir);
831 //if (len > uSize) return 0;
832 //strcpy(lpBuffer, systemdir);
833 //not_implement("kernel32.dll incompete function dllGetSystemDirectory called\n"); //warning
834 //CLog::Log(LOGDEBUG,"KERNEL32!GetSystemDirectoryA(0x%x, %d) => %s", lpBuffer, uSize, systemdir);
837 CLog::Log(LOGDEBUG, "GetSystemDirectoryA(%p,%d)\n", lpBuffer, uSize);
839 if (!lpBuffer) strcpy(lpBuffer, ".");
844 extern "C" UINT WINAPI dllGetShortPathName(LPTSTR lpszLongPath, LPTSTR lpszShortPath, UINT cchBuffer)
846 if (!lpszLongPath) return 0;
847 if (strlen(lpszLongPath) == 0)
849 //strcpy(lpszLongPath, "special://xbmc/system/mplayer/codecs/QuickTime.qts");
852 CLog::Log(LOGDEBUG, "KERNEL32!GetShortPathNameA('%s',%p,%d)\n", lpszLongPath, lpszShortPath, cchBuffer);
854 strcpy(lpszShortPath, lpszLongPath);
855 return strlen(lpszShortPath);
858 extern "C" HANDLE WINAPI dllGetProcessHeap()
861 CLog::Log(LOGWARNING, "KERNEL32!GetProcessHeap() linux cant provide this service!");
865 hHeap = GetProcessHeap();
867 CLog::Log(LOGDEBUG, "KERNEL32!GetProcessHeap() => 0x%x", hHeap);
873 extern "C" UINT WINAPI dllSetErrorMode(UINT i)
876 CLog::Log(LOGDEBUG, "SetErrorMode(%d) => 0\n", i);
881 extern "C" BOOL WINAPI dllIsProcessorFeaturePresent(DWORD ProcessorFeature)
884 switch (ProcessorFeature)
886 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
889 case PF_COMPARE_EXCHANGE_DOUBLE:
892 case PF_FLOATING_POINT_EMULATED:
895 case PF_FLOATING_POINT_PRECISION_ERRATA:
898 case PF_MMX_INSTRUCTIONS_AVAILABLE:
904 case PF_RDTSC_INSTRUCTION_AVAILABLE:
907 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
910 case 10: //PF_XMMI64_INSTRUCTIONS_AVAILABLE
916 CLog::Log(LOGDEBUG, "IsProcessorFeaturePresent(0x%x) => 0x%x\n", ProcessorFeature, result);
921 extern "C" UINT WINAPI dllGetCurrentDirectoryA(UINT c, LPSTR s)
923 char curdir[] = "special://xbmc/";
925 strncpy(s, curdir, c);
926 result = 1 + ((c < strlen(curdir)) ? c : strlen(curdir));
928 CLog::Log(LOGDEBUG, "GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
933 extern "C" UINT WINAPI dllSetCurrentDirectoryA(const char *pathname)
936 CLog::Log(LOGDEBUG, "SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
941 extern "C" int WINAPI dllSetUnhandledExceptionFilter(void* filter)
944 CLog::Log(LOGDEBUG, "SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
946 return 1; //unsupported and probably won't ever be supported
949 extern "C" int WINAPI dllSetEnvironmentVariableA(const char *name, const char *value)
952 CLog::Log(LOGDEBUG, "SetEnvironmentVariableA(%s, %s)\n", name, value);
957 extern "C" int WINAPI dllCreateDirectoryA(const char *pathname, void *sa)
960 CLog::Log(LOGDEBUG, "CreateDirectory(0x%x = %s, 0x%x) => 1\n", pathname, pathname, sa);
965 extern "C" DWORD WINAPI dllWaitForSingleObject(HANDLE hHandle, DWORD dwMiliseconds)
968 CLog::Log(LOGDEBUG, "WaitForSingleObject(0x%x, %d)", hHandle, dwMiliseconds);
970 return WaitForSingleObject(hHandle, dwMiliseconds);
974 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
976 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
980 CLog::Log(LOGDEBUG, "WaitForMultipleObjects(..)");
983 return WaitForMultipleObjects(nCount, lpHandles, fWaitAll, dwMilliseconds);
986 extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProcessAffinityMask, LPDWORD lpSystemAffinityMask)
988 CLog::Log(LOGDEBUG, "GetProcessAffinityMask(%p, %p, %p) => 1\n",
989 (void*)hProcess, (void*)lpProcessAffinityMask, (void*)lpSystemAffinityMask);
990 if (lpProcessAffinityMask)*lpProcessAffinityMask = 1;
991 if (lpSystemAffinityMask)*lpSystemAffinityMask = 1;
995 extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData)
997 if (Locale == LOCALE_SYSTEM_DEFAULT || Locale == LOCALE_USER_DEFAULT)
999 if (LCType == LOCALE_SISO639LANGNAME)
1003 strcpy(lpLCData, "eng");
1007 else if (LCType == LOCALE_SISO3166CTRYNAME)
1011 strcpy(lpLCData, "US");
1015 else if (LCType == LOCALE_IDEFAULTLANGUAGE)
1019 strcpy(lpLCData, "en-US");
1025 not_implement("kernel32.dll incomplete function GetLocaleInfoA called\n"); //warning
1026 SetLastError(ERROR_INVALID_FUNCTION);
1030 extern "C" UINT WINAPI dllGetConsoleCP()
1032 return 437; // OEM - United States
1035 extern "C" UINT WINAPI dllGetConsoleOutputCP()
1037 return 437; // OEM - United States
1040 // emulated because windows expects different behaviour
1041 // the xbox calculates always 1 character extra for 0 termination
1042 // however, this is only desired when cbMultiByte has the value -1
1043 extern "C" int WINAPI dllMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
1045 // first fix, on windows cchWideChar and cbMultiByte may be the same.
1046 // xbox fails, because it expects cbMultiByte to be at least one character bigger
1047 // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1048 // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1049 int destinationBufferSize = cchWideChar;
1050 LPWSTR destinationBuffer = lpWideCharStr;
1051 if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1052 destinationBufferSize++;
1053 destinationBuffer = (LPWSTR)malloc(destinationBufferSize * sizeof(WCHAR));
1056 int ret = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, destinationBuffer, destinationBufferSize);
1060 // second fix, but only if cchWideChar == 0, and ofcours ret > 0 indicating the function
1061 // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1062 if (cchWideChar == 0) {
1066 // revert the first fix again
1067 if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1068 // the 0 termination character could never have been written on a windows machine
1069 // because of cchWideChar == cbMultiByte, again xbox added one for it.
1072 memcpy(lpWideCharStr, destinationBuffer, ret * sizeof(WCHAR));
1073 free(destinationBuffer);
1080 // same reason as above
1081 extern "C" int WINAPI dllWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
1083 // first fix, on windows cchWideChar and cbMultiByte may be the same.
1084 // xbox fails, because it expects cbMultiByte to be at least one character bigger
1085 // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1086 // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1087 int destinationBufferSize = cbMultiByte;
1088 LPSTR destinationBuffer = lpMultiByteStr;
1089 if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1090 destinationBufferSize++;
1091 destinationBuffer = (LPSTR)malloc(destinationBufferSize * sizeof(char));
1094 int ret = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, destinationBuffer, destinationBufferSize, lpDefaultChar, lpUsedDefaultChar);
1098 // second fix, but only if cbMultiByte == 0, and ofcours ret > 0 indicating the function
1099 // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1100 if (cbMultiByte == 0) {
1104 // revert the first fix again
1105 if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1106 // the 0 termination character could never have been written on a windows machine
1107 // because of cchWideChar == cbMultiByte, again xbox added one for it.
1110 memcpy(lpMultiByteStr, destinationBuffer, ret);
1111 free(destinationBuffer);
1118 extern "C" UINT WINAPI dllSetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
1121 return SetConsoleCtrlHandler(HandlerRoutine, Add);
1123 // no consoles exists on the xbox, do nothing
1124 not_implement("kernel32.dll fake function SetConsoleCtrlHandler called\n"); //warning
1125 SetLastError(ERROR_INVALID_FUNCTION);
1130 typedef struct _SFlsSlot
1134 PFLS_CALLBACK_FUNCTION pCallback;
1136 SFlsSlot, *LPSFlsSlot;
1138 #define FLS_NUM_SLOTS 5
1139 #if defined (_LINUX)
1140 #define FLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
1142 SFlsSlot flsSlots[FLS_NUM_SLOTS] = { { false, NULL, NULL } };
1144 extern "C" DWORD WINAPI dllFlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
1148 CLog::Log(LOGDEBUG, "FlsAlloc(0x%x)\n", lpCallback);
1150 for (i = 0; i < FLS_NUM_SLOTS; i++) {
1151 if( InterlockedCompareExchange(&flsSlots[i].lInUse, 1, 0) == 0 ) {
1152 flsSlots[i].pData = NULL;
1153 flsSlots[i].pCallback = lpCallback;
1157 SetLastError(ERROR_INVALID_PARAMETER);
1158 CLog::Log(LOGERROR, " - Out of fls slots");
1159 return FLS_OUT_OF_INDEXES; // "
1162 static LPSFlsSlot FlsGetSlot(DWORD dwFlsIndex)
1164 if (dwFlsIndex >= FLS_NUM_SLOTS) {
1165 SetLastError(ERROR_INVALID_PARAMETER);
1168 if (flsSlots[dwFlsIndex].lInUse != 1) {
1169 SetLastError(ERROR_INVALID_PARAMETER); // actually ERROR_NO_MEMORY would be correct
1172 return &(flsSlots[dwFlsIndex]);
1175 extern "C" BOOL WINAPI dllFlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
1178 CLog::Log(LOGDEBUG, "FlsSetValue(%d, 0x%x) => 0x%x\n", dwFlsIndex, lpFlsData);
1180 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1183 slot->pData = lpFlsData;
1187 extern "C" PVOID WINAPI dllFlsGetValue(DWORD dwFlsIndex)
1190 CLog::Log(LOGDEBUG, "FlsGetValue(%d)\n", dwFlsIndex);
1192 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1193 return (slot == NULL) ? NULL : slot->pData;
1196 extern "C" BOOL WINAPI dllFlsFree(DWORD dwFlsIndex)
1199 CLog::Log(LOGDEBUG, "FlsFree(%d)\n", dwFlsIndex);
1201 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1205 if( slot->pCallback )
1206 slot->pCallback(slot->pData);
1215 extern "C" PVOID WINAPI dllEncodePointer(PVOID ptr)
1220 extern "C" PVOID WINAPI dllDecodePointer(PVOID ptr)
1226 extern "C" HANDLE WINAPI dllCreateFileA(
1227 IN LPCSTR lpFileName,
1228 IN DWORD dwDesiredAccess,
1229 IN DWORD dwShareMode,
1230 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1231 IN DWORD dwCreationDisposition,
1232 IN DWORD dwFlagsAndAttributes,
1233 IN HANDLE hTemplateFile
1236 return CreateFileA(_P(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
1239 extern "C" BOOL WINAPI dllLockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh)
1241 //return LockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh);
1245 extern "C" BOOL WINAPI dllLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh, LPOVERLAPPED lpOverlapped)
1247 //return LockFileEx(hFile, dwFlags, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh, lpOverlapped);
1251 extern "C" BOOL WINAPI dllUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1253 //return UnlockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1257 extern "C" DWORD WINAPI dllGetTempPathA(DWORD nBufferLength, LPTSTR lpBuffer)
1259 // If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer,
1260 // not including the terminating null character. If the return value is greater than nBufferLength,
1261 // the return value is the size of the buffer required to hold the path.
1262 const char* tempPath = "special://temp/temp/";
1263 unsigned int len = strlen(tempPath);
1265 if (nBufferLength > len)
1267 strcpy(lpBuffer, tempPath);
1273 extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE hModule, HRSRC hResInfo)
1275 not_implement("kernel32.dll fake function LoadResource called\n");
1279 extern "C" HRSRC WINAPI dllFindResourceA(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
1281 not_implement("kernel32.dll fake function FindResource called\n");
1288 The following routine was hacked up by JM while looking at why the DVD player was failing
1289 in the middle of the movie. The symptoms were:
1291 1. DVD player returned error about expecting a NAV packet but none found.
1292 2. Resulted in DVD player closing.
1293 3. Always occured in the same place.
1294 4. Occured on every DVD I tried (originals)
1295 5. Approximately where I would expect the layer change to be (ie just over half way
1297 6. Resulted in the last chunk of the requested data to be NULL'd out completely. ReadFile()
1298 returns correctly, but the last chunk is completely zero'd out.
1300 This routine checks the last chunk for zeros, and re-reads if necessary.
1302 #define DVD_CHUNK_SIZE 2048
1304 extern "C" BOOL WINAPI dllDVDReadFileLayerChangeHack(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
1306 BOOL ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
1307 if (!ret || !lpNumberOfBytesRead || *lpNumberOfBytesRead < DVD_CHUNK_SIZE) return ret;
1308 DWORD numChecked = *lpNumberOfBytesRead;
1309 while (numChecked >= DVD_CHUNK_SIZE)
1311 BYTE *p = (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE;
1312 // test for a NULL block
1313 while (*p == 0 && p < (BYTE *)lpBuffer + numChecked)
1315 if (p == (BYTE *)lpBuffer + numChecked)
1316 { // fully NULL block - reread
1324 low = SetFilePointer(hFile, low, &high, FILE_CURRENT);
1325 CLog::Log(LOGWARNING,
1326 "DVDReadFile() warning - "
1327 "invalid data read from block at %i (%i) - rereading",
1329 SetFilePointer(hFile, (int)numChecked - (int)*lpNumberOfBytesRead - DVD_CHUNK_SIZE, NULL, FILE_CURRENT);
1331 ret = ReadFile(hFile, (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE, DVD_CHUNK_SIZE, &numRead, lpOverlapped);
1332 if (!ret) return FALSE;
1333 SetFilePointer(hFile, low, &high, FILE_BEGIN);
1335 numChecked -= DVD_CHUNK_SIZE;
1340 extern "C" LPVOID WINAPI dllLockResource(HGLOBAL hResData)
1343 return LockResource(hResData);
1345 not_implement("kernel32.dll fake function LockResource called\n"); //warning
1350 extern "C" SIZE_T WINAPI dllGlobalSize(HGLOBAL hMem)
1353 return GlobalSize(hMem);
1355 not_implement("kernel32.dll fake function GlobalSize called\n"); //warning
1360 extern "C" DWORD WINAPI dllSizeofResource(HMODULE hModule, HRSRC hResInfo)
1363 return SizeofResource(hModule, hResInfo);
1365 not_implement("kernel32.dll fake function SizeofResource called\n"); //warning