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)
320 return (DWORD)getppid();
322 return GetCurrentProcessId();
326 CLog::Log(LOGDEBUG, "GetCurrentProcessId(void) => 31337");
332 extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
334 // since the xbox has only one process, we just take the current thread
335 HANDLE h = GetCurrentThread();
336 BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
341 extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
342 HANDLE hSourceHandle, // handle to duplicate
343 HANDLE hTargetProcessHandle, // handle to target process
344 HANDLE* lpTargetHandle, // duplicate handle
345 DWORD dwDesiredAccess, // requested access
346 int bInheritHandle, // handle inheritance option
347 DWORD dwOptions // optional actions
351 CLog::Log(LOGDEBUG, "DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
352 hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
353 lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
355 #if defined (_XBOX) || defined (_LINUX)
356 *lpTargetHandle = hSourceHandle;
359 return DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
363 extern "C" BOOL WINAPI dllDisableThreadLibraryCalls(HMODULE h)
366 return DisableThreadLibraryCalls(h);
368 not_implement("kernel32.dll fake function DisableThreadLibraryCalls called\n"); //warning
373 static void DumpSystemInfo(const SYSTEM_INFO* si)
375 CLog::Log(LOGDEBUG, " Processor architecture %d\n", si->wProcessorArchitecture);
376 CLog::Log(LOGDEBUG, " Page size: %d\n", si->dwPageSize);
377 CLog::Log(LOGDEBUG, " Minimum app address: %d\n", si->lpMinimumApplicationAddress);
378 CLog::Log(LOGDEBUG, " Maximum app address: %d\n", si->lpMaximumApplicationAddress);
379 CLog::Log(LOGDEBUG, " Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
380 CLog::Log(LOGDEBUG, " Number of processors: %d\n", si->dwNumberOfProcessors);
381 CLog::Log(LOGDEBUG, " Processor type: 0x%x\n", si->dwProcessorType);
382 CLog::Log(LOGDEBUG, " Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
383 CLog::Log(LOGDEBUG, " Processor level: 0x%x\n", si->wProcessorLevel);
384 CLog::Log(LOGDEBUG, " Processor revision: 0x%x\n", si->wProcessorRevision);
388 extern "C" void WINAPI dllGetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
391 CLog::Log(LOGDEBUG, "GetSystemInfo(0x%x) =>", lpSystemInfo);
394 // VS 2003 complains about x even so it's defined
395 lpSystemInfo->wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
397 lpSystemInfo->x.wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
399 lpSystemInfo->dwPageSize = 4096; //Xbox page size
400 lpSystemInfo->lpMinimumApplicationAddress = (void *)0x00000000;
401 lpSystemInfo->lpMaximumApplicationAddress = (void *)0x7fffffff;
402 lpSystemInfo->dwActiveProcessorMask = 1;
403 lpSystemInfo->dwNumberOfProcessors = 1;
404 lpSystemInfo->dwProcessorType = 586; //#define PROCESSOR_INTEL_PENTIUM 586
405 lpSystemInfo->wProcessorLevel = 6;
406 //lpSystemInfo->wProcessorLevel = 5;
407 lpSystemInfo->wProcessorRevision = 0x080A;
408 lpSystemInfo->dwAllocationGranularity = 0x10000; //virtualalloc reserve block size
410 DumpSystemInfo(lpSystemInfo);
412 } //hardcode for xbox processor type;
414 extern "C" UINT WINAPI dllGetPrivateProfileIntA(
420 not_implement("kernel32.dll fake function GetPrivateProfileIntA called\n"); //warning
424 //globals for memory leak hack, no need for well-behaved dlls call init/del in pair
425 //We can free the sections if applications does not call deletecriticalsection
426 //need to initialize the list head NULL at mplayer_open_file, and free memory at close file.
427 std::map<LPCRITICAL_SECTION, LPCRITICAL_SECTION> g_mapCriticalSection;
429 extern "C" void WINAPI dllDeleteCriticalSection(LPCRITICAL_SECTION cs)
432 CLog::Log(LOGDEBUG, "DeleteCriticalSection(0x%x)", cs);
434 if (g_mapCriticalSection.find(cs) != g_mapCriticalSection.end())
436 LPCRITICAL_SECTION cs_new = g_mapCriticalSection[cs];
437 DeleteCriticalSection(cs_new);
439 g_mapCriticalSection.erase(cs);
443 extern "C" void WINAPI dllInitializeCriticalSection(LPCRITICAL_SECTION cs)
446 CLog::Log(LOGDEBUG, "InitializeCriticalSection(0x%x)", cs);
448 LPCRITICAL_SECTION cs_new = new CRITICAL_SECTION;
449 memset(cs_new, 0, sizeof(CRITICAL_SECTION));
450 InitializeCriticalSection(cs_new);
452 // just take the first member of the CRITICAL_SECTION to save ourdata in, this will be used to
453 // get fast access to the new critial section in dllLeaveCriticalSection and dllEnterCriticalSection
454 ((LPCRITICAL_SECTION*)cs)[0] = cs_new;
455 g_mapCriticalSection[cs] = cs_new;
458 extern "C" void WINAPI dllLeaveCriticalSection(LPCRITICAL_SECTION cs)
461 CLog::Log(LOGDEBUG, "LeaveCriticalSection(0x%x) %p\n", ((LPCRITICAL_SECTION*)cs)[0]);
463 LeaveCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
466 extern "C" void WINAPI dllEnterCriticalSection(LPCRITICAL_SECTION cs)
469 CLog::Log(LOGDEBUG, "EnterCriticalSection(0x%x) %p\n", cs, ((LPCRITICAL_SECTION*)cs)[0]);
472 if (!(LPCRITICAL_SECTION)cs->OwningThread)
475 CLog::Log(LOGDEBUG, "entered uninitialized critisec!\n");
477 dllInitializeCriticalSection(cs);
480 EnterCriticalSection(((LPCRITICAL_SECTION*)cs)[0]);
483 extern "C" DWORD WINAPI dllGetVersion()
486 CLog::Log(LOGDEBUG, "GetVersion() => 0xC0000004 (Windows 95)\n");
488 //return 0x0a280105; //Windows XP
489 return 0xC0000004; //Windows 95
492 extern "C" BOOL WINAPI dllGetVersionExA(LPOSVERSIONINFO lpVersionInfo)
495 CLog::Log(LOGDEBUG, "GetVersionExA()\n");
497 lpVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
498 lpVersionInfo->dwMajorVersion = 4;
499 lpVersionInfo->dwMinorVersion = 0;
500 lpVersionInfo->dwBuildNumber = 0x4000457;
501 // leave it here for testing win9x-only codecs
502 lpVersionInfo->dwPlatformId = 1; //VER_PLATFORM_WIN32_WINDOWS
503 lpVersionInfo->szCSDVersion[0] = 0;
505 CLog::Log(LOGDEBUG, " Major version: %d\n Minor version: %d\n Build number: %x\n"
506 " Platform Id: %d\n Version string: '%s'\n",
507 lpVersionInfo->dwMajorVersion, lpVersionInfo->dwMinorVersion,
508 lpVersionInfo->dwBuildNumber, lpVersionInfo->dwPlatformId, lpVersionInfo->szCSDVersion);
513 extern "C" BOOL WINAPI dllGetVersionExW(LPOSVERSIONINFOW lpVersionInfo)
516 CLog::Log(LOGDEBUG, "GetVersionExW()\n");
518 if(!dllGetVersionExA((LPOSVERSIONINFO)lpVersionInfo))
521 lpVersionInfo->szCSDVersion[0] = 0;
522 lpVersionInfo->szCSDVersion[1] = 0;
526 extern "C" UINT WINAPI dllGetProfileIntA(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault)
528 // CLog::Log(LOGDEBUG,"GetProfileIntA:%s %s %i", lpAppName,lpKeyName,nDefault);
529 not_implement("kernel32.dll fake function GetProfileIntA called\n"); //warning
533 extern "C" BOOL WINAPI dllFreeEnvironmentStringsW(LPWSTR lpString)
535 // we don't have anything to clean up here, just return.
537 CLog::Log(LOGDEBUG, "FreeEnvironmentStringsA(0x%x) => 1", lpString);
542 extern "C" HMODULE WINAPI dllGetOEMCP()
544 not_implement("kernel32.dll fake function GetOEMCP called\n"); //warning
548 extern "C" HMODULE WINAPI dllRtlUnwind(PVOID TargetFrame OPTIONAL, PVOID TargetIp OPTIONAL, PEXCEPTION_RECORD ExceptionRecord OPTIONAL, PVOID ReturnValue)
550 not_implement("kernel32.dll fake function RtlUnwind called\n"); //warning
553 extern "C" LPTSTR WINAPI dllGetCommandLineA()
556 CLog::Log(LOGDEBUG, "GetCommandLineA() => \"c:\\xbmc.xbe\"\n");
558 return (LPTSTR)"c:\\xbmc.xbe";
561 extern "C" HMODULE WINAPI dllExitProcess(UINT uExitCode)
563 not_implement("kernel32.dll fake function ExitProcess called\n"); //warning
566 extern "C" HMODULE WINAPI dllTerminateProcess(HANDLE hProcess, UINT uExitCode)
568 not_implement("kernel32.dll fake function TerminateProcess called\n"); //warning
571 extern "C" HANDLE WINAPI dllGetCurrentProcess()
573 #if !defined (_XBOX) && !defined(_LINUX)
574 return GetCurrentProcess();
577 return GetCurrentProcess();
580 CLog::Log(LOGDEBUG, "GetCurrentProcess(void) => 9375");
586 extern "C" UINT WINAPI dllGetACP()
589 CLog::Log(LOGDEBUG, "GetACP() => 0");
594 extern "C" UINT WINAPI dllSetHandleCount(UINT uNumber)
596 //Under Windows NT and Windows 95, this function simply returns the value specified in the uNumber parameter.
599 CLog::Log(LOGDEBUG, "SetHandleCount(0x%x) => 1\n", uNumber);
604 extern "C" HANDLE WINAPI dllGetStdHandle(DWORD nStdHandle)
608 case STD_INPUT_HANDLE: return (HANDLE)0;
609 case STD_OUTPUT_HANDLE: return (HANDLE)1;
610 case STD_ERROR_HANDLE: return (HANDLE)2;
612 SetLastError( ERROR_INVALID_PARAMETER );
613 return INVALID_HANDLE_VALUE;
617 #define FILE_TYPE_UNKNOWN 0
618 #define FILE_TYPE_DISK 1
619 #define FILE_TYPE_CHAR 2
622 extern "C" DWORD WINAPI dllGetFileType(HANDLE hFile)
625 CLog::Log(LOGDEBUG, "GetFileType(0x%x) => 0x3 = pipe", hFile);
630 extern "C" int WINAPI dllGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
633 CLog::Log(LOGDEBUG, "GetStartupInfoA(0x%x) => 1\n");
635 lpStartupInfo->cb = sizeof(_STARTUPINFOA);
636 lpStartupInfo->cbReserved2 = 0;
637 lpStartupInfo->dwFillAttribute = 0;
638 lpStartupInfo->dwFlags = 0;
639 lpStartupInfo->dwX = 50; //
640 lpStartupInfo->dwXCountChars = 0;
641 lpStartupInfo->dwXSize = 0;
642 lpStartupInfo->dwY = 50; //
643 lpStartupInfo->dwYCountChars = 0;
644 lpStartupInfo->dwYSize = 0;
645 lpStartupInfo->hStdError = (HANDLE)2;
646 lpStartupInfo->hStdInput = (HANDLE)0;
647 lpStartupInfo->hStdOutput = (HANDLE)1;
648 lpStartupInfo->lpDesktop = NULL;
649 lpStartupInfo->lpReserved = NULL;
650 lpStartupInfo->lpReserved2 = 0;
651 lpStartupInfo->lpTitle = (LPTSTR)"XBMC";
652 lpStartupInfo->wShowWindow = 0;
656 extern "C" BOOL WINAPI dllFreeEnvironmentStringsA(LPSTR lpString)
658 // we don't have anything to clean up here, just return.
662 static const char ch_envs[] =
663 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELETED,1\r\n"
664 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
666 extern "C" LPVOID WINAPI dllGetEnvironmentStrings()
669 return GetEnvironmentStrings();
672 CLog::Log(LOGDEBUG, "GetEnvironmentStrings() => 0x%x = %p", ch_envs, ch_envs);
674 return (LPVOID)ch_envs;
677 extern "C" LPVOID WINAPI dllGetEnvironmentStringsW()
680 return GetEnvironmentStringsW();
685 extern "C" int WINAPI dllGetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
688 return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
690 if (lpBuffer) lpBuffer[0] = 0;
692 if (strcmp(lpName, "__MSVCRT_HEAP_SELECT") == 0)
693 strcpy(lpBuffer, "__GLOBAL_HEAP_SELECTED,1");
695 CLog::Log(LOGDEBUG, "GetEnvironmentVariableA('%s', 0x%x, %d) => %d", lpName, lpBuffer, nSize, strlen(lpBuffer));
697 return strlen(lpBuffer);
700 extern "C" HMODULE WINAPI dllLCMapStringA(LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest)
702 not_implement("kernel32.dll fake function LCMapStringA called\n"); //warning
706 extern "C" HMODULE WINAPI dllLCMapStringW(LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest)
708 not_implement("kernel32.dll fake function LCMapStringW called\n"); //warning
712 extern "C" HMODULE WINAPI dllSetStdHandle(DWORD nStdHandle, HANDLE hHandle)
714 not_implement("kernel32.dll fake function SetStdHandle called\n"); //warning
718 extern "C" HMODULE WINAPI dllGetStringTypeA(LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
720 not_implement("kernel32.dll fake function GetStringTypeA called\n"); //warning
724 extern "C" HMODULE WINAPI dllGetStringTypeW(DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
726 not_implement("kernel32.dll fake function GetStringTypeW called\n"); //warning
730 extern "C" HMODULE WINAPI dllGetCPInfo(UINT CodePage, LPCPINFO lpCPInfo)
732 not_implement("kernel32.dll fake function GetCPInfo called\n"); //warning
736 extern "C" LCID WINAPI dllGetThreadLocale(void)
738 // primary language identifier, sublanguage identifier, sorting identifier
739 return MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
742 extern "C" BOOL WINAPI dllSetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass)
744 not_implement("kernel32.dll fake function SetPriorityClass called\n"); //warning
748 extern "C" DWORD WINAPI dllFormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, va_list* Arguments)
751 return FormatMessageA(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
753 not_implement("kernel32.dll fake function FormatMessage called\n"); //warning
758 extern "C" DWORD WINAPI dllGetFullPathNameA(LPCTSTR lpFileName, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR* lpFilePart)
761 if (!lpFileName) return 0;
762 if(strstr(lpFileName, "://"))
764 unsigned int length = strlen(lpFileName);
765 if (nBufferLength < (length + 1))
769 strcpy(lpBuffer, lpFileName);
772 char* s1 = strrchr(lpBuffer, '\\');
773 char* s2 = strrchr(lpBuffer, '/');
775 *lpFilePart = s1 + 1;
776 else if(s1 && s2 > s1)
777 *lpFilePart = s2 + 1;
779 *lpFilePart = lpBuffer;
784 return GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, lpFilePart);
786 not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
791 extern "C" DWORD WINAPI dllGetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart)
794 if (!lpFileName) return 0;
795 if(wcsstr(lpFileName, L"://"))
797 size_t length = wcslen(lpFileName);
798 if (nBufferLength < (length + 1))
802 wcscpy(lpBuffer, lpFileName);
805 wchar_t* s1 = wcsrchr(lpBuffer, '\\');
806 wchar_t* s2 = wcsrchr(lpBuffer, '/');
808 *lpFilePart = s1 + 1;
809 else if(s1 && s2 > s1)
810 *lpFilePart = s2 + 1;
812 *lpFilePart = lpBuffer;
817 return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
819 not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
824 extern "C" DWORD WINAPI dllExpandEnvironmentStringsA(LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize)
827 return ExpandEnvironmentStringsA(lpSrc, lpDst, nSize);
829 not_implement("kernel32.dll fake function ExpandEnvironmentStringsA called\n"); //warning
834 extern "C" UINT WINAPI dllGetWindowsDirectoryA(LPTSTR lpBuffer, UINT uSize)
836 not_implement("kernel32.dll fake function dllGetWindowsDirectory called\n"); //warning
840 extern "C" UINT WINAPI dllGetSystemDirectoryA(LPTSTR lpBuffer, UINT uSize)
842 //char* systemdir = "special://xbmc/system/mplayer/codecs";
843 //unsigned int len = strlen(systemdir);
844 //if (len > uSize) return 0;
845 //strcpy(lpBuffer, systemdir);
846 //not_implement("kernel32.dll incompete function dllGetSystemDirectory called\n"); //warning
847 //CLog::Log(LOGDEBUG,"KERNEL32!GetSystemDirectoryA(0x%x, %d) => %s", lpBuffer, uSize, systemdir);
850 CLog::Log(LOGDEBUG, "GetSystemDirectoryA(%p,%d)\n", lpBuffer, uSize);
852 if (!lpBuffer) strcpy(lpBuffer, ".");
857 extern "C" UINT WINAPI dllGetShortPathName(LPTSTR lpszLongPath, LPTSTR lpszShortPath, UINT cchBuffer)
859 if (!lpszLongPath) return 0;
860 if (strlen(lpszLongPath) == 0)
862 //strcpy(lpszLongPath, "special://xbmc/system/mplayer/codecs/QuickTime.qts");
865 CLog::Log(LOGDEBUG, "KERNEL32!GetShortPathNameA('%s',%p,%d)\n", lpszLongPath, lpszShortPath, cchBuffer);
867 strcpy(lpszShortPath, lpszLongPath);
868 return strlen(lpszShortPath);
871 extern "C" HANDLE WINAPI dllGetProcessHeap()
874 CLog::Log(LOGWARNING, "KERNEL32!GetProcessHeap() linux cant provide this service!");
878 hHeap = GetProcessHeap();
880 CLog::Log(LOGDEBUG, "KERNEL32!GetProcessHeap() => 0x%x", hHeap);
886 extern "C" UINT WINAPI dllSetErrorMode(UINT i)
889 CLog::Log(LOGDEBUG, "SetErrorMode(%d) => 0\n", i);
894 extern "C" BOOL WINAPI dllIsProcessorFeaturePresent(DWORD ProcessorFeature)
897 switch (ProcessorFeature)
899 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
902 case PF_COMPARE_EXCHANGE_DOUBLE:
905 case PF_FLOATING_POINT_EMULATED:
908 case PF_FLOATING_POINT_PRECISION_ERRATA:
911 case PF_MMX_INSTRUCTIONS_AVAILABLE:
917 case PF_RDTSC_INSTRUCTION_AVAILABLE:
920 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
923 case 10: //PF_XMMI64_INSTRUCTIONS_AVAILABLE
929 CLog::Log(LOGDEBUG, "IsProcessorFeaturePresent(0x%x) => 0x%x\n", ProcessorFeature, result);
934 extern "C" UINT WINAPI dllGetCurrentDirectoryA(UINT c, LPSTR s)
936 char curdir[] = "special://xbmc/";
938 strncpy(s, curdir, c);
939 result = 1 + ((c < strlen(curdir)) ? c : strlen(curdir));
941 CLog::Log(LOGDEBUG, "GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
946 extern "C" UINT WINAPI dllSetCurrentDirectoryA(const char *pathname)
949 CLog::Log(LOGDEBUG, "SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
954 extern "C" int WINAPI dllSetUnhandledExceptionFilter(void* filter)
957 CLog::Log(LOGDEBUG, "SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
959 return 1; //unsupported and probably won't ever be supported
962 extern "C" int WINAPI dllSetEnvironmentVariableA(const char *name, const char *value)
965 CLog::Log(LOGDEBUG, "SetEnvironmentVariableA(%s, %s)\n", name, value);
970 extern "C" int WINAPI dllCreateDirectoryA(const char *pathname, void *sa)
973 CLog::Log(LOGDEBUG, "CreateDirectory(0x%x = %s, 0x%x) => 1\n", pathname, pathname, sa);
978 extern "C" DWORD WINAPI dllWaitForSingleObject(HANDLE hHandle, DWORD dwMiliseconds)
981 CLog::Log(LOGDEBUG, "WaitForSingleObject(0x%x, %d)", hHandle, dwMiliseconds);
983 return WaitForSingleObject(hHandle, dwMiliseconds);
987 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
989 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
993 CLog::Log(LOGDEBUG, "WaitForMultipleObjects(..)");
996 return WaitForMultipleObjects(nCount, lpHandles, fWaitAll, dwMilliseconds);
999 extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProcessAffinityMask, LPDWORD lpSystemAffinityMask)
1001 CLog::Log(LOGDEBUG, "GetProcessAffinityMask(%p, %p, %p) => 1\n",
1002 (void*)hProcess, (void*)lpProcessAffinityMask, (void*)lpSystemAffinityMask);
1003 if (lpProcessAffinityMask)*lpProcessAffinityMask = 1;
1004 if (lpSystemAffinityMask)*lpSystemAffinityMask = 1;
1008 extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData)
1010 if (Locale == LOCALE_SYSTEM_DEFAULT || Locale == LOCALE_USER_DEFAULT)
1012 if (LCType == LOCALE_SISO639LANGNAME)
1016 strcpy(lpLCData, "eng");
1020 else if (LCType == LOCALE_SISO3166CTRYNAME)
1024 strcpy(lpLCData, "US");
1028 else if (LCType == LOCALE_IDEFAULTLANGUAGE)
1032 strcpy(lpLCData, "en-US");
1038 not_implement("kernel32.dll incomplete function GetLocaleInfoA called\n"); //warning
1039 SetLastError(ERROR_INVALID_FUNCTION);
1043 extern "C" UINT WINAPI dllGetConsoleCP()
1045 return 437; // OEM - United States
1048 extern "C" UINT WINAPI dllGetConsoleOutputCP()
1050 return 437; // OEM - United States
1053 // emulated because windows expects different behaviour
1054 // the xbox calculates always 1 character extra for 0 termination
1055 // however, this is only desired when cbMultiByte has the value -1
1056 extern "C" int WINAPI dllMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
1058 // first fix, on windows cchWideChar and cbMultiByte may be the same.
1059 // xbox fails, because it expects cbMultiByte to be at least one character bigger
1060 // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1061 // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1062 int destinationBufferSize = cchWideChar;
1063 LPWSTR destinationBuffer = lpWideCharStr;
1064 if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1065 destinationBufferSize++;
1066 destinationBuffer = (LPWSTR)malloc(destinationBufferSize * sizeof(WCHAR));
1069 int ret = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, destinationBuffer, destinationBufferSize);
1073 // second fix, but only if cchWideChar == 0, and ofcours ret > 0 indicating the function
1074 // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1075 if (cchWideChar == 0) {
1079 // revert the first fix again
1080 if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
1081 // the 0 termination character could never have been written on a windows machine
1082 // because of cchWideChar == cbMultiByte, again xbox added one for it.
1085 memcpy(lpWideCharStr, destinationBuffer, ret * sizeof(WCHAR));
1086 free(destinationBuffer);
1093 // same reason as above
1094 extern "C" int WINAPI dllWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
1096 // first fix, on windows cchWideChar and cbMultiByte may be the same.
1097 // xbox fails, because it expects cbMultiByte to be at least one character bigger
1098 // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
1099 // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
1100 int destinationBufferSize = cbMultiByte;
1101 LPSTR destinationBuffer = lpMultiByteStr;
1102 if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1103 destinationBufferSize++;
1104 destinationBuffer = (LPSTR)malloc(destinationBufferSize * sizeof(char));
1107 int ret = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, destinationBuffer, destinationBufferSize, lpDefaultChar, lpUsedDefaultChar);
1111 // second fix, but only if cbMultiByte == 0, and ofcours ret > 0 indicating the function
1112 // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
1113 if (cbMultiByte == 0) {
1117 // revert the first fix again
1118 if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
1119 // the 0 termination character could never have been written on a windows machine
1120 // because of cchWideChar == cbMultiByte, again xbox added one for it.
1123 memcpy(lpMultiByteStr, destinationBuffer, ret);
1124 free(destinationBuffer);
1131 extern "C" UINT WINAPI dllSetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
1134 return SetConsoleCtrlHandler(HandlerRoutine, Add);
1136 // no consoles exists on the xbox, do nothing
1137 not_implement("kernel32.dll fake function SetConsoleCtrlHandler called\n"); //warning
1138 SetLastError(ERROR_INVALID_FUNCTION);
1143 typedef struct _SFlsSlot
1147 PFLS_CALLBACK_FUNCTION pCallback;
1149 SFlsSlot, *LPSFlsSlot;
1151 #define FLS_NUM_SLOTS 5
1152 #if defined (_XBOX) || defined (_LINUX)
1153 #define FLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
1155 SFlsSlot flsSlots[FLS_NUM_SLOTS] = { { false, NULL, NULL } };
1157 extern "C" DWORD WINAPI dllFlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
1161 CLog::Log(LOGDEBUG, "FlsAlloc(0x%x)\n", lpCallback);
1163 for (i = 0; i < FLS_NUM_SLOTS; i++) {
1164 if( InterlockedCompareExchange(&flsSlots[i].lInUse, 1, 0) == 0 ) {
1165 flsSlots[i].pData = NULL;
1166 flsSlots[i].pCallback = lpCallback;
1170 SetLastError(ERROR_INVALID_PARAMETER);
1171 CLog::Log(LOGERROR, " - Out of fls slots");
1172 return FLS_OUT_OF_INDEXES; // "
1175 static LPSFlsSlot FlsGetSlot(DWORD dwFlsIndex)
1177 if (dwFlsIndex >= FLS_NUM_SLOTS) {
1178 SetLastError(ERROR_INVALID_PARAMETER);
1181 if (flsSlots[dwFlsIndex].lInUse != 1) {
1182 SetLastError(ERROR_INVALID_PARAMETER); // actually ERROR_NO_MEMORY would be correct
1185 return &(flsSlots[dwFlsIndex]);
1188 extern "C" BOOL WINAPI dllFlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
1191 CLog::Log(LOGDEBUG, "FlsSetValue(%d, 0x%x) => 0x%x\n", dwFlsIndex, lpFlsData);
1193 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1196 slot->pData = lpFlsData;
1200 extern "C" PVOID WINAPI dllFlsGetValue(DWORD dwFlsIndex)
1203 CLog::Log(LOGDEBUG, "FlsGetValue(%d)\n", dwFlsIndex);
1205 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1206 return (slot == NULL) ? NULL : slot->pData;
1209 extern "C" BOOL WINAPI dllFlsFree(DWORD dwFlsIndex)
1212 CLog::Log(LOGDEBUG, "FlsFree(%d)\n", dwFlsIndex);
1214 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1218 if( slot->pCallback )
1219 slot->pCallback(slot->pData);
1228 extern "C" PVOID WINAPI dllEncodePointer(PVOID ptr)
1233 extern "C" PVOID WINAPI dllDecodePointer(PVOID ptr)
1239 extern "C" HANDLE WINAPI dllCreateFileA(
1240 IN LPCSTR lpFileName,
1241 IN DWORD dwDesiredAccess,
1242 IN DWORD dwShareMode,
1243 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1244 IN DWORD dwCreationDisposition,
1245 IN DWORD dwFlagsAndAttributes,
1246 IN HANDLE hTemplateFile
1249 return CreateFileA(_P(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
1252 extern "C" BOOL WINAPI dllLockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh)
1254 //return LockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh);
1258 extern "C" BOOL WINAPI dllLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh, LPOVERLAPPED lpOverlapped)
1260 //return LockFileEx(hFile, dwFlags, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh, lpOverlapped);
1264 extern "C" BOOL WINAPI dllUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1266 //return UnlockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1270 extern "C" DWORD WINAPI dllGetTempPathA(DWORD nBufferLength, LPTSTR lpBuffer)
1272 // If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer,
1273 // not including the terminating null character. If the return value is greater than nBufferLength,
1274 // the return value is the size of the buffer required to hold the path.
1275 const char* tempPath = "special://temp/temp/";
1276 unsigned int len = strlen(tempPath);
1278 if (nBufferLength > len)
1280 strcpy(lpBuffer, tempPath);
1286 extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE hModule, HRSRC hResInfo)
1288 not_implement("kernel32.dll fake function LoadResource called\n");
1292 extern "C" HRSRC WINAPI dllFindResourceA(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
1294 not_implement("kernel32.dll fake function FindResource called\n");
1301 The following routine was hacked up by JM while looking at why the DVD player was failing
1302 in the middle of the movie. The symptoms were:
1304 1. DVD player returned error about expecting a NAV packet but none found.
1305 2. Resulted in DVD player closing.
1306 3. Always occured in the same place.
1307 4. Occured on every DVD I tried (originals)
1308 5. Approximately where I would expect the layer change to be (ie just over half way
1310 6. Resulted in the last chunk of the requested data to be NULL'd out completely. ReadFile()
1311 returns correctly, but the last chunk is completely zero'd out.
1313 This routine checks the last chunk for zeros, and re-reads if necessary.
1315 #define DVD_CHUNK_SIZE 2048
1317 extern "C" BOOL WINAPI dllDVDReadFileLayerChangeHack(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
1319 BOOL ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
1320 if (!ret || !lpNumberOfBytesRead || *lpNumberOfBytesRead < DVD_CHUNK_SIZE) return ret;
1321 DWORD numChecked = *lpNumberOfBytesRead;
1322 while (numChecked >= DVD_CHUNK_SIZE)
1324 BYTE *p = (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE;
1325 // test for a NULL block
1326 while (*p == 0 && p < (BYTE *)lpBuffer + numChecked)
1328 if (p == (BYTE *)lpBuffer + numChecked)
1329 { // fully NULL block - reread
1337 low = SetFilePointer(hFile, low, &high, FILE_CURRENT);
1338 CLog::Log(LOGWARNING,
1339 "DVDReadFile() warning - "
1340 "invalid data read from block at %i (%i) - rereading",
1342 SetFilePointer(hFile, (int)numChecked - (int)*lpNumberOfBytesRead - DVD_CHUNK_SIZE, NULL, FILE_CURRENT);
1344 ret = ReadFile(hFile, (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE, DVD_CHUNK_SIZE, &numRead, lpOverlapped);
1345 if (!ret) return FALSE;
1346 SetFilePointer(hFile, low, &high, FILE_BEGIN);
1348 numChecked -= DVD_CHUNK_SIZE;
1353 extern "C" LPVOID WINAPI dllLockResource(HGLOBAL hResData)
1356 return LockResource(hResData);
1358 not_implement("kernel32.dll fake function LockResource called\n"); //warning
1363 extern "C" SIZE_T WINAPI dllGlobalSize(HGLOBAL hMem)
1366 return GlobalSize(hMem);
1368 not_implement("kernel32.dll fake function GlobalSize called\n"); //warning
1373 extern "C" DWORD WINAPI dllSizeofResource(HMODULE hModule, HRSRC hResInfo)
1376 return SizeofResource(hModule, hResInfo);
1378 not_implement("kernel32.dll fake function SizeofResource called\n"); //warning