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;
229 extern "C" void WINAPI dllSleep(DWORD dwTime)
231 return ::Sleep(dwTime);
234 extern "C" DWORD WINAPI dllGetCurrentProcessId(void)
237 return (DWORD)getppid();
239 return GetCurrentProcessId();
243 extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
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);
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
262 CLog::Log(LOGDEBUG, "DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
263 hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
264 lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
267 *lpTargetHandle = hSourceHandle;
270 return DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
274 extern "C" BOOL WINAPI dllDisableThreadLibraryCalls(HMODULE h)
277 return DisableThreadLibraryCalls(h);
279 not_implement("kernel32.dll fake function DisableThreadLibraryCalls called\n"); //warning
284 static void DumpSystemInfo(const SYSTEM_INFO* si)
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);
299 extern "C" void WINAPI dllGetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
302 CLog::Log(LOGDEBUG, "GetSystemInfo(0x%x) =>", lpSystemInfo);
305 // VS 2003 complains about x even so it's defined
306 lpSystemInfo->wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
308 lpSystemInfo->x.wProcessorArchitecture = 0; //#define PROCESSOR_ARCHITECTURE_INTEL 0
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
321 DumpSystemInfo(lpSystemInfo);
323 } //hardcode for xbox processor type;
325 extern "C" UINT WINAPI dllGetPrivateProfileIntA(
331 not_implement("kernel32.dll fake function GetPrivateProfileIntA called\n"); //warning
335 extern "C" DWORD WINAPI dllGetVersion()
338 CLog::Log(LOGDEBUG, "GetVersion() => 0xC0000004 (Windows 95)\n");
340 //return 0x0a280105; //Windows XP
341 return 0xC0000004; //Windows 95
344 extern "C" BOOL WINAPI dllGetVersionExA(LPOSVERSIONINFO lpVersionInfo)
347 CLog::Log(LOGDEBUG, "GetVersionExA()\n");
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;
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);
365 extern "C" BOOL WINAPI dllGetVersionExW(LPOSVERSIONINFOW lpVersionInfo)
368 CLog::Log(LOGDEBUG, "GetVersionExW()\n");
370 if(!dllGetVersionExA((LPOSVERSIONINFO)lpVersionInfo))
373 lpVersionInfo->szCSDVersion[0] = 0;
374 lpVersionInfo->szCSDVersion[1] = 0;
378 extern "C" UINT WINAPI dllGetProfileIntA(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault)
380 // CLog::Log(LOGDEBUG,"GetProfileIntA:%s %s %i", lpAppName,lpKeyName,nDefault);
381 not_implement("kernel32.dll fake function GetProfileIntA called\n"); //warning
385 extern "C" BOOL WINAPI dllFreeEnvironmentStringsW(LPWSTR lpString)
387 // we don't have anything to clean up here, just return.
389 CLog::Log(LOGDEBUG, "FreeEnvironmentStringsA(0x%x) => 1", lpString);
394 extern "C" HMODULE WINAPI dllGetOEMCP()
396 not_implement("kernel32.dll fake function GetOEMCP called\n"); //warning
400 extern "C" HMODULE WINAPI dllRtlUnwind(PVOID TargetFrame OPTIONAL, PVOID TargetIp OPTIONAL, PEXCEPTION_RECORD ExceptionRecord OPTIONAL, PVOID ReturnValue)
402 not_implement("kernel32.dll fake function RtlUnwind called\n"); //warning
405 extern "C" LPTSTR WINAPI dllGetCommandLineA()
408 CLog::Log(LOGDEBUG, "GetCommandLineA() => \"c:\\xbmc.xbe\"\n");
410 return (LPTSTR)"c:\\xbmc.xbe";
413 extern "C" HMODULE WINAPI dllExitProcess(UINT uExitCode)
415 not_implement("kernel32.dll fake function ExitProcess called\n"); //warning
418 extern "C" HMODULE WINAPI dllTerminateProcess(HANDLE hProcess, UINT uExitCode)
420 not_implement("kernel32.dll fake function TerminateProcess called\n"); //warning
423 extern "C" HANDLE WINAPI dllGetCurrentProcess()
426 return GetCurrentProcess();
429 return GetCurrentProcess();
432 CLog::Log(LOGDEBUG, "GetCurrentProcess(void) => 9375");
438 extern "C" UINT WINAPI dllGetACP()
441 CLog::Log(LOGDEBUG, "GetACP() => 0");
446 extern "C" UINT WINAPI dllSetHandleCount(UINT uNumber)
448 //Under Windows NT and Windows 95, this function simply returns the value specified in the uNumber parameter.
451 CLog::Log(LOGDEBUG, "SetHandleCount(0x%x) => 1\n", uNumber);
456 extern "C" HANDLE WINAPI dllGetStdHandle(DWORD nStdHandle)
460 case STD_INPUT_HANDLE: return (HANDLE)0;
461 case STD_OUTPUT_HANDLE: return (HANDLE)1;
462 case STD_ERROR_HANDLE: return (HANDLE)2;
464 SetLastError( ERROR_INVALID_PARAMETER );
465 return INVALID_HANDLE_VALUE;
468 extern "C" DWORD WINAPI dllGetFileType(HANDLE hFile)
471 CLog::Log(LOGDEBUG, "GetFileType(0x%x) => 0x3 = pipe", hFile);
476 extern "C" int WINAPI dllGetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
479 CLog::Log(LOGDEBUG, "GetStartupInfoA(0x%x) => 1\n");
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;
502 extern "C" BOOL WINAPI dllFreeEnvironmentStringsA(LPSTR lpString)
504 // we don't have anything to clean up here, just return.
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";
512 extern "C" LPVOID WINAPI dllGetEnvironmentStrings()
515 return GetEnvironmentStrings();
518 CLog::Log(LOGDEBUG, "GetEnvironmentStrings() => 0x%x = %p", ch_envs, ch_envs);
520 return (LPVOID)ch_envs;
523 extern "C" LPVOID WINAPI dllGetEnvironmentStringsW()
526 return GetEnvironmentStringsW();
531 extern "C" int WINAPI dllGetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
534 return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
536 if (lpBuffer) lpBuffer[0] = 0;
538 if (strcmp(lpName, "__MSVCRT_HEAP_SELECT") == 0)
539 strcpy(lpBuffer, "__GLOBAL_HEAP_SELECTED,1");
541 CLog::Log(LOGDEBUG, "GetEnvironmentVariableA('%s', 0x%x, %d) => %d", lpName, lpBuffer, nSize, strlen(lpBuffer));
543 return strlen(lpBuffer);
546 extern "C" HMODULE WINAPI dllLCMapStringA(LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest)
548 not_implement("kernel32.dll fake function LCMapStringA called\n"); //warning
552 extern "C" HMODULE WINAPI dllLCMapStringW(LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest)
554 not_implement("kernel32.dll fake function LCMapStringW called\n"); //warning
558 extern "C" HMODULE WINAPI dllSetStdHandle(DWORD nStdHandle, HANDLE hHandle)
560 not_implement("kernel32.dll fake function SetStdHandle called\n"); //warning
564 extern "C" HMODULE WINAPI dllGetStringTypeA(LCID Locale, DWORD dwInfoType, LPCSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
566 not_implement("kernel32.dll fake function GetStringTypeA called\n"); //warning
570 extern "C" HMODULE WINAPI dllGetStringTypeW(DWORD dwInfoType, LPCWSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
572 not_implement("kernel32.dll fake function GetStringTypeW called\n"); //warning
576 extern "C" HMODULE WINAPI dllGetCPInfo(UINT CodePage, LPCPINFO lpCPInfo)
578 not_implement("kernel32.dll fake function GetCPInfo called\n"); //warning
582 extern "C" LCID WINAPI dllGetThreadLocale(void)
584 // primary language identifier, sublanguage identifier, sorting identifier
585 return MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
588 extern "C" BOOL WINAPI dllSetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass)
590 not_implement("kernel32.dll fake function SetPriorityClass called\n"); //warning
594 extern "C" DWORD WINAPI dllFormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPTSTR lpBuffer, DWORD nSize, va_list* Arguments)
597 return FormatMessageA(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
599 not_implement("kernel32.dll fake function FormatMessage called\n"); //warning
604 extern "C" DWORD WINAPI dllGetFullPathNameA(LPCTSTR lpFileName, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR* lpFilePart)
607 if (!lpFileName) return 0;
608 if(strstr(lpFileName, "://"))
610 unsigned int length = strlen(lpFileName);
611 if (nBufferLength < (length + 1))
615 strcpy(lpBuffer, lpFileName);
618 char* s1 = strrchr(lpBuffer, '\\');
619 char* s2 = strrchr(lpBuffer, '/');
621 *lpFilePart = s1 + 1;
622 else if(s1 && s2 > s1)
623 *lpFilePart = s2 + 1;
625 *lpFilePart = lpBuffer;
630 return GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, lpFilePart);
632 not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
637 extern "C" DWORD WINAPI dllGetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart)
640 if (!lpFileName) return 0;
641 if(wcsstr(lpFileName, L"://"))
643 size_t length = wcslen(lpFileName);
644 if (nBufferLength < (length + 1))
648 wcscpy(lpBuffer, lpFileName);
651 wchar_t* s1 = wcsrchr(lpBuffer, '\\');
652 wchar_t* s2 = wcsrchr(lpBuffer, '/');
654 *lpFilePart = s1 + 1;
655 else if(s1 && s2 > s1)
656 *lpFilePart = s2 + 1;
658 *lpFilePart = lpBuffer;
663 return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart);
665 not_implement("kernel32.dll fake function GetFullPathNameW called\n"); //warning
670 extern "C" DWORD WINAPI dllExpandEnvironmentStringsA(LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize)
673 return ExpandEnvironmentStringsA(lpSrc, lpDst, nSize);
675 not_implement("kernel32.dll fake function ExpandEnvironmentStringsA called\n"); //warning
680 extern "C" UINT WINAPI dllGetWindowsDirectoryA(LPTSTR lpBuffer, UINT uSize)
682 not_implement("kernel32.dll fake function dllGetWindowsDirectory called\n"); //warning
686 extern "C" UINT WINAPI dllGetSystemDirectoryA(LPTSTR lpBuffer, UINT uSize)
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);
696 CLog::Log(LOGDEBUG, "GetSystemDirectoryA(%p,%d)\n", lpBuffer, uSize);
698 if (!lpBuffer) strcpy(lpBuffer, ".");
703 extern "C" UINT WINAPI dllGetShortPathName(LPTSTR lpszLongPath, LPTSTR lpszShortPath, UINT cchBuffer)
705 if (!lpszLongPath) return 0;
706 if (strlen(lpszLongPath) == 0)
708 //strcpy(lpszLongPath, "special://xbmc/system/mplayer/codecs/QuickTime.qts");
711 CLog::Log(LOGDEBUG, "KERNEL32!GetShortPathNameA('%s',%p,%d)\n", lpszLongPath, lpszShortPath, cchBuffer);
713 strcpy(lpszShortPath, lpszLongPath);
714 return strlen(lpszShortPath);
717 extern "C" HANDLE WINAPI dllGetProcessHeap()
720 CLog::Log(LOGWARNING, "KERNEL32!GetProcessHeap() linux cant provide this service!");
724 hHeap = GetProcessHeap();
726 CLog::Log(LOGDEBUG, "KERNEL32!GetProcessHeap() => 0x%x", hHeap);
732 extern "C" UINT WINAPI dllSetErrorMode(UINT i)
735 CLog::Log(LOGDEBUG, "SetErrorMode(%d) => 0\n", i);
740 extern "C" BOOL WINAPI dllIsProcessorFeaturePresent(DWORD ProcessorFeature)
743 switch (ProcessorFeature)
745 case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
748 case PF_COMPARE_EXCHANGE_DOUBLE:
751 case PF_FLOATING_POINT_EMULATED:
754 case PF_FLOATING_POINT_PRECISION_ERRATA:
757 case PF_MMX_INSTRUCTIONS_AVAILABLE:
763 case PF_RDTSC_INSTRUCTION_AVAILABLE:
766 case PF_XMMI_INSTRUCTIONS_AVAILABLE:
769 case 10: //PF_XMMI64_INSTRUCTIONS_AVAILABLE
775 CLog::Log(LOGDEBUG, "IsProcessorFeaturePresent(0x%x) => 0x%x\n", ProcessorFeature, result);
780 extern "C" UINT WINAPI dllGetCurrentDirectoryA(UINT c, LPSTR s)
782 char curdir[] = "special://xbmc/";
784 strncpy(s, curdir, c);
785 result = 1 + ((c < strlen(curdir)) ? c : strlen(curdir));
787 CLog::Log(LOGDEBUG, "GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
792 extern "C" UINT WINAPI dllSetCurrentDirectoryA(const char *pathname)
795 CLog::Log(LOGDEBUG, "SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
800 extern "C" int WINAPI dllSetUnhandledExceptionFilter(void* filter)
803 CLog::Log(LOGDEBUG, "SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
805 return 1; //unsupported and probably won't ever be supported
808 extern "C" int WINAPI dllSetEnvironmentVariableA(const char *name, const char *value)
811 CLog::Log(LOGDEBUG, "SetEnvironmentVariableA(%s, %s)\n", name, value);
816 extern "C" int WINAPI dllCreateDirectoryA(const char *pathname, void *sa)
819 CLog::Log(LOGDEBUG, "CreateDirectory(0x%x = %s, 0x%x) => 1\n", pathname, pathname, sa);
824 extern "C" DWORD WINAPI dllWaitForSingleObject(HANDLE hHandle, DWORD dwMiliseconds)
827 CLog::Log(LOGDEBUG, "WaitForSingleObject(0x%x, %d)", hHandle, dwMiliseconds);
829 return WaitForSingleObject(hHandle, dwMiliseconds);
833 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
835 extern "C" DWORD WINAPI dllWaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
839 CLog::Log(LOGDEBUG, "WaitForMultipleObjects(..)");
842 return WaitForMultipleObjects(nCount, lpHandles, fWaitAll, dwMilliseconds);
845 extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProcessAffinityMask, LPDWORD lpSystemAffinityMask)
847 CLog::Log(LOGDEBUG, "GetProcessAffinityMask(%p, %p, %p) => 1\n",
848 (void*)hProcess, (void*)lpProcessAffinityMask, (void*)lpSystemAffinityMask);
849 if (lpProcessAffinityMask)*lpProcessAffinityMask = 1;
850 if (lpSystemAffinityMask)*lpSystemAffinityMask = 1;
854 extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData)
856 if (Locale == LOCALE_SYSTEM_DEFAULT || Locale == LOCALE_USER_DEFAULT)
858 if (LCType == LOCALE_SISO639LANGNAME)
862 strcpy(lpLCData, "eng");
866 else if (LCType == LOCALE_SISO3166CTRYNAME)
870 strcpy(lpLCData, "US");
874 else if (LCType == LOCALE_IDEFAULTLANGUAGE)
878 strcpy(lpLCData, "en-US");
884 not_implement("kernel32.dll incomplete function GetLocaleInfoA called\n"); //warning
885 SetLastError(ERROR_INVALID_FUNCTION);
889 extern "C" UINT WINAPI dllGetConsoleCP()
891 return 437; // OEM - United States
894 extern "C" UINT WINAPI dllGetConsoleOutputCP()
896 return 437; // OEM - United States
899 // emulated because windows expects different behaviour
900 // the xbox calculates always 1 character extra for 0 termination
901 // however, this is only desired when cbMultiByte has the value -1
902 extern "C" int WINAPI dllMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
904 // first fix, on windows cchWideChar and cbMultiByte may be the same.
905 // xbox fails, because it expects cbMultiByte to be at least one character bigger
906 // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
907 // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
908 int destinationBufferSize = cchWideChar;
909 LPWSTR destinationBuffer = lpWideCharStr;
910 if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
911 destinationBufferSize++;
912 destinationBuffer = (LPWSTR)malloc(destinationBufferSize * sizeof(WCHAR));
915 int ret = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, destinationBuffer, destinationBufferSize);
919 // second fix, but only if cchWideChar == 0, and ofcours ret > 0 indicating the function
920 // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
921 if (cchWideChar == 0) {
925 // revert the first fix again
926 if (cbMultiByte > 0 && cbMultiByte == cchWideChar) {
927 // the 0 termination character could never have been written on a windows machine
928 // because of cchWideChar == cbMultiByte, again xbox added one for it.
931 memcpy(lpWideCharStr, destinationBuffer, ret * sizeof(WCHAR));
932 free(destinationBuffer);
939 // same reason as above
940 extern "C" int WINAPI dllWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
942 // first fix, on windows cchWideChar and cbMultiByte may be the same.
943 // xbox fails, because it expects cbMultiByte to be at least one character bigger
944 // solution, create a new buffer to can hold the new data and copy it (without the 0 termination)
945 // to lpMultiByteStr. This is needed because we cannot be sure that lpMultiByteStr is big enough
946 int destinationBufferSize = cbMultiByte;
947 LPSTR destinationBuffer = lpMultiByteStr;
948 if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
949 destinationBufferSize++;
950 destinationBuffer = (LPSTR)malloc(destinationBufferSize * sizeof(char));
953 int ret = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, destinationBuffer, destinationBufferSize, lpDefaultChar, lpUsedDefaultChar);
957 // second fix, but only if cbMultiByte == 0, and ofcours ret > 0 indicating the function
958 // returned the number of bytes needed, otherwise ret would be 0, meaning a successfull conversion
959 if (cbMultiByte == 0) {
963 // revert the first fix again
964 if (cchWideChar > 0 && cchWideChar == cbMultiByte) {
965 // the 0 termination character could never have been written on a windows machine
966 // because of cchWideChar == cbMultiByte, again xbox added one for it.
969 memcpy(lpMultiByteStr, destinationBuffer, ret);
970 free(destinationBuffer);
977 extern "C" UINT WINAPI dllSetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
980 return SetConsoleCtrlHandler(HandlerRoutine, Add);
982 // no consoles exists on the xbox, do nothing
983 not_implement("kernel32.dll fake function SetConsoleCtrlHandler called\n"); //warning
984 SetLastError(ERROR_INVALID_FUNCTION);
989 typedef struct _SFlsSlot
993 PFLS_CALLBACK_FUNCTION pCallback;
995 SFlsSlot, *LPSFlsSlot;
997 #define FLS_NUM_SLOTS 5
999 #define FLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
1001 SFlsSlot flsSlots[FLS_NUM_SLOTS] = { { false, NULL, NULL } };
1003 extern "C" DWORD WINAPI dllFlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
1007 CLog::Log(LOGDEBUG, "FlsAlloc(0x%x)\n", lpCallback);
1009 for (i = 0; i < FLS_NUM_SLOTS; i++) {
1010 if( InterlockedCompareExchange(&flsSlots[i].lInUse, 1, 0) == 0 ) {
1011 flsSlots[i].pData = NULL;
1012 flsSlots[i].pCallback = lpCallback;
1016 SetLastError(ERROR_INVALID_PARAMETER);
1017 CLog::Log(LOGERROR, " - Out of fls slots");
1018 return FLS_OUT_OF_INDEXES; // "
1021 static LPSFlsSlot FlsGetSlot(DWORD dwFlsIndex)
1023 if (dwFlsIndex >= FLS_NUM_SLOTS) {
1024 SetLastError(ERROR_INVALID_PARAMETER);
1027 if (flsSlots[dwFlsIndex].lInUse != 1) {
1028 SetLastError(ERROR_INVALID_PARAMETER); // actually ERROR_NO_MEMORY would be correct
1031 return &(flsSlots[dwFlsIndex]);
1034 extern "C" BOOL WINAPI dllFlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
1037 CLog::Log(LOGDEBUG, "FlsSetValue(%d, 0x%x) => 0x%x\n", dwFlsIndex, lpFlsData);
1039 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1042 slot->pData = lpFlsData;
1046 extern "C" PVOID WINAPI dllFlsGetValue(DWORD dwFlsIndex)
1049 CLog::Log(LOGDEBUG, "FlsGetValue(%d)\n", dwFlsIndex);
1051 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1052 return (slot == NULL) ? NULL : slot->pData;
1055 extern "C" BOOL WINAPI dllFlsFree(DWORD dwFlsIndex)
1058 CLog::Log(LOGDEBUG, "FlsFree(%d)\n", dwFlsIndex);
1060 LPSFlsSlot slot = FlsGetSlot(dwFlsIndex);
1064 if( slot->pCallback )
1065 slot->pCallback(slot->pData);
1074 extern "C" PVOID WINAPI dllEncodePointer(PVOID ptr)
1079 extern "C" PVOID WINAPI dllDecodePointer(PVOID ptr)
1085 extern "C" HANDLE WINAPI dllCreateFileA(
1086 IN LPCSTR lpFileName,
1087 IN DWORD dwDesiredAccess,
1088 IN DWORD dwShareMode,
1089 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1090 IN DWORD dwCreationDisposition,
1091 IN DWORD dwFlagsAndAttributes,
1092 IN HANDLE hTemplateFile
1095 return CreateFileA(_P(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
1098 extern "C" BOOL WINAPI dllLockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh)
1100 //return LockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh);
1104 extern "C" BOOL WINAPI dllLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOffBytesToLockLow, DWORD nNumberOffBytesToLockHigh, LPOVERLAPPED lpOverlapped)
1106 //return LockFileEx(hFile, dwFlags, nNumberOffBytesToLockLow, nNumberOffBytesToLockHigh, lpOverlapped);
1110 extern "C" BOOL WINAPI dllUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1112 //return UnlockFile(hFile, dwFileOffsetLow, dwFileOffsetHigh, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
1116 extern "C" DWORD WINAPI dllGetTempPathA(DWORD nBufferLength, LPTSTR lpBuffer)
1118 // If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer,
1119 // not including the terminating null character. If the return value is greater than nBufferLength,
1120 // the return value is the size of the buffer required to hold the path.
1121 const char* tempPath = "special://temp/temp/";
1122 unsigned int len = strlen(tempPath);
1124 if (nBufferLength > len)
1126 strcpy(lpBuffer, tempPath);
1132 extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE hModule, HRSRC hResInfo)
1134 not_implement("kernel32.dll fake function LoadResource called\n");
1138 extern "C" HRSRC WINAPI dllFindResourceA(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
1140 not_implement("kernel32.dll fake function FindResource called\n");
1147 The following routine was hacked up by JM while looking at why the DVD player was failing
1148 in the middle of the movie. The symptoms were:
1150 1. DVD player returned error about expecting a NAV packet but none found.
1151 2. Resulted in DVD player closing.
1152 3. Always occured in the same place.
1153 4. Occured on every DVD I tried (originals)
1154 5. Approximately where I would expect the layer change to be (ie just over half way
1156 6. Resulted in the last chunk of the requested data to be NULL'd out completely. ReadFile()
1157 returns correctly, but the last chunk is completely zero'd out.
1159 This routine checks the last chunk for zeros, and re-reads if necessary.
1161 #define DVD_CHUNK_SIZE 2048
1163 extern "C" BOOL WINAPI dllDVDReadFileLayerChangeHack(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
1165 BOOL ret = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
1166 if (!ret || !lpNumberOfBytesRead || *lpNumberOfBytesRead < DVD_CHUNK_SIZE) return ret;
1167 DWORD numChecked = *lpNumberOfBytesRead;
1168 while (numChecked >= DVD_CHUNK_SIZE)
1170 BYTE *p = (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE;
1171 // test for a NULL block
1172 while (*p == 0 && p < (BYTE *)lpBuffer + numChecked)
1174 if (p == (BYTE *)lpBuffer + numChecked)
1175 { // fully NULL block - reread
1183 low = SetFilePointer(hFile, low, &high, FILE_CURRENT);
1184 CLog::Log(LOGWARNING,
1185 "DVDReadFile() warning - "
1186 "invalid data read from block at %i (%i) - rereading",
1188 SetFilePointer(hFile, (int)numChecked - (int)*lpNumberOfBytesRead - DVD_CHUNK_SIZE, NULL, FILE_CURRENT);
1190 ret = ReadFile(hFile, (BYTE *)lpBuffer + numChecked - DVD_CHUNK_SIZE, DVD_CHUNK_SIZE, &numRead, lpOverlapped);
1191 if (!ret) return FALSE;
1192 SetFilePointer(hFile, low, &high, FILE_BEGIN);
1194 numChecked -= DVD_CHUNK_SIZE;
1199 extern "C" LPVOID WINAPI dllLockResource(HGLOBAL hResData)
1202 return LockResource(hResData);
1204 not_implement("kernel32.dll fake function LockResource called\n"); //warning
1209 extern "C" SIZE_T WINAPI dllGlobalSize(HGLOBAL hMem)
1212 return GlobalSize(hMem);
1214 not_implement("kernel32.dll fake function GlobalSize called\n"); //warning
1219 extern "C" DWORD WINAPI dllSizeofResource(HMODULE hModule, HRSRC hResInfo)
1222 return SizeofResource(hModule, hResInfo);
1224 not_implement("kernel32.dll fake function SizeofResource called\n"); //warning