diff --git a/CHANGELOG.txt b/CHANGELOG.txt index e7c63bc..dffd585 100755 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,37 @@ +KernelEx v4.5 RC 4 by Xeno86 +2010-09-21 + +added kernel32.EncodePointer, DecodePointer, EncodeSystemPointer, DecodeSystemPointer +SystemParametersInfo/SPI_GETHIGHCONTRAST call doesn't fail now when accessability pack is not installed or wrong uiParam parameter is passed (fixes Firefox 3.6.9/3.6.10) +force usage of KernelEx's 'Known DLLs' when full system path is passed to LoadLibrary call +fixed iGetProcAddress/kexGetProcAddress not taking into account relocation - fixes crashes revealed by RC 3 + +--------------------------------------- + +KernelEx v4.5 RC 3 by Xeno86 +2010-09-10 + +added fix to prevent DLL circular-references + +--------------------------------------- + +KernelEx v4.5 RC 2 by Xeno86 +2010-09-08 + +ported SysLink COMCTL32 class (from Wine project, fixes Google Picasa options dialog) +added kernel32.SystemTimeToTzSpecificLocalTime, TzSpecificLocalTimeToSystemTime (from Wine project, for Google Picasa 3.8) +implemented shell32.SHBindToParent (needed by Maxthon 1.6.7) [Tihiy] +fixed TlsExt pointer not zeroed after freeing +added WS2_32.getaddrinfo, freeaddrinfo, getnameinfo implementation based on wspiapi.h +added WINMM.waveInGetDevCapsW, waveOutGetDevCapsW (makes Flash Player 10.1 volume control work) +added USER32.SetParent fix to forbid deadly circular references (fixes VLC 1.1.2 crash) [ported from RP9] +fixed handling of lpOverlapped parameter in kernel32.PostQueuedCompletionStatus +restricted completion ports to NT only +added kernel32.GetProcessId, CreateFiberEx +replaced kernel32.ReadConsoleInputW from MSLU with custom implementation due to bugs in the former [Tihiy] + +--------------------------------------- + KernelEx v4.5 RC 1 by Xeno86 2010-07-30 diff --git a/KernelEx.nsi b/KernelEx.nsi index 44661ca..724b217 100755 --- a/KernelEx.nsi +++ b/KernelEx.nsi @@ -1,4 +1,4 @@ - !define _VERSION '4.5 RC 1' + !define _VERSION '4.5 RC 4' !ifndef _DEBUG !define FLAVOUR 'Release' diff --git a/NEWS.txt b/NEWS.txt index c7cca1c..6394d5b 100755 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,41 @@ +KernelEx v4.5 RC 4 by Xeno86 +2010-09-21 + +What's new: +----------- +* Fixed: missing background colors and images in Mozilla Firefox 3.6.9/3.6.10 +* Fixed: MSIMG32 warning and menu icon transparency issues in Opera 10.62 +* Fixed: crashes introduced in RC 3 +* KernelEx auxiliary libraries weren't loaded when full path to system file was passed in call to LoadLibary + +################################################# + +KernelEx v4.5 RC 3 by Xeno86 +2010-09-10 + +hotfix to prevent DLL circular-references causing crashes on certain configurations + +################################################# + +KernelEx v4.5 RC 2 by Xeno86 +2010-09-08 + +What's new: +----------- +* Implemented SysLink common control class + +Apps fixed / now working: +------------------------- +* Fixed: Google Picasa options dialog (empty tabs) +* Fixed: Adobe Flash Player crashes (reported by mailcat via sf.net forum) +* Fixed: Adobe Flash Player 10.1 volume control +* Fixed: Wizard101 game crash (bug #3041092) +* Fixed: Maxthon browser (freezing) +* Now working: Maxthon 1.6.7 +* Now working: VLC 1.1.2 (without RP9) + +################################################# + KernelEx v4.5 RC 1 by Xeno86 2010-07-30 @@ -18,7 +56,7 @@ Apps fixed / now working: * Fixed: VLC 1.0+ (UI) * Fixed: Firefox 3.6.4+ (high cpu usage) * Now working: Adobe Flash 10.1 plugin -* Now working: Mozilla Firefox 4.0 Beta 1 +* Now working: Mozilla Firefox 4.0 Beta 2 * Now working: Artweaver 1.0 * Now working: MPC-HC (newer builds, svn build 1391+) diff --git a/apilibs/CORE.INI b/apilibs/CORE.INI index 3de8a91..19342dd 100755 --- a/apilibs/CORE.INI +++ b/apilibs/CORE.INI @@ -28,6 +28,7 @@ GDI32.SetMapMode=std KERNEL32.VerSetConditionMask=none KERNEL32.VerifyVersionInfoA=none KERNEL32.VerifyVersionInfoW=none +KERNEL32.CreateIoCompletionPort=std SHELL32.SHParseDisplayName=none [DCFG1.names.Me] @@ -42,6 +43,7 @@ GDI32.SetMapMode=std KERNEL32.VerSetConditionMask=none KERNEL32.VerifyVersionInfoA=none KERNEL32.VerifyVersionInfoW=none +KERNEL32.CreateIoCompletionPort=std USER32.AllowSetForegroundWindow=std USER32.LockSetForegroundWindow=std USER32.GetMouseMovePointsEx=std @@ -82,6 +84,7 @@ desc=Windows NT 4.0 SP6 KERNEL32.GetVersion=kexbases.3 KERNEL32.GetVersionExA=kexbases.4 KERNEL32.GetVersionExW=kexbases.4 +KERNEL32.CreateIoCompletionPort=kexbases.0 GDI32.GetRandomRgn=kexbases.0 GDI32.SetGraphicsMode=kexbases.0 GDI32.GetTextMetricsA=kexbases.0 diff --git a/apilibs/kexbasen/comdlg32/_comdlg32_apilist.h b/apilibs/kexbasen/comdlg32/_comdlg32_apilist.h index 6546cb0..646f720 100755 --- a/apilibs/kexbasen/comdlg32/_comdlg32_apilist.h +++ b/apilibs/kexbasen/comdlg32/_comdlg32_apilist.h @@ -23,6 +23,7 @@ #define _COMDLG32_APILIST_H #include "kexcoresdk.h" +#include BOOL init_comdlg32(); extern const apilib_api_table apitable_comdlg32; diff --git a/apilibs/kexbasen/common.h b/apilibs/kexbasen/common.h index 15fdb90..36d0b98 100755 --- a/apilibs/kexbasen/common.h +++ b/apilibs/kexbasen/common.h @@ -22,13 +22,17 @@ #ifndef __COMMON_H #define __COMMON_H +#define WIN32_LEAN_AND_MEAN #include #include +#include "kexcoresdk.h" #ifdef __cplusplus extern "C" { #endif +void* __cdecl recalloc(void* ptr, size_t size); + typedef int __stdcall STUB(void); typedef int __stdcall FWDPROC(void); diff --git a/apilibs/kexbasen/dirlist b/apilibs/kexbasen/dirlist index e44e532..a9786a4 100755 --- a/apilibs/kexbasen/dirlist +++ b/apilibs/kexbasen/dirlist @@ -7,3 +7,5 @@ shell32 rpcrt4 winspool shfolder +winmm +ws2_32 diff --git a/apilibs/kexbasen/kernel32/DelayLoadFailureHook.c b/apilibs/kexbasen/kernel32/DelayLoadFailureHook.c index 9f06a6e..95fde93 100755 --- a/apilibs/kexbasen/kernel32/DelayLoadFailureHook.c +++ b/apilibs/kexbasen/kernel32/DelayLoadFailureHook.c @@ -19,7 +19,7 @@ * */ -#include +#include "common.h" typedef struct { @@ -52,7 +52,7 @@ FARPROC WINAPI DelayLoadFailureHook_new( hShlwapi = LoadLibrary("shlwapi.dll"); } - DLFH ShlwapiDelayLoad = (DLFH) GetProcAddress(hShlwapi,"DelayLoadFailureHook"); + DLFH ShlwapiDelayLoad = (DLFH) kexGetProcAddress(hShlwapi,"DelayLoadFailureHook"); if (!ShlwapiDelayLoad) return NULL; diff --git a/apilibs/kexbasen/kernel32/TlsExt.c b/apilibs/kexbasen/kernel32/TlsExt.c index d355ae8..1ff21c7 100755 --- a/apilibs/kexbasen/kernel32/TlsExt.c +++ b/apilibs/kexbasen/kernel32/TlsExt.c @@ -127,7 +127,10 @@ void detach_exttls(void) ext = (LPVOID*) tdb->TlsSlots[TLS_SIZE-1]; if (ext) + { HeapFree(GetProcessHeap(), 0, ext); + tdb->TlsSlots[TLS_SIZE-1] = 0; + } } /* MAKE_EXPORT TlsAlloc_new=TlsAlloc */ diff --git a/apilibs/kexbasen/kernel32/_kernel32_apilist.c b/apilibs/kexbasen/kernel32/_kernel32_apilist.c index b1b8ae7..f984294 100755 --- a/apilibs/kexbasen/kernel32/_kernel32_apilist.c +++ b/apilibs/kexbasen/kernel32/_kernel32_apilist.c @@ -112,7 +112,6 @@ static const apilib_named_api kernel32_named_apis[] = DECL_API("PeekConsoleInputW", PeekConsoleInputW_fwd), DECL_API("QueryDosDeviceW", QueryDosDeviceW_fwd), DECL_API("QueueUserWorkItem", QueueUserWorkItem_new), - DECL_API("ReadConsoleInputW", ReadConsoleInputW_fwd), DECL_API("ReadConsoleOutputCharacterW", ReadConsoleOutputCharacterW_fwd), DECL_API("ReadConsoleOutputW", ReadConsoleOutputW_fwd), DECL_API("ReadConsoleW", ReadConsoleW_fwd), diff --git a/apilibs/kexbasen/kernel32/_kernel32_apilist.h b/apilibs/kexbasen/kernel32/_kernel32_apilist.h index a4b1989..05ba681 100755 --- a/apilibs/kexbasen/kernel32/_kernel32_apilist.h +++ b/apilibs/kexbasen/kernel32/_kernel32_apilist.h @@ -108,7 +108,6 @@ FWDPROC OpenSemaphoreW_fwd; FWDPROC OpenWaitableTimerW_fwd; FWDPROC PeekConsoleInputW_fwd; FWDPROC QueryDosDeviceW_fwd; -FWDPROC ReadConsoleInputW_fwd; FWDPROC ReadConsoleOutputCharacterW_fwd; FWDPROC ReadConsoleOutputW_fwd; FWDPROC ReadConsoleW_fwd; diff --git a/apilibs/kexbasen/kernel32/unikernel32.c b/apilibs/kexbasen/kernel32/unikernel32.c index 4234c97..6e589b2 100755 --- a/apilibs/kexbasen/kernel32/unikernel32.c +++ b/apilibs/kexbasen/kernel32/unikernel32.c @@ -73,7 +73,6 @@ FORWARD_TO_UNICOWS(OpenSemaphoreW); FORWARD_TO_UNICOWS(OpenWaitableTimerW); FORWARD_TO_UNICOWS(PeekConsoleInputW); FORWARD_TO_UNICOWS(QueryDosDeviceW); -FORWARD_TO_UNICOWS(ReadConsoleInputW); FORWARD_TO_UNICOWS(ReadConsoleOutputCharacterW); FORWARD_TO_UNICOWS(ReadConsoleOutputW); FORWARD_TO_UNICOWS(ReadConsoleW); diff --git a/apilibs/kexbasen/kexbasen.dsp b/apilibs/kexbasen/kexbasen.dsp index f54d03e..e2df6af 100755 --- a/apilibs/kexbasen/kexbasen.dsp +++ b/apilibs/kexbasen/kexbasen.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shlwapi.lib shell32.lib rpcrt4.lib usp10.lib ../../common/KernelEx.lib ../../kexcrt/kexcrt.lib libc.lib delayimp.lib /nologo /dll /map /machine:I386 /nodefaultlib /OPT:NOWIN98 /DELAYLOAD:shell32.dll /DELAYLOAD:rpcrt4.dll /DELAYLOAD:usp10.dll /DELAYLOAD:comdlg32.dll /DELAYLOAD:winspool.drv /DELAYLOAD:shlwapi.dll +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shlwapi.lib shell32.lib rpcrt4.lib usp10.lib winmm.lib ws2_32.lib ../../common/KernelEx.lib ../../kexcrt/kexcrt.lib libc.lib delayimp.lib /nologo /dll /map /machine:I386 /nodefaultlib /OPT:NOWIN98 /DELAYLOAD:shell32.dll /DELAYLOAD:rpcrt4.dll /DELAYLOAD:usp10.dll /DELAYLOAD:comdlg32.dll /DELAYLOAD:winspool.drv /DELAYLOAD:shlwapi.dll /DELAYLOAD:winmm.dll /DELAYLOAD:ws2_32.dll # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "KernelEx Base NonShared - Win32 Debug" @@ -80,7 +80,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shlwapi.lib shell32.lib rpcrt4.lib usp10.lib ../../common/KernelEx.lib ../../kexcrt/kexcrt.lib libc.lib delayimp.lib /nologo /dll /map /debug /machine:I386 /nodefaultlib /OPT:NOWIN98 /DELAYLOAD:shell32.dll /DELAYLOAD:rpcrt4.dll /DELAYLOAD:usp10.dll /DELAYLOAD:comdlg32.dll /DELAYLOAD:winspool.drv /DELAYLOAD:shlwapi.dll +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shlwapi.lib shell32.lib rpcrt4.lib usp10.lib winmm.lib ws2_32.lib ../../common/KernelEx.lib ../../kexcrt/kexcrt.lib libc.lib delayimp.lib /nologo /dll /map /debug /machine:I386 /nodefaultlib /OPT:NOWIN98 /DELAYLOAD:shell32.dll /DELAYLOAD:rpcrt4.dll /DELAYLOAD:usp10.dll /DELAYLOAD:comdlg32.dll /DELAYLOAD:winspool.drv /DELAYLOAD:shlwapi.dll /DELAYLOAD:winmm.dll /DELAYLOAD:ws2_32.dll # SUBTRACT LINK32 /pdb:none !ENDIF @@ -221,6 +221,10 @@ SOURCE=.\shell32\folderfix.h # End Source File # Begin Source File +SOURCE=.\shell32\SHBindToParent.c +# End Source File +# Begin Source File + SOURCE=.\shell32\SHGetFolderLocation.c # End Source File # Begin Source File @@ -296,6 +300,38 @@ SOURCE=.\shfolder\_shfolder_apilist.h SOURCE=.\shfolder\shfolder.c # End Source File # End Group +# Begin Group "winmm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\winmm\_winmm_apilist.c +# End Source File +# Begin Source File + +SOURCE=.\winmm\_winmm_apilist.h +# End Source File +# Begin Source File + +SOURCE=.\winmm\uniwinmm.c +# End Source File +# End Group +# Begin Group "ws2_32" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ws2_32\_ws2_32_apilist.c +# End Source File +# Begin Source File + +SOURCE=.\ws2_32\_ws2_32_apilist.h +# End Source File +# Begin Source File + +SOURCE=.\ws2_32\addinfo.c +# End Source File +# End Group # Begin Source File SOURCE=.\common.c diff --git a/apilibs/kexbasen/main.c b/apilibs/kexbasen/main.c index 80ff953..acda2ec 100755 --- a/apilibs/kexbasen/main.c +++ b/apilibs/kexbasen/main.c @@ -31,9 +31,11 @@ #include "rpcrt4/_rpcrt4_apilist.h" #include "winspool/_winspool_apilist.h" #include "shfolder/_shfolder_apilist.h" +#include "winmm/_winmm_apilist.h" +#include "ws2_32/_ws2_32_apilist.h" //#include "/__apilist.h" -static apilib_api_table api_table[10]; +static apilib_api_table api_table[12]; static void fill_apitable() { @@ -46,6 +48,8 @@ static void fill_apitable() api_table[6] = apitable_rpcrt4; api_table[7] = apitable_winspool; api_table[8] = apitable_shfolder; + api_table[9] = apitable_winmm; + api_table[10] = apitable_ws2_32; //last entry is null terminator } @@ -59,7 +63,9 @@ const apilib_api_table* get_api_table() static BOOL init() { - return common_init() && init_kernel32() && init_gdi32() && init_user32() && init_advapi32() && init_comdlg32() && init_shell32() && init_rpcrt4() && init_winspool() && init_shfolder(); + return common_init() && init_kernel32() && init_gdi32() && init_user32() + && init_advapi32() && init_comdlg32() && init_shell32() && init_rpcrt4() + && init_winspool() && init_shfolder() && init_winmm() && init_ws2_32(); } static void uninit() diff --git a/apilibs/kexbasen/rpcrt4/_rpcrt4_apilist.h b/apilibs/kexbasen/rpcrt4/_rpcrt4_apilist.h index f195f21..d9c7d81 100755 --- a/apilibs/kexbasen/rpcrt4/_rpcrt4_apilist.h +++ b/apilibs/kexbasen/rpcrt4/_rpcrt4_apilist.h @@ -23,6 +23,7 @@ #define _RPCRT4_APILIST_H #include "kexcoresdk.h" +#include BOOL init_rpcrt4(); extern const apilib_api_table apitable_rpcrt4; diff --git a/apilibs/kexbasen/shell32/SHBindToParent.c b/apilibs/kexbasen/shell32/SHBindToParent.c new file mode 100755 index 0000000..6ae642e --- /dev/null +++ b/apilibs/kexbasen/shell32/SHBindToParent.c @@ -0,0 +1,55 @@ +/* + * KernelEx + * Copyright (C) 2010, Tihiy + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define CINTERFACE +#include + +/* MAKE_EXPORT SHBindToParent_new=SHBindToParent */ +HRESULT WINAPI SHBindToParent_new(LPCITEMIDLIST pidl, REFIID riid, VOID **ppv, LPCITEMIDLIST *ppidlLast) +{ + HRESULT hres; + LPITEMIDLIST pidlParent = ILClone(pidl); + if (pidlParent) + { + ILRemoveLastID(pidlParent); + IShellFolder *psf; + hres = SHGetDesktopFolder(&psf); + if (SUCCEEDED(hres)) + { + if (pidl->mkid.cb == 0) //empty i.e. desktop + hres = psf->lpVtbl->QueryInterface(psf,riid,ppv); + else + hres = psf->lpVtbl->BindToObject(psf,pidlParent,NULL,riid,ppv); + psf->lpVtbl->Release(psf); + } + ILFree(pidlParent); + + if (SUCCEEDED(hres) && (*ppv == NULL)) //no interface provided? + hres = E_FAIL; + } + else + hres = E_OUTOFMEMORY; + + if (ppidlLast) + *ppidlLast = ILFindLastID(pidl); + + return hres; +} diff --git a/apilibs/kexbasen/shell32/SHGetFolderLocation.c b/apilibs/kexbasen/shell32/SHGetFolderLocation.c index f67f497..4031e65 100755 --- a/apilibs/kexbasen/shell32/SHGetFolderLocation.c +++ b/apilibs/kexbasen/shell32/SHGetFolderLocation.c @@ -67,7 +67,7 @@ static SHGetFolderLocation_t dld() { HMODULE h = GetModuleHandle("SHELL32"); SHGetFolderLocation_t pfn = (SHGetFolderLocation_t) - GetProcAddress(h, "SHGetFolderLocation"); + kexGetProcAddress(h, "SHGetFolderLocation"); if (!pfn) pfn = SHGetFolderLocation_impl; return pfn; diff --git a/apilibs/kexbasen/shell32/SHParseDisplayName.c b/apilibs/kexbasen/shell32/SHParseDisplayName.c index 117d81a..350a732 100755 --- a/apilibs/kexbasen/shell32/SHParseDisplayName.c +++ b/apilibs/kexbasen/shell32/SHParseDisplayName.c @@ -19,6 +19,7 @@ * */ +#define CINTERFACE #include #include @@ -31,9 +32,9 @@ HRESULT WINAPI SHParseDisplayName_new(PCWSTR pszName, IBindCtx *pbc, LPITEMIDLIS { ULONG attrs = sfgaoIn; LPOLESTR pszNameCopyW = StrDupW(pszName); - ret = psf->ParseDisplayName(NULL,pbc,pszNameCopyW,NULL,ppidl,&attrs); + ret = psf->lpVtbl->ParseDisplayName(psf,NULL,pbc,pszNameCopyW,NULL,ppidl,&attrs); if (psfgaoOut) *psfgaoOut = attrs; - psf->Release(); + psf->lpVtbl->Release(psf); LocalFree(pszNameCopyW); } return ret; diff --git a/apilibs/kexbasen/shell32/_shell32_apilist.c b/apilibs/kexbasen/shell32/_shell32_apilist.c index 248fc0f..c162107 100755 --- a/apilibs/kexbasen/shell32/_shell32_apilist.c +++ b/apilibs/kexbasen/shell32/_shell32_apilist.c @@ -35,6 +35,7 @@ static const apilib_named_api shell32_named_apis[] = DECL_API("ExtractIconExW", ExtractIconExW_fwd), DECL_API("ExtractIconW", ExtractIconW_fwd), DECL_API("FindExecutableW", FindExecutableW_fwd), + DECL_API("SHBindToParent", SHBindToParent_new), DECL_API("SHBrowseForFolderW", SHBrowseForFolderW_fwd), DECL_API("SHFileOperationW", SHFileOperationW_fwd), DECL_API("SHGetFileInfoW", SHGetFileInfoW_fwd), diff --git a/apilibs/kexbasen/shell32/_shell32_apilist.h b/apilibs/kexbasen/shell32/_shell32_apilist.h index 4424b68..9689605 100755 --- a/apilibs/kexbasen/shell32/_shell32_apilist.h +++ b/apilibs/kexbasen/shell32/_shell32_apilist.h @@ -29,6 +29,7 @@ BOOL init_shell32(); extern const apilib_api_table apitable_shell32; /*** AUTOGENERATED APILIST DECLARATIONS BEGIN ***/ +HRESULT WINAPI SHBindToParent_new(LPCITEMIDLIST pidl, REFIID riid, VOID **ppv, LPCITEMIDLIST *ppidlLast); HRESULT WINAPI SHGetFolderLocation_new(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwReserved, LPVOID *ppidl); HRESULT WINAPI SHGetFolderPathA_new(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPSTR pszPath); HRESULT WINAPI SHGetFolderPathW_new(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath); diff --git a/apilibs/kexbasen/shlord.c b/apilibs/kexbasen/shlord.c index a395e8c..e0c4f74 100755 --- a/apilibs/kexbasen/shlord.c +++ b/apilibs/kexbasen/shlord.c @@ -41,7 +41,7 @@ PVOID WINAPI GetShlwapiProc(int funcnum) if (!hShlwapi) hShlwapi = LoadLibrary("shlwapi.dll"); } - PVOID proc = GetProcAddress(hShlwapi,(LPSTR)funcnum); + PVOID proc = kexGetProcAddress(hShlwapi,(LPSTR)funcnum); if (!proc) shlwapi_fatal_error(funcnum); return proc; diff --git a/apilibs/kexbasen/unifwd.c b/apilibs/kexbasen/unifwd.c index 8baf68b..f05732f 100755 --- a/apilibs/kexbasen/unifwd.c +++ b/apilibs/kexbasen/unifwd.c @@ -59,7 +59,7 @@ unsigned long __stdcall GetUnicowsAddress(const char* name) { if (!hUnicows) unifwd_init(); - PROC addr = GetProcAddress(hUnicows, name); + PROC addr = kexGetProcAddress(hUnicows, name); if (!addr) unicows_fatal_error(name); return (unsigned long) addr; diff --git a/apilibs/kexbasen/winmm/_winmm_apilist.c b/apilibs/kexbasen/winmm/_winmm_apilist.c new file mode 100755 index 0000000..2fe7a5e --- /dev/null +++ b/apilibs/kexbasen/winmm/_winmm_apilist.c @@ -0,0 +1,47 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "common.h" +#include "kexcoresdk.h" +#include "_winmm_apilist.h" + +BOOL init_winmm() +{ + return TRUE; +} + +static const apilib_named_api winmm_named_apis[] = +{ +/*** AUTOGENERATED APILIST NAMED EXPORTS BEGIN ***/ + DECL_API("waveInGetDevCapsW", waveInGetDevCapsW_new), + DECL_API("waveOutGetDevCapsW", waveOutGetDevCapsW_new), +/*** AUTOGENERATED APILIST NAMED EXPORTS END ***/ +}; + +#if 0 +static const apilib_unnamed_api winmm_ordinal_apis[] = +{ +/*** AUTOGENERATED APILIST ORDINAL EXPORTS BEGIN ***/ +/*** AUTOGENERATED APILIST ORDINAL EXPORTS END ***/ +}; +#endif + +const apilib_api_table apitable_winmm = DECL_TAB("WINMM.DLL", winmm_named_apis, 0 /*winmm_ordinal_apis*/); diff --git a/apilibs/kexbasen/winmm/_winmm_apilist.h b/apilibs/kexbasen/winmm/_winmm_apilist.h new file mode 100755 index 0000000..82d43a8 --- /dev/null +++ b/apilibs/kexbasen/winmm/_winmm_apilist.h @@ -0,0 +1,36 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _WINMM_APILIST_H +#define _WINMM_APILIST_H + +#include "kexcoresdk.h" +#include + +BOOL init_winmm(); +extern const apilib_api_table apitable_winmm; + +/*** AUTOGENERATED APILIST DECLARATIONS BEGIN ***/ +MMRESULT WINAPI waveInGetDevCapsW_new(UINT uDeviceID, LPWAVEINCAPSW pwicW, UINT cbwic); +MMRESULT WINAPI waveOutGetDevCapsW_new(UINT uDeviceID, LPWAVEOUTCAPSW pwocW, UINT cbwoc); +/*** AUTOGENERATED APILIST DECLARATIONS END ***/ + +#endif diff --git a/apilibs/kexbasen/winmm/uniwinmm.c b/apilibs/kexbasen/winmm/uniwinmm.c new file mode 100755 index 0000000..017317a --- /dev/null +++ b/apilibs/kexbasen/winmm/uniwinmm.c @@ -0,0 +1,88 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "common.h" +#include + +/* MAKE_EXPORT waveInGetDevCapsW_new=waveInGetDevCapsW */ +MMRESULT WINAPI waveInGetDevCapsW_new( + UINT uDeviceID, + LPWAVEINCAPSW pwicW, + UINT cbwic +) +{ + MMRESULT ret; + WAVEINCAPSA wicA; + WAVEINCAPSW wicW; + + if (pwicW == NULL) + return MMSYSERR_INVALPARAM; + + ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA)); + + if (ret == MMSYSERR_NOERROR) + { + wicW.wMid = wicA.wMid; + wicW.wPid = wicA.wPid; + wicW.vDriverVersion = wicA.vDriverVersion; + MultiByteToWideChar(CP_ACP, 0, wicA.szPname, -1, wicW.szPname, sizeof(wicW.szPname)); + wicW.dwFormats = wicA.dwFormats; + wicW.wChannels = wicA.wChannels; + wicW.wReserved1 = wicA.wReserved1; + + memcpy(pwicW, &wicW, min(sizeof(wicW), cbwic)); + } + + return ret; +} + +/* MAKE_EXPORT waveOutGetDevCapsW_new=waveOutGetDevCapsW */ +MMRESULT WINAPI waveOutGetDevCapsW_new( + UINT uDeviceID, + LPWAVEOUTCAPSW pwocW, + UINT cbwoc +) +{ + MMRESULT ret; + WAVEOUTCAPSA wocA; + WAVEOUTCAPSW wocW; + + if (pwocW == NULL) + return MMSYSERR_INVALPARAM; + + ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA)); + + if (ret == MMSYSERR_NOERROR) + { + wocW.wMid = wocA.wMid; + wocW.wPid = wocA.wPid; + wocW.vDriverVersion = wocA.vDriverVersion; + MultiByteToWideChar(CP_ACP, 0, wocA.szPname, -1, wocW.szPname, sizeof(wocW.szPname)); + wocW.dwFormats = wocA.dwFormats; + wocW.wChannels = wocA.wChannels; + wocW.wReserved1 = wocA.wReserved1; + wocW.dwSupport = wocA.dwSupport; + + memcpy(pwocW, &wocW, min(sizeof(wocW), cbwoc)); + } + + return ret; +} diff --git a/apilibs/kexbasen/winspool/DefaultPrinter.c b/apilibs/kexbasen/winspool/DefaultPrinter.c index 83baaf3..22fcd7a 100755 --- a/apilibs/kexbasen/winspool/DefaultPrinter.c +++ b/apilibs/kexbasen/winspool/DefaultPrinter.c @@ -20,9 +20,10 @@ */ #include "common.h" +#include -/* MAKE_EXPORT GetDefaultPrinterA=GetDefaultPrinterA */ -BOOL WINAPI GetDefaultPrinterA(LPSTR buf, LPDWORD size) +/* MAKE_EXPORT GetDefaultPrinterA_new=GetDefaultPrinterA */ +BOOL WINAPI GetDefaultPrinterA_new(LPSTR buf, LPDWORD size) { DWORD needed, returned; BOOL ret; @@ -53,8 +54,8 @@ BOOL WINAPI GetDefaultPrinterA(LPSTR buf, LPDWORD size) return TRUE; } -/* MAKE_EXPORT GetDefaultPrinterW=GetDefaultPrinterW */ -BOOL WINAPI GetDefaultPrinterW(LPWSTR bufW, LPDWORD sizeW) +/* MAKE_EXPORT GetDefaultPrinterW_new=GetDefaultPrinterW */ +BOOL WINAPI GetDefaultPrinterW_new(LPWSTR bufW, LPDWORD sizeW) { BOOL ret; DWORD sizeA = *sizeW; diff --git a/apilibs/kexbasen/winspool/_winspool_apilist.c b/apilibs/kexbasen/winspool/_winspool_apilist.c index 62854cb..3da2953 100755 --- a/apilibs/kexbasen/winspool/_winspool_apilist.c +++ b/apilibs/kexbasen/winspool/_winspool_apilist.c @@ -48,8 +48,8 @@ static const apilib_named_api winspool_named_apis[] = DECL_API("DeviceCapabilitiesW", DeviceCapabilitiesW_fwd), DECL_API("DocumentPropertiesW", DocumentPropertiesW_fwd), DECL_API("EnumPrintersW", EnumPrintersW_new), - DECL_API("GetDefaultPrinterA", GetDefaultPrinterA), - DECL_API("GetDefaultPrinterW", GetDefaultPrinterW), + DECL_API("GetDefaultPrinterA", GetDefaultPrinterA_new), + DECL_API("GetDefaultPrinterW", GetDefaultPrinterW_new), DECL_API("GetPrintProcessorDirectoryW", GetPrintProcessorDirectoryW_fwd), DECL_API("GetPrinterDataExA", GetPrinterDataExA_stub), DECL_API("GetPrinterDataExW", GetPrinterDataExW_stub), diff --git a/apilibs/kexbasen/winspool/_winspool_apilist.h b/apilibs/kexbasen/winspool/_winspool_apilist.h index e22569b..66bfd73 100755 --- a/apilibs/kexbasen/winspool/_winspool_apilist.h +++ b/apilibs/kexbasen/winspool/_winspool_apilist.h @@ -28,8 +28,8 @@ BOOL init_winspool(); extern const apilib_api_table apitable_winspool; /*** AUTOGENERATED APILIST DECLARATIONS BEGIN ***/ -BOOL WINAPI GetDefaultPrinterA(LPSTR buf, LPDWORD size); -BOOL WINAPI GetDefaultPrinterW(LPWSTR bufW, LPDWORD sizeW); +BOOL WINAPI GetDefaultPrinterA_new(LPSTR buf, LPDWORD size); +BOOL WINAPI GetDefaultPrinterW_new(LPWSTR bufW, LPDWORD sizeW); STUB GetPrinterDataExA_stub; STUB GetPrinterDataExW_stub; STUB SetPrinterDataExA_stub; diff --git a/apilibs/kexbasen/winspool/uniwinspool.c b/apilibs/kexbasen/winspool/uniwinspool.c index fa651d1..852fdcd 100755 --- a/apilibs/kexbasen/winspool/uniwinspool.c +++ b/apilibs/kexbasen/winspool/uniwinspool.c @@ -30,6 +30,7 @@ #include "common.h" #include "unifwd.h" +#include static const DWORD pi_sizeof[] = {0, sizeof(PRINTER_INFO_1), sizeof(PRINTER_INFO_2), sizeof(PRINTER_INFO_3), sizeof(PRINTER_INFO_4), diff --git a/apilibs/kexbasen/ws2_32/_ws2_32_apilist.c b/apilibs/kexbasen/ws2_32/_ws2_32_apilist.c new file mode 100755 index 0000000..f44478b --- /dev/null +++ b/apilibs/kexbasen/ws2_32/_ws2_32_apilist.c @@ -0,0 +1,47 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "common.h" +#include "_ws2_32_apilist.h" + +BOOL init_ws2_32() +{ + return TRUE; +} + +static const apilib_named_api ws2_32_named_apis[] = +{ +/*** AUTOGENERATED APILIST NAMED EXPORTS BEGIN ***/ + DECL_API("freeaddrinfo", freeaddrinfo_new), + DECL_API("getaddrinfo", getaddrinfo_new), + DECL_API("getnameinfo", getnameinfo_new), +/*** AUTOGENERATED APILIST NAMED EXPORTS END ***/ +}; + +#if 0 +static const apilib_unnamed_api ws2_32_ordinal_apis[] = +{ +/*** AUTOGENERATED APILIST ORDINAL EXPORTS BEGIN ***/ +/*** AUTOGENERATED APILIST ORDINAL EXPORTS END ***/ +}; +#endif + +const apilib_api_table apitable_ws2_32 = DECL_TAB("WS2_32.DLL", ws2_32_named_apis, 0 /*ws2_32_ordinal_apis*/); diff --git a/apilibs/kexbasen/ws2_32/_ws2_32_apilist.h b/apilibs/kexbasen/ws2_32/_ws2_32_apilist.h new file mode 100755 index 0000000..8365753 --- /dev/null +++ b/apilibs/kexbasen/ws2_32/_ws2_32_apilist.h @@ -0,0 +1,39 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _WS2_32_APILIST_H +#define _WS2_32_APILIST_H + +#include "kexcoresdk.h" +#include +#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) +#include + +BOOL init_ws2_32(); +extern const apilib_api_table apitable_ws2_32; + +/*** AUTOGENERATED APILIST DECLARATIONS BEGIN ***/ +int WINAPI getaddrinfo_new(const char* hostname, const char* servname, const struct addrinfo* hints, struct addrinfo** res); +void WINAPI freeaddrinfo_new(struct addrinfo* ai); +int WINAPI getnameinfo_new(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags); +/*** AUTOGENERATED APILIST DECLARATIONS END ***/ + +#endif diff --git a/apilibs/kexbasen/ws2_32/addinfo.c b/apilibs/kexbasen/ws2_32/addinfo.c new file mode 100755 index 0000000..2f892be --- /dev/null +++ b/apilibs/kexbasen/ws2_32/addinfo.c @@ -0,0 +1,60 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) +#include +#include + +/* MAKE_EXPORT getaddrinfo_new=getaddrinfo */ +int WINAPI getaddrinfo_new( + const char* hostname, + const char* servname, + const struct addrinfo* hints, + struct addrinfo** res +) +{ + return WspiapiLegacyGetAddrInfo(hostname, servname, hints, res); +} + +/* MAKE_EXPORT freeaddrinfo_new=freeaddrinfo */ +void WINAPI freeaddrinfo_new( + struct addrinfo* ai +) +{ + WspiapiLegacyFreeAddrInfo(ai); +} + +/* MAKE_EXPORT getnameinfo_new=getnameinfo */ +int WINAPI getnameinfo_new( + const struct sockaddr* sa, + socklen_t salen, + char* host, + size_t hostlen, + char* serv, + size_t servlen, + int flags +) +{ + return WspiapiLegacyGetNameInfo(sa, salen, host, hostlen, serv, servlen, flags); +} diff --git a/apilibs/kexbases/Gdi32/GdiObjects.c b/apilibs/kexbases/Gdi32/GdiObjects.c index 0f28aec..e0ec1c7 100755 --- a/apilibs/kexbases/Gdi32/GdiObjects.c +++ b/apilibs/kexbases/Gdi32/GdiObjects.c @@ -25,7 +25,6 @@ #include "k32ord.h" #include "kexcoresdk.h" -static BOOL blockkexgdiobj; static WORD g_GDILH_addr; static DWORD g_GdiBase; static int script_cache_psidx; @@ -40,7 +39,6 @@ BOOL InitGDIObjects(void) { g_GdiBase = MapSL( LoadLibrary16("gdi") << 16 ); g_GDILH_addr = ((PINSTANCE16)g_GdiBase)->pLocalHeap; - blockkexgdiobj = (BOOL)GetProcAddress(GetModuleHandle("rp10.dll"),"blockkexgdiobj"); script_cache_psidx = kexPsAllocIndex(); return (BOOL)g_GdiBase; } @@ -126,7 +124,6 @@ static DWORD SwitchGDIObjectType( PGDIOBJ16 obj ) /* MAKE_EXPORT GetObjectType_fix=GetObjectType */ DWORD WINAPI GetObjectType_fix( HGDIOBJ hgdiobj ) { - if (blockkexgdiobj) return GetObjectType(hgdiobj); //GetObjectType is rewritten in order to boost it's correctness and speed: //constantly throwing page/segfaults is very bad on virtual machines. PGDIOBJ16 obj = GetGDIObjectPtr( hgdiobj ); @@ -166,7 +163,6 @@ WORD GetCurrentTDB() /* MAKE_EXPORT DeleteObject_fix=DeleteObject */ BOOL WINAPI DeleteObject_fix( HGDIOBJ hObject ) { - if (blockkexgdiobj) return DeleteObject(hObject); PGDIOBJ16 obj = GetGDIObjectPtr( hObject ); if ( !obj || !SwitchGDIObjectType(obj) ) return FALSE; DWORD violated = 0; @@ -178,7 +174,7 @@ BOOL WINAPI DeleteObject_fix( HGDIOBJ hObject ) DeleteUSPFontCache_fn DeleteUSPFontCache = (DeleteUSPFontCache_fn) kexPsGetValue(script_cache_psidx); if (!DeleteUSPFontCache) { - DeleteUSPFontCache = (DeleteUSPFontCache_fn)GetProcAddress(LoadLibrary("KEXBASEN.DLL"), "DeleteUSPFontCache"); + DeleteUSPFontCache = (DeleteUSPFontCache_fn)kexGetProcAddress(LoadLibrary("KEXBASEN.DLL"), "DeleteUSPFontCache"); kexPsSetValue(script_cache_psidx, DeleteUSPFontCache); } if (DeleteUSPFontCache) @@ -206,7 +202,6 @@ BOOL WINAPI DeleteObject_fix( HGDIOBJ hObject ) /* MAKE_EXPORT SelectObject_fix=SelectObject */ HGDIOBJ WINAPI SelectObject_fix( HDC hdc, HGDIOBJ hgdiobj ) { - if (blockkexgdiobj) return SelectObject(hdc,hgdiobj); //9x should do this if ( !hdc ) SetLastError(ERROR_INVALID_HANDLE); if ( !hdc || !hgdiobj ) return NULL; @@ -233,7 +228,6 @@ HGDIOBJ WINAPI SelectObject_fix( HDC hdc, HGDIOBJ hgdiobj ) /* MAKE_EXPORT DeleteDC_fix=DeleteDC */ BOOL WINAPI DeleteDC_fix( HDC hdc ) { - if (blockkexgdiobj) return DeleteDC(hdc); BOOL ret; PGDIOBJ16 obj = GetGDIObjectPtr( hdc ); if ( !obj || !SwitchGDIObjectType(obj) ) return FALSE; diff --git a/apilibs/kexbases/Kernel32/CompletionPorts.c b/apilibs/kexbases/Kernel32/CompletionPorts.c index e5162fa..986f424 100755 --- a/apilibs/kexbases/Kernel32/CompletionPorts.c +++ b/apilibs/kexbases/Kernel32/CompletionPorts.c @@ -128,7 +128,7 @@ BOOL WINAPI PostQueuedCompletionStatus_new( { PCOMPLET_PORT port = (PCOMPLET_PORT)MapViewOfFile(CompletionPort,FILE_MAP_ALL_ACCESS,0,0,0); //kexDebugPrint("PostQueuedCompletionStatus queued from port %p: %p %p %p",port,dwNumberOfBytesTransferred,dwCompletionKey,lpOverlapped); - if (!port || port->signature != PORT_SIGNATURE || !lpOverlapped) + if (!port || port->signature != PORT_SIGNATURE) { UnmapViewOfFile(port); SetLastError(ERROR_INVALID_PARAMETER); diff --git a/apilibs/kexbases/Kernel32/CreateFiberEx.c b/apilibs/kexbases/Kernel32/CreateFiberEx.c new file mode 100755 index 0000000..62bc23e --- /dev/null +++ b/apilibs/kexbases/Kernel32/CreateFiberEx.c @@ -0,0 +1,34 @@ +/* + * KernelEx + * Copyright (C) 2010, Tihiy + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +/* MAKE_EXPORT CreateFiberEx_new=CreateFiberEx */ +LPVOID WINAPI CreateFiberEx_new( + SIZE_T dwStackCommitSize, + SIZE_T dwStackReserveSize, + DWORD dwFlags, + LPFIBER_START_ROUTINE lpStartAddress, + LPVOID lpParameter +) +{ + return CreateFiber( dwStackCommitSize ? dwStackCommitSize : dwStackReserveSize, lpStartAddress, lpParameter ); +} diff --git a/apilibs/kexbases/Kernel32/GetProcessId.c b/apilibs/kexbases/Kernel32/GetProcessId.c new file mode 100755 index 0000000..c37d6aa --- /dev/null +++ b/apilibs/kexbases/Kernel32/GetProcessId.c @@ -0,0 +1,46 @@ +/* + * KernelEx + * Copyright (C) 2010, Tihiy + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include "common.h" + +/* MAKE_EXPORT GetProcessId_new=GetProcessId */ +DWORD WINAPI GetProcessId_new( + HANDLE hProcess +) +{ + typedef DWORD (WINAPI *MPH) (HANDLE hProcess); + static MPH MapProcessHandle = 0; + + if (!MapProcessHandle) + { + DWORD *faddr; + DWORD addr; + + faddr = (DWORD *) ( (DWORD)SetFilePointer + 0x1D ); //there is jmp _SetFilePointer + addr = (DWORD) faddr + *faddr + 4 - 0x16; //0x16 bytes before _SetFilePointer there is MapProcessHandle, just what we need + faddr = (DWORD *) addr; + if (*faddr != 0x206A006A) + fatal_error("GetProcessId: ASSERTION FAILED"); //push 0; push 0x20 + MapProcessHandle = (MPH) addr; + } + return MapProcessHandle(hProcess); +} diff --git a/apilibs/kexbases/Kernel32/_kernel32_apilist.c b/apilibs/kexbases/Kernel32/_kernel32_apilist.c index 09a9d64..f4974fb 100755 --- a/apilibs/kexbases/Kernel32/_kernel32_apilist.c +++ b/apilibs/kexbases/Kernel32/_kernel32_apilist.c @@ -55,6 +55,7 @@ static const apilib_named_api kernel32_named_apis[] = DECL_API("CopyFileW", CopyFileW_new), DECL_API("CreateDirectoryExW", CreateDirectoryExW_new), DECL_API("CreateDirectoryW", CreateDirectoryW_new), + DECL_API("CreateFiberEx", CreateFiberEx_new), DECL_API("CreateFileA", CreateFileA_fix), DECL_API("CreateFileW", CreateFileW_new), DECL_API("CreateHardLinkA", CreateHardLinkA_stub), @@ -63,9 +64,13 @@ static const apilib_named_api kernel32_named_apis[] = DECL_API("CreateJobObjectA", CreateJobObjectA_new), DECL_API("CreateJobObjectW", CreateJobObjectW_new), DECL_API("CreateThread", CreateThread_fix), + DECL_API("DecodePointer", XorPointer), + DECL_API("DecodeSystemPointer", XorPointer), DECL_API("DefineDosDeviceW", DefineDosDeviceW_new), DECL_API("DeleteCriticalSection", DeleteCriticalSection_new), DECL_API("DeleteFileW", DeleteFileW_new), + DECL_API("EncodePointer", XorPointer), + DECL_API("EncodeSystemPointer", XorPointer), DECL_API("EnumUILanguagesA", EnumUILanguagesA_new), DECL_API("EnumUILanguagesW", EnumUILanguagesW_new), DECL_API("FindAtomW", FindAtomW_new), @@ -99,6 +104,7 @@ static const apilib_named_api kernel32_named_apis[] = DECL_API("GetModuleHandleExW", GetModuleHandleExW_new), DECL_API("GetModuleHandleW", GetModuleHandleW_new), DECL_API("GetNativeSystemInfo", GetSystemInfo), + DECL_API("GetProcessId", GetProcessId_new), DECL_API("GetProcessIoCounters", GetProcessIoCounters_stub), DECL_API("GetQueuedCompletionStatus", GetQueuedCompletionStatus_new), DECL_API("GetShortPathNameW", GetShortPathNameW_new), @@ -182,6 +188,7 @@ static const apilib_named_api kernel32_named_apis[] = DECL_API("Process32NextW", Process32NextW_new), DECL_API("ProcessIdToSessionId", ProcessIdToSessionId_new), DECL_API("QueryInformationJobObject", QueryInformationJobObject_new), + DECL_API("ReadConsoleInputW", ReadConsoleInputW_new), DECL_API("ReadFile", ReadFile_fix), DECL_API("RemoveDirectoryW", RemoveDirectoryW_new), DECL_API("ReplaceFileA", ReplaceFileA_stub), @@ -195,8 +202,10 @@ static const apilib_named_api kernel32_named_apis[] = DECL_API("SetFileAttributesW", SetFileAttributesW_new), DECL_API("SetFilePointerEx", SetFilePointerEx_new), DECL_API("SetInformationJobObject", SetInformationJobObject_new), + DECL_API("SystemTimeToTzSpecificLocalTime", SystemTimeToTzSpecificLocalTime_new), DECL_API("TerminateJobObject", TerminateJobObject_new), DECL_API("TryEnterCriticalSection", TryEnterCriticalSection_new), + DECL_API("TzSpecificLocalTimeToSystemTime", TzSpecificLocalTimeToSystemTime_new), DECL_API("VerLanguageNameW", VerLanguageNameW_new), DECL_API("VerSetConditionMask", VerSetConditionMask_new), DECL_API("VerifyVersionInfoA", VerifyVersionInfoA_NT2K), diff --git a/apilibs/kexbases/Kernel32/_kernel32_apilist.h b/apilibs/kexbases/Kernel32/_kernel32_apilist.h index 18cf50a..a8facb3 100755 --- a/apilibs/kexbases/Kernel32/_kernel32_apilist.h +++ b/apilibs/kexbases/Kernel32/_kernel32_apilist.h @@ -33,6 +33,7 @@ HANDLE WINAPI CreateIoCompletionPort_new(HANDLE FileHandle, HANDLE ExistingCompl BOOL WINAPI GetQueuedCompletionStatus_new(HANDLE CompletionPort, LPDWORD lpNumberOfBytes, PULONG_PTR lpCompletionKey, LPOVERLAPPED *lpOverlapped, DWORD dwMilliseconds); BOOL WINAPI PostQueuedCompletionStatus_new(HANDLE CompletionPort, DWORD dwNumberOfBytesTransferred, ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped); BOOL WINAPI CopyFileExA_new(LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags); +LPVOID WINAPI CreateFiberEx_new(SIZE_T dwStackCommitSize, SIZE_T dwStackReserveSize, DWORD dwFlags, LPFIBER_START_ROUTINE lpStartAddress, LPVOID lpParameter); HANDLE WINAPI CreateThread_fix(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); void WINAPI DeleteCriticalSection_new(PCRITICAL_SECTION lpCriticalSection); HANDLE WINAPI CreateFileA_fix(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); @@ -45,6 +46,7 @@ HWND WINAPI GetConsoleWindow_new(); BOOL WINAPI GetFileSizeEx_new(HANDLE hFile, PLARGE_INTEGER lpFileSize); BOOL WINAPI GetModuleHandleExA_new(DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule); BOOL WINAPI GetModuleHandleExW_new(DWORD dwFlags, LPCWSTR lpModuleNameW, HMODULE* phModule); +DWORD WINAPI GetProcessId_new(HANDLE hProcess); BOOL WINAPI GlobalMemoryStatusEx_new(LPMEMORYSTATUSEX lpmemex); BOOL WINAPI HeapLock_new(HANDLE hHeap); BOOL WINAPI HeapUnlock_new(HANDLE hHeap); @@ -94,6 +96,9 @@ INT WINAPI FoldStringW_new(DWORD dwFlags, LPCWSTR src, INT srclen, LPWSTR dst, I INT WINAPI FoldStringA_new(DWORD dwFlags, LPCSTR src, INT srclen, LPSTR dst, INT dstlen); int WINAPI lstrcmpW_new(LPCWSTR str1, LPCWSTR str2); int WINAPI lstrcmpiW_new(LPCWSTR str1, LPCWSTR str2); +PVOID WINAPI XorPointer(PVOID ptr); +BOOL WINAPI SystemTimeToTzSpecificLocalTime_new(const TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpUniversalTime, LPSYSTEMTIME lpLocalTime); +BOOL WINAPI TzSpecificLocalTimeToSystemTime_new(const TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpLocalTime, LPSYSTEMTIME lpUniversalTime); LANGID WINAPI GetUserDefaultUILanguage_new(void); LANGID WINAPI GetSystemDefaultUILanguage_new(void); BOOL WINAPI EnumUILanguagesA_new(UILANGUAGE_ENUMPROCA pUILangEnumProc, DWORD dwFlags, LONG_PTR lParam); @@ -151,6 +156,7 @@ BOOL WINAPI SetCurrentDirectoryW_new(LPCWSTR lpPathNameW); BOOL WINAPI SetFileAttributesW_new(LPCWSTR lpFileNameW, DWORD dwFileAttributes); DWORD WINAPI VerLanguageNameW_new(DWORD wLang, LPWSTR szLangW, DWORD nSize); LPWSTR WINAPI lstrcpynW_new(LPWSTR dst, LPCWSTR src, INT n); +BOOL WINAPI ReadConsoleInputW_new(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead); ULONGLONG WINAPI VerSetConditionMask_new(ULONGLONG dwlConditionMask, DWORD dwTypeBitMask, BYTE dwConditionMask); DWORD WINAPI GetVersion_WIN95(void); DWORD WINAPI GetVersion_WIN98(void); diff --git a/apilibs/kexbases/Kernel32/locale.c b/apilibs/kexbases/Kernel32/locale.c index ed8b288..6c9209d 100755 --- a/apilibs/kexbases/Kernel32/locale.c +++ b/apilibs/kexbases/Kernel32/locale.c @@ -21,7 +21,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include "common.h" #include "locale_unicode.h" #ifdef _MSC_VER @@ -140,7 +140,7 @@ BOOL WINAPI GetStringTypeW_new( DWORD type, LPCWSTR src, INT count, LPWORD chart return FALSE; } GetStringType3ExW = (BOOL (WINAPI*)(LPCWSTR, INT, LPWORD)) - GetProcAddress(hShlwapi, (LPSTR) 35); + kexGetProcAddress(hShlwapi, (LPSTR) 35); return GetStringType3ExW(src, count, chartype); #endif } diff --git a/apilibs/kexbases/Kernel32/pointer.c b/apilibs/kexbases/Kernel32/pointer.c new file mode 100755 index 0000000..a9a403f --- /dev/null +++ b/apilibs/kexbases/Kernel32/pointer.c @@ -0,0 +1,51 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86, Tihiy + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "common.h" + +BOOL WINAPI SystemFunction036_new(PVOID pbBuffer, ULONG dwLen); + +static LONG get_pointer_obfuscator(void) +{ + static LONG obfuscator; + + if (obfuscator == 0) + { + LONG rand; + SystemFunction036_new(&rand, sizeof(rand)); + rand |= 0xc0000000; + InterlockedCompareExchange(&obfuscator, rand, 0); + } + + return obfuscator; +} + +/* FIXME: EncodePointer/DecodePointer should use per-process obfuscator */ + +/* MAKE_EXPORT XorPointer=EncodePointer */ +/* MAKE_EXPORT XorPointer=DecodePointer */ +/* MAKE_EXPORT XorPointer=EncodeSystemPointer */ +/* MAKE_EXPORT XorPointer=DecodeSystemPointer */ +PVOID WINAPI XorPointer(PVOID ptr) +{ + LONG ptrval = (LONG) ptr; + return (PVOID)(ptrval ^ get_pointer_obfuscator()); +} diff --git a/apilibs/kexbases/Kernel32/time.c b/apilibs/kexbases/Kernel32/time.c new file mode 100755 index 0000000..c1ac9fb --- /dev/null +++ b/apilibs/kexbases/Kernel32/time.c @@ -0,0 +1,314 @@ +/* + * KernelEx + * + * Copyright (C) 2010, Xeno86 + * Copyright (C) 1995, Martin von Loewis, Cameron Heide (Wine project) + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include "common.h" + +#define LL2FILETIME( ll, pft )\ + (pft)->dwLowDateTime = (UINT)(ll); \ + (pft)->dwHighDateTime = (UINT)((ll) >> 32); +#define FILETIME2LL( pft, ll) \ + ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ; + + +static const int MonthLengths[2][12] = +{ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static inline int IsLeapYear(int Year) +{ + return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0; +} + + +/*********************************************************************** + * TIME_DayLightCompareDate + * + * Compares two dates without looking at the year. + * + * PARAMS + * date [in] The local time to compare. + * compareDate [in] The daylight savings begin or end date. + * + * RETURNS + * + * -1 if date < compareDate + * 0 if date == compareDate + * 1 if date > compareDate + * -2 if an error occurs + */ +static int TIME_DayLightCompareDate( const SYSTEMTIME *date, + const SYSTEMTIME *compareDate ) +{ + int limit_day, dayinsecs; + + if (date->wMonth < compareDate->wMonth) + return -1; /* We are in a month before the date limit. */ + + if (date->wMonth > compareDate->wMonth) + return 1; /* We are in a month after the date limit. */ + + /* if year is 0 then date is in day-of-week format, otherwise + * it's absolute date. + */ + if (compareDate->wYear == 0) + { + WORD First; + /* compareDate->wDay is interpreted as number of the week in the month + * 5 means: the last week in the month */ + int weekofmonth = compareDate->wDay; + /* calculate the day of the first DayOfWeek in the month */ + First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay + ) % 7 + 1; + limit_day = First + 7 * (weekofmonth - 1); + /* check needed for the 5th weekday of the month */ + if(limit_day > MonthLengths[date->wMonth==2 && IsLeapYear(date->wYear)] + [date->wMonth - 1]) + limit_day -= 7; + } + else + { + limit_day = compareDate->wDay; + } + + /* convert to seconds */ + limit_day = ((limit_day * 24 + compareDate->wHour) * 60 + + compareDate->wMinute ) * 60; + dayinsecs = ((date->wDay * 24 + date->wHour) * 60 + + date->wMinute ) * 60 + date->wSecond; + /* and compare */ + return dayinsecs < limit_day ? -1 : + dayinsecs > limit_day ? 1 : + 0; /* date is equal to the date limit. */ +} + +/*********************************************************************** + * TIME_CompTimeZoneID + * + * Computes the local time bias for a given time and time zone. + * + * PARAMS + * pTZinfo [in] The time zone data. + * lpFileTime [in] The system or local time. + * islocal [in] it is local time. + * + * RETURNS + * TIME_ZONE_ID_INVALID An error occurred + * TIME_ZONE_ID_UNKNOWN There are no transition time known + * TIME_ZONE_ID_STANDARD Current time is standard time + * TIME_ZONE_ID_DAYLIGHT Current time is daylight savings time + */ +static DWORD TIME_CompTimeZoneID ( const TIME_ZONE_INFORMATION *pTZinfo, + FILETIME *lpFileTime, BOOL islocal ) +{ + int ret; + BOOL beforeStandardDate, afterDaylightDate; + DWORD retval = TIME_ZONE_ID_INVALID; + LONGLONG llTime = 0; /* initialized to prevent gcc complaining */ + SYSTEMTIME SysTime; + FILETIME ftTemp; + + if (pTZinfo->DaylightDate.wMonth != 0) + { + /* if year is 0 then date is in day-of-week format, otherwise + * it's absolute date. + */ + if (pTZinfo->StandardDate.wMonth == 0 || + (pTZinfo->StandardDate.wYear == 0 && + (pTZinfo->StandardDate.wDay<1 || + pTZinfo->StandardDate.wDay>5 || + pTZinfo->DaylightDate.wDay<1 || + pTZinfo->DaylightDate.wDay>5))) + { + SetLastError(ERROR_INVALID_PARAMETER); + return TIME_ZONE_ID_INVALID; + } + + if (!islocal) { + FILETIME2LL( lpFileTime, llTime ); + llTime -= ( pTZinfo->Bias + pTZinfo->DaylightBias ) + * (LONGLONG)600000000; + LL2FILETIME( llTime, &ftTemp) + lpFileTime = &ftTemp; + } + + FileTimeToSystemTime(lpFileTime, &SysTime); + + /* check for daylight savings */ + ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate); + if (ret == -2) + return TIME_ZONE_ID_INVALID; + + beforeStandardDate = ret < 0; + + if (!islocal) { + llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias ) + * (LONGLONG)600000000; + LL2FILETIME( llTime, &ftTemp) + FileTimeToSystemTime(lpFileTime, &SysTime); + } + + ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate); + if (ret == -2) + return TIME_ZONE_ID_INVALID; + + afterDaylightDate = ret >= 0; + + retval = TIME_ZONE_ID_STANDARD; + if( pTZinfo->DaylightDate.wMonth < pTZinfo->StandardDate.wMonth ) { + /* Northern hemisphere */ + if( beforeStandardDate && afterDaylightDate ) + retval = TIME_ZONE_ID_DAYLIGHT; + } else /* Down south */ + if( beforeStandardDate || afterDaylightDate ) + retval = TIME_ZONE_ID_DAYLIGHT; + } else + /* No transition date */ + retval = TIME_ZONE_ID_UNKNOWN; + + return retval; +} + +/*********************************************************************** + * TIME_GetTimezoneBias + * + * Calculates the local time bias for a given time zone. + * + * PARAMS + * pTZinfo [in] The time zone data. + * lpFileTime [in] The system or local time. + * islocal [in] It is local time. + * pBias [out] The calculated bias in minutes. + * + * RETURNS + * TRUE when the time zone bias was calculated. + */ +static BOOL TIME_GetTimezoneBias( const TIME_ZONE_INFORMATION *pTZinfo, + FILETIME *lpFileTime, BOOL islocal, LONG *pBias ) +{ + LONG bias = pTZinfo->Bias; + DWORD tzid = TIME_CompTimeZoneID( pTZinfo, lpFileTime, islocal); + + if( tzid == TIME_ZONE_ID_INVALID) + return FALSE; + if (tzid == TIME_ZONE_ID_DAYLIGHT) + bias += pTZinfo->DaylightBias; + else if (tzid == TIME_ZONE_ID_STANDARD) + bias += pTZinfo->StandardBias; + *pBias = bias; + return TRUE; +} + +/*********************************************************************** + * SystemTimeToTzSpecificLocalTime (KERNEL32.@) + * + * Convert a utc system time to a local time in a given time zone. + * + * PARAMS + * lpTimeZoneInformation [in] The desired time zone. + * lpUniversalTime [in] The utc time to base local time on. + * lpLocalTime [out] The local time in the time zone. + * + * RETURNS + * Success: TRUE. lpLocalTime contains the converted time + * Failure: FALSE. + */ + +/* MAKE_EXPORT SystemTimeToTzSpecificLocalTime_new=SystemTimeToTzSpecificLocalTime */ +BOOL WINAPI SystemTimeToTzSpecificLocalTime_new( + const TIME_ZONE_INFORMATION *lpTimeZoneInformation, + const SYSTEMTIME *lpUniversalTime, LPSYSTEMTIME lpLocalTime ) +{ + FILETIME ft; + LONG lBias; + LONGLONG llTime; + TIME_ZONE_INFORMATION tzinfo; + + if (lpTimeZoneInformation != NULL) + { + tzinfo = *lpTimeZoneInformation; + } + else + { + if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID) + return FALSE; + } + + if (!SystemTimeToFileTime(lpUniversalTime, &ft)) + return FALSE; + FILETIME2LL( &ft, llTime) + if (!TIME_GetTimezoneBias(&tzinfo, &ft, FALSE, &lBias)) + return FALSE; + /* convert minutes to 100-nanoseconds-ticks */ + llTime -= (LONGLONG)lBias * 600000000; + LL2FILETIME( llTime, &ft) + + return FileTimeToSystemTime(&ft, lpLocalTime); +} + + +/*********************************************************************** + * TzSpecificLocalTimeToSystemTime (KERNEL32.@) + * + * Converts a local time to a time in utc. + * + * PARAMS + * lpTimeZoneInformation [in] The desired time zone. + * lpLocalTime [in] The local time. + * lpUniversalTime [out] The calculated utc time. + * + * RETURNS + * Success: TRUE. lpUniversalTime contains the converted time. + * Failure: FALSE. + */ + +/* MAKE_EXPORT TzSpecificLocalTimeToSystemTime_new=TzSpecificLocalTimeToSystemTime */ +BOOL WINAPI TzSpecificLocalTimeToSystemTime_new( + const TIME_ZONE_INFORMATION *lpTimeZoneInformation, + const SYSTEMTIME *lpLocalTime, LPSYSTEMTIME lpUniversalTime) +{ + FILETIME ft; + LONG lBias; + LONGLONG t; + TIME_ZONE_INFORMATION tzinfo; + + if (lpTimeZoneInformation != NULL) + { + tzinfo = *lpTimeZoneInformation; + } + else + { + if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID) + return FALSE; + } + + if (!SystemTimeToFileTime(lpLocalTime, &ft)) + return FALSE; + FILETIME2LL( &ft, t) + if (!TIME_GetTimezoneBias(&tzinfo, &ft, TRUE, &lBias)) + return FALSE; + /* convert minutes to 100-nanoseconds-ticks */ + t += (LONGLONG)lBias * 600000000; + LL2FILETIME( t, &ft) + return FileTimeToSystemTime(&ft, lpUniversalTime); +} diff --git a/apilibs/kexbases/Kernel32/unikernel32.c b/apilibs/kexbases/Kernel32/unikernel32.c index 5c29b31..83ad730 100755 --- a/apilibs/kexbases/Kernel32/unikernel32.c +++ b/apilibs/kexbases/Kernel32/unikernel32.c @@ -858,3 +858,27 @@ LPWSTR WINAPI lstrcpynW_new(LPWSTR dst, LPCWSTR src, INT n) } return ret; } + +//MAKE_EXPORT ReadConsoleInputW_new=ReadConsoleInputW +BOOL WINAPI ReadConsoleInputW_new( HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, + DWORD nLength, LPDWORD lpNumberOfEventsRead) +{ + BOOL ret = ReadConsoleInputA(hConsoleInput,lpBuffer,nLength,lpNumberOfEventsRead); + if ( ret && lpBuffer && lpNumberOfEventsRead ) + { + DWORD i; + for (i=0;i<*lpNumberOfEventsRead;i++) + { + if (lpBuffer->EventType == KEY_EVENT) + { + WCHAR uniChar; + if ( MultiByteToWideChar(CP_OEMCP,0,&lpBuffer->Event.KeyEvent.uChar.AsciiChar,1,&uniChar,1) ) + lpBuffer->Event.KeyEvent.uChar.UnicodeChar = uniChar; + else //fallback + lpBuffer->Event.KeyEvent.uChar.UnicodeChar = lpBuffer->Event.KeyEvent.uChar.AsciiChar; + } + lpBuffer++; + } + } + return ret; +} diff --git a/apilibs/kexbases/User32/SetParent_fix.c b/apilibs/kexbases/User32/SetParent_fix.c new file mode 100755 index 0000000..aacd9d1 --- /dev/null +++ b/apilibs/kexbases/User32/SetParent_fix.c @@ -0,0 +1,106 @@ +/* + * KernelEx + * Copyright (C) 2010, Tihiy, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include "k32ord.h" +#include "hwnd9x.h" + +static DWORD g_UserBase; +static HTOP_API HWNDtoPWND; + +//those are in thunilay +void GrabWin16Lock(); +void ReleaseWin16Lock(); + +#define REBASEUSER(x) ((x) != 0 ? g_UserBase + (DWORD)(x) : 0) + +BOOL SetParent_fix_init() +{ + g_UserBase = MapSL(LoadLibrary16("user") << 16); + /* IsWindow returns PWND */ + HWNDtoPWND = (HTOP_API)IsWindow; + return (g_UserBase != 0 && HWNDtoPWND != 0); +} + +/* returns TRUE if hwnd is a parent of hwndNewParent */ +static BOOL WINAPI TestChild(HWND hwnd, HWND hwndNewParent) +{ + BOOL ret = FALSE; + PWND pwnd, pwndT; + GrabWin16Lock(); + pwnd = HWNDtoPWND(hwnd); + pwndT = HWNDtoPWND(hwndNewParent); + if ( pwnd && pwndT ) + { + for ( ; pwndT != NULL; pwndT = (PWND)REBASEUSER(pwndT->spwndParent)) + { + if (pwnd == pwndT) + { + ret = TRUE; + break; + } + } + } + ReleaseWin16Lock(); + return ret; +} + +/* MAKE_EXPORT SetParent_fix=SetParent */ +__declspec(naked) +HWND WINAPI SetParent_fix(HWND hWndChild, HWND hWndNewParent) +{ +__asm { + + /* forbid changing parent of system windows */ + mov ecx, [esp+4] /* hWndChild */ + cmp ecx, 0x88 + ja __hwndok + cmp ecx, 0x80 + jb __hwndok + + /* hwnd is system one - disallow */ + push ERROR_ACCESS_DENIED + jmp __error + +__hwndok: + /* test hwnds to avoid circular references */ + mov eax, [esp+8] /* hWndNewParent */ + push eax + push ecx + call TestChild + test eax, eax + jnz __childfail + + /* return control to SetParent */ + jmp dword ptr [SetParent] + +__childfail: + /* circular reference detected - stop! */ + push ERROR_INVALID_PARAMETER + +__error: + /* return error */ + call dword ptr [SetLastError] + xor eax, eax + retn 8 + + } +} diff --git a/apilibs/kexbases/User32/SystemParametersInfo_fix.c b/apilibs/kexbases/User32/SystemParametersInfo_fix.c new file mode 100755 index 0000000..b91be64 --- /dev/null +++ b/apilibs/kexbases/User32/SystemParametersInfo_fix.c @@ -0,0 +1,48 @@ +/* + * KernelEx + * Copyright (C) 2010, Tihiy, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "common.h" + +/* MAKE_EXPORT SystemParametersInfoA_fix=SystemParametersInfoA */ +BOOL WINAPI SystemParametersInfoA_fix( + UINT uiAction, + UINT uiParam, + PVOID pvParam, + UINT fWinIni +) +{ + BOOL ret; + + if (uiAction == SPI_GETHIGHCONTRAST && uiParam == 0) + { + uiParam = sizeof(HIGHCONTRAST); + } + ret = SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni); + if (!ret && uiAction == SPI_GETHIGHCONTRAST && pvParam) + { + LPHIGHCONTRAST hc = (LPHIGHCONTRAST) pvParam; + hc->dwFlags = 0; + hc->lpszDefaultScheme = NULL; + ret = TRUE; + } + + return ret; +} diff --git a/apilibs/kexbases/User32/_user32_apilist.c b/apilibs/kexbases/User32/_user32_apilist.c index 6590c5a..43ba948 100755 --- a/apilibs/kexbases/User32/_user32_apilist.c +++ b/apilibs/kexbases/User32/_user32_apilist.c @@ -27,15 +27,18 @@ IsHungThread_t IsHungThread_pfn; DrawCaptionTempA_t DrawCaptionTempA_pfn; +BOOL SetParent_fix_init(); + BOOL init_user32() { HMODULE hUser32 = GetModuleHandle("USER32.DLL"); - IsHungThread_pfn = (IsHungThread_t)GetProcAddress(hUser32, "IsHungThread"); - DrawCaptionTempA_pfn = (DrawCaptionTempA_t)GetProcAddress(hUser32, "DrawCaptionTempA"); - GetMouseMovePoints_pfn = (GetMouseMovePoints_t)GetProcAddress(hUser32, "GetMouseMovePoints"); + IsHungThread_pfn = (IsHungThread_t)kexGetProcAddress(hUser32, "IsHungThread"); + DrawCaptionTempA_pfn = (DrawCaptionTempA_t)kexGetProcAddress(hUser32, "DrawCaptionTempA"); + GetMouseMovePoints_pfn = (GetMouseMovePoints_t)kexGetProcAddress(hUser32, "GetMouseMovePoints"); - return IsHungThread_pfn && DrawCaptionTempA_pfn && GetMouseMovePoints_pfn && InitUniThunkLayer(); + return IsHungThread_pfn && DrawCaptionTempA_pfn && GetMouseMovePoints_pfn + && InitUniThunkLayer() && SetParent_fix_init(); } /* APIs which don't require Unicode implementations in thuni model @@ -148,11 +151,13 @@ static const apilib_named_api user32_named_apis[] = DECL_API("SetClassLongW", SetClassLongW_NEW), DECL_API("SetDlgItemTextW", SetDlgItemTextW_NEW), DECL_API("SetLayeredWindowAttributes", SetLayeredWindowAttributes_stub), + DECL_API("SetParent", SetParent_fix), DECL_API("SetWindowLongA", SetWindowLongA_NEW), DECL_API("SetWindowLongW", SetWindowLongW_NEW), DECL_API("SetWindowTextW", SetWindowTextW_NEW), DECL_API("SetWindowsHookExW", SetWindowsHookExA), DECL_API("SetWindowsHookW", SetWindowsHookA), + DECL_API("SystemParametersInfoA", SystemParametersInfoA_fix), DECL_API("ToUnicode", ToUnicode_new), DECL_API("ToUnicodeEx", ToUnicodeEx_new), DECL_API("TranslateAcceleratorW", TranslateAcceleratorA), diff --git a/apilibs/kexbases/User32/_user32_apilist.h b/apilibs/kexbases/User32/_user32_apilist.h index 1d931e5..8417183 100755 --- a/apilibs/kexbases/User32/_user32_apilist.h +++ b/apilibs/kexbases/User32/_user32_apilist.h @@ -58,6 +58,8 @@ BOOL WINAPI LockWorkStation_new(void); UINT WINAPI MapVirtualKeyA_new(UINT uCode, UINT uMapType); UINT WINAPI MapVirtualKeyExA_new(UINT uCode, UINT uMapType, HKL dwhkl); LRESULT WINAPI SendMessageA_fix(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +HWND WINAPI SetParent_fix(HWND hWndChild, HWND hWndNewParent); +BOOL WINAPI SystemParametersInfoA_fix(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); BOOL WINAPI UpdateLayeredWindow_new(HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags); STUB SetLayeredWindowAttributes_stub; STUB DefRawInputProc_stub; diff --git a/apilibs/kexbases/User32/hwnd9x.h b/apilibs/kexbases/User32/hwnd9x.h index 5df8397..a6f3ac2 100755 --- a/apilibs/kexbases/User32/hwnd9x.h +++ b/apilibs/kexbases/User32/hwnd9x.h @@ -25,6 +25,8 @@ #ifndef _HWND32_H #define _HWND32_H +#define IS_SYSTEM_HWND(hwnd) ((hwnd)>=(HWND)0x80 && (hwnd)<=(HWND)0x88) + #pragma pack (1) typedef struct _RECTS { @@ -107,4 +109,6 @@ typedef struct _MSGQUEUE } MSGQUEUE, *PMSGQUEUE; #pragma pack() +typedef PWND (WINAPI *HTOP_API) (HWND hwnd); + #endif diff --git a/apilibs/kexbases/User32/thuni_layer.h b/apilibs/kexbases/User32/thuni_layer.h index fb6d561..e0172b0 100755 --- a/apilibs/kexbases/User32/thuni_layer.h +++ b/apilibs/kexbases/User32/thuni_layer.h @@ -20,7 +20,6 @@ static DWORD GetWindowProcessId( HWND hwnd ) #define ISDIALOG(pwnd) (pwnd->moreFlags & WF_M_DIALOG) typedef PMSGQUEUE (WINAPI *GCQ_API) (); -typedef PWND (WINAPI *HTOP_API) (HWND hwnd); #define RELTOABS(x) ( (DWORD)(x) + *(DWORD*)(x) + 4 ) diff --git a/apilibs/kexbases/comctl32/_comctl32_apilist.c b/apilibs/kexbases/comctl32/_comctl32_apilist.c new file mode 100755 index 0000000..af6aa6b --- /dev/null +++ b/apilibs/kexbases/comctl32/_comctl32_apilist.c @@ -0,0 +1,46 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86, Tihiy + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "common.h" +#include "kexcoresdk.h" +#include "_comctl32_apilist.h" + +BOOL init_comctl32() +{ + return TRUE; +} + +static const apilib_named_api comctl32_named_apis[] = +{ +/*** AUTOGENERATED APILIST NAMED EXPORTS BEGIN ***/ + DECL_API("InitCommonControlsEx", InitCommonControlsEx_new), +/*** AUTOGENERATED APILIST NAMED EXPORTS END ***/ +}; + +#if 0 +static const apilib_unnamed_api comctl32_ordinal_apis[] = +{ +/*** AUTOGENERATED APILIST ORDINAL EXPORTS BEGIN ***/ +/*** AUTOGENERATED APILIST ORDINAL EXPORTS END ***/ +}; +#endif + +const apilib_api_table apitable_comctl32 = DECL_TAB("COMCTL32.DLL", comctl32_named_apis, 0 /*comctl32_ordinal_apis*/); diff --git a/apilibs/kexbases/comctl32/_comctl32_apilist.h b/apilibs/kexbases/comctl32/_comctl32_apilist.h new file mode 100755 index 0000000..2b3fff3 --- /dev/null +++ b/apilibs/kexbases/comctl32/_comctl32_apilist.h @@ -0,0 +1,35 @@ +/* + * KernelEx + * Copyright (C) 2010, Xeno86, Tihiy + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _COMCTL32_APILIST_H +#define _COMCTL32_APILIST_H + +#include +#include "kexcoresdk.h" + +BOOL init_comctl32(); +extern const apilib_api_table apitable_comctl32; + +/*** AUTOGENERATED APILIST DECLARATIONS BEGIN ***/ +BOOL WINAPI InitCommonControlsEx_new(LPINITCOMMONCONTROLSEX lpInitCtrls); +/*** AUTOGENERATED APILIST DECLARATIONS END ***/ + +#endif diff --git a/apilibs/kexbases/comctl32/newclassreg.c b/apilibs/kexbases/comctl32/newclassreg.c new file mode 100755 index 0000000..487d7ee --- /dev/null +++ b/apilibs/kexbases/comctl32/newclassreg.c @@ -0,0 +1,59 @@ +/* + * KernelEx + * Copyright (C) 2010, Tihiy, Xeno86 + * + * This file is part of KernelEx source code. + * + * KernelEx is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * KernelEx is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600 +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 + +#include "common.h" +#include + + +typedef BOOL (WINAPI* ICCEX) (LPINITCOMMONCONTROLSEX); + +VOID SYSLINK_Register(void); + +/* MAKE_EXPORT InitCommonControlsEx_new=InitCommonControlsEx */ +BOOL WINAPI InitCommonControlsEx_new(LPINITCOMMONCONTROLSEX lpInitCtrls) +{ + static ICCEX InitCommonControlsEx_dld; + + //sanity check + if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX)) + return FALSE; + + //register SysLink + if (lpInitCtrls->dwICC & ICC_LINK_CLASS || + lpInitCtrls->dwICC == (ICC_WIN95_CLASSES|ICC_DATE_CLASSES|ICC_USEREX_CLASSES|ICC_COOL_CLASSES)) + { + SYSLINK_Register(); + if (lpInitCtrls->dwICC == ICC_LINK_CLASS) + return TRUE; //no other classes to register + + //remove SysLink from list of classes to register - COMCTL32 will fail otherwise + lpInitCtrls->dwICC &= ~ICC_LINK_CLASS; + } + if (!InitCommonControlsEx_dld) + InitCommonControlsEx_dld = (ICCEX)kexGetProcAddress(GetModuleHandle("COMCTL32.DLL"),"InitCommonControlsEx"); + + return InitCommonControlsEx_dld(lpInitCtrls); +} diff --git a/apilibs/kexbases/comctl32/syslink.c b/apilibs/kexbases/comctl32/syslink.c new file mode 100755 index 0000000..a5b046a --- /dev/null +++ b/apilibs/kexbases/comctl32/syslink.c @@ -0,0 +1,1854 @@ +/* + * SysLink control + * + * Copyright 2004 - 2006 Thomas Weidenmueller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * NOTES + * + * This code was audited for completeness against the documented features + * of Comctl32.dll version 6.0 on Apr. 4, 2005, by Dimitrie O. Paun. + * + * Unless otherwise noted, we believe this code to be complete, as per + * the specification mentioned above. + * If you discover missing features, or bugs, please note them below. + */ + +#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600 +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 + +#include "common.h" +#include +#include "../kernel32/_kernel32_apilist.h" +#include "../user32/_user32_apilist.h" + +/* PORTING STUFF */ +#ifdef _MSC_VER +#pragma warning(disable:4002) +#define TRACE() ((void)0) +#define TRACE_() ((void)0) +#define WARN() ((void)0) +#define ERR() ((void)0) +#else +#define TRACE(...) do {} while(0) +#define TRACE_(x) TRACE +#define WARN(...) do {} while(0) +#define ERR(...) do {} while(0) +#endif + +//comctl32 has StrCmpNIW, good enough for tag matching +typedef int (WINAPI* CC361) (LPCWSTR,LPCWSTR,int); +int WINAPI StrCmpNIW(LPCWSTR lpStr1,LPCWSTR lpStr2,int nChar) +{ + static CC361 StrCmpNIW_dld; + + if (!StrCmpNIW_dld) + StrCmpNIW_dld = (CC361)kexGetProcAddress(GetModuleHandle("COMCTL32.DLL"),(LPSTR)361); + + return StrCmpNIW_dld(lpStr1,lpStr2,nChar); +} + +BOOL WINAPI GetTextExtentExPointW_lame( HDC hdc, LPCWSTR lpszStr, int cchString, int nMaxExtent, + LPINT lpnFit, LPINT alpDx, LPSIZE lpSize) +{ + if ( GetTextExtentPointW(hdc,lpszStr,cchString,lpSize) ) + { + if (lpnFit) + { + SIZE dummy; + dummy.cx = lpSize->cx; + while (dummy.cx>nMaxExtent && cchString>0) + { + cchString--; + GetTextExtentPointW(hdc,lpszStr,cchString,&dummy); + } + *lpnFit = cchString; + } + return TRUE; + } + else + return FALSE; +} + +#define Alloc(x) calloc(1,x) +#define Free(x) free(x) +#define ReAlloc(x,y) recalloc(x,y) +#define GetTextExtentExPointW(h,s,n,m,f,d,l) GetTextExtentExPointW_lame(h,s,n,m,f,d,l) +#define lstrcpynW(x,y,z) lstrcpynW_new(x,y,z) +#define RegisterClassW(x) RegisterClassW_NEW(x) +#define DefWindowProcW(h,m,w,l) DefWindowProcW_NEW(h,m,w,l) +/* END OF PORTING STUFF */ + +typedef struct +{ + int nChars; + int nSkip; + RECT rc; +} DOC_TEXTBLOCK, *PDOC_TEXTBLOCK; + +#define LIF_FLAGSMASK (LIF_STATE | LIF_ITEMID | LIF_URL) +#define LIS_MASK (LIS_FOCUSED | LIS_ENABLED | LIS_VISITED) + +typedef enum +{ + slText = 0, + slLink +} SL_ITEM_TYPE; + +typedef struct _DOC_ITEM +{ + struct _DOC_ITEM *Next; /* Address to the next item */ + UINT nText; /* Number of characters of the text */ + SL_ITEM_TYPE Type; /* type of the item */ + PDOC_TEXTBLOCK Blocks; /* Array of text blocks */ + union + { + struct + { + UINT state; /* Link state */ + WCHAR *szID; /* Link ID string */ + WCHAR *szUrl; /* Link URL string */ + } Link; + struct + { + UINT Dummy; + } Text; + } u; + WCHAR Text[1]; /* Text of the document item */ +} DOC_ITEM, *PDOC_ITEM; + +typedef struct +{ + HWND Self; /* The window handle for this control */ + HWND Notify; /* The parent handle to receive notifications */ + DWORD Style; /* Styles for this control */ + PDOC_ITEM Items; /* Address to the first document item */ + BOOL HasFocus; /* Whether the control has the input focus */ + int MouseDownID; /* ID of the link that the mouse button first selected */ + HFONT Font; /* Handle to the font for text */ + HFONT LinkFont; /* Handle to the font for links */ + COLORREF TextColor; /* Color of the text */ + COLORREF LinkColor; /* Color of links */ + COLORREF VisitedColor; /* Color of visited links */ + COLORREF BackColor; /* Background color, set on creation */ + WCHAR BreakChar; /* Break Character for the current font */ + BOOL IgnoreReturn; /* (infoPtr->Style & LWS_IGNORERETURN) on creation */ +} SYSLINK_INFO; + +static const WCHAR SL_LINKOPEN[] = { '<','a', 0 }; +static const WCHAR SL_HREF[] = { 'h','r','e','f','=','\"',0 }; +static const WCHAR SL_ID[] = { 'i','d','=','\"',0 }; +static const WCHAR SL_LINKCLOSE[] = { '<','/','a','>',0 }; + +/* Control configuration constants */ + +#define SL_LEFTMARGIN (0) +#define SL_TOPMARGIN (0) +#define SL_RIGHTMARGIN (0) +#define SL_BOTTOMMARGIN (0) + +/*********************************************************************** + * SYSLINK_FreeDocItem + * Frees all data and gdi objects associated with a document item + */ +static VOID SYSLINK_FreeDocItem (PDOC_ITEM DocItem) +{ + if(DocItem->Type == slLink) + { + Free(DocItem->u.Link.szID); + Free(DocItem->u.Link.szUrl); + } + + /* we don't free Text because it's just a pointer to a character in the + entire window text string */ + + Free(DocItem); +} + +/*********************************************************************** + * SYSLINK_AppendDocItem + * Create and append a new document item. + */ +static PDOC_ITEM SYSLINK_AppendDocItem (SYSLINK_INFO *infoPtr, LPCWSTR Text, UINT textlen, + SL_ITEM_TYPE type, PDOC_ITEM LastItem) +{ + PDOC_ITEM Item; + + textlen = min(textlen, (UINT)lstrlenW(Text)); + Item = (PDOC_ITEM)Alloc(FIELD_OFFSET(DOC_ITEM, Text[textlen + 1])); + if(Item == NULL) + { + ERR("Failed to alloc DOC_ITEM structure!\n"); + return NULL; + } + + Item->Next = NULL; + Item->nText = textlen; + Item->Type = type; + Item->Blocks = NULL; + + if(LastItem != NULL) + { + LastItem->Next = Item; + } + else + { + infoPtr->Items = Item; + } + + lstrcpynW(Item->Text, Text, textlen + 1); + + return Item; +} + +/*********************************************************************** + * SYSLINK_ClearDoc + * Clears the document tree + */ +static VOID SYSLINK_ClearDoc (SYSLINK_INFO *infoPtr) +{ + PDOC_ITEM Item, Next; + + Item = infoPtr->Items; + while(Item != NULL) + { + Next = Item->Next; + SYSLINK_FreeDocItem(Item); + Item = Next; + } + + infoPtr->Items = NULL; +} + +/*********************************************************************** + * SYSLINK_ParseText + * Parses the window text string and creates a document. Returns the + * number of document items created. + */ +static UINT SYSLINK_ParseText (SYSLINK_INFO *infoPtr, LPCWSTR Text) +{ + LPCWSTR current, textstart = NULL, linktext = NULL, firsttag = NULL; + int taglen = 0, textlen = 0, linklen = 0, docitems = 0; + PDOC_ITEM Last = NULL; + SL_ITEM_TYPE CurrentType = slText; + LPCWSTR lpID, lpUrl; + UINT lenId, lenUrl; + + TRACE("(%p %s)\n", infoPtr, debugstr_w(Text)); + + for(current = Text; *current != 0;) + { + if(*current == '<') + { + if(!StrCmpNIW(current, SL_LINKOPEN, 2) && (CurrentType == slText)) + { + BOOL ValidParam = FALSE, ValidLink = FALSE; + + if(*(current + 2) == '>') + { + /* we just have to deal with a tag */ + taglen = 3; + ValidLink = TRUE; + ValidParam = TRUE; + firsttag = current; + linklen = 0; + lpID = NULL; + lpUrl = NULL; + } + else if(*(current + 2) == infoPtr->BreakChar) + { + /* we expect parameters, parse them */ + LPCWSTR *CurrentParameter = NULL, tmp; + UINT *CurrentParameterLen = NULL; + + taglen = 3; + tmp = current + taglen; + lpID = NULL; + lpUrl = NULL; + +CheckParameter: + /* compare the current position with all known parameters */ + if(!StrCmpNIW(tmp, SL_HREF, 6)) + { + taglen += 6; + ValidParam = TRUE; + CurrentParameter = &lpUrl; + CurrentParameterLen = &lenUrl; + } + else if(!StrCmpNIW(tmp, SL_ID, 4)) + { + taglen += 4; + ValidParam = TRUE; + CurrentParameter = &lpID; + CurrentParameterLen = &lenId; + } + else + { + ValidParam = FALSE; + } + + if(ValidParam) + { + /* we got a known parameter, now search until the next " character. + If we can't find a " character, there's a syntax error and we just assume it's text */ + ValidParam = FALSE; + *CurrentParameter = current + taglen; + *CurrentParameterLen = 0; + + for(tmp = *CurrentParameter; *tmp != 0; tmp++) + { + taglen++; + if(*tmp == '\"') + { + ValidParam = TRUE; + tmp++; + break; + } + (*CurrentParameterLen)++; + } + } + if(ValidParam) + { + /* we're done with this parameter, now there are only 2 possibilities: + * 1. another parameter is coming, so expect a ' ' (space) character + * 2. the tag is being closed, so expect a '<' character + */ + if(*tmp == infoPtr->BreakChar) + { + /* we expect another parameter, do the whole thing again */ + taglen++; + tmp++; + goto CheckParameter; + } + else if(*tmp == '>') + { + /* the tag is being closed, we're done */ + ValidLink = TRUE; + taglen++; + } + } + } + + if(ValidLink && ValidParam) + { + /* the tag appears to be valid. save all information + so we can add the link if we find a valid tag later */ + CurrentType = slLink; + linktext = current + taglen; + linklen = 0; + firsttag = current; + } + else + { + taglen = 1; + lpID = NULL; + lpUrl = NULL; + if(textstart == NULL) + { + textstart = current; + } + } + } + else if(!StrCmpNIW(current, SL_LINKCLOSE, 4) && (CurrentType == slLink) && firsttag) + { + /* there's a tag opened, first add the previous text, if present */ + if(textstart != NULL && textlen > 0 && firsttag > textstart) + { + Last = SYSLINK_AppendDocItem(infoPtr, textstart, firsttag - textstart, slText, Last); + if(Last == NULL) + { + ERR("Unable to create new document item!\n"); + return docitems; + } + docitems++; + textstart = NULL; + textlen = 0; + } + + /* now it's time to add the link to the document */ + current += 4; + if(linktext != NULL && linklen > 0) + { + Last = SYSLINK_AppendDocItem(infoPtr, linktext, linklen, slLink, Last); + if(Last == NULL) + { + ERR("Unable to create new document item!\n"); + return docitems; + } + docitems++; + if(CurrentType == slLink) + { + int nc; + + if(!(infoPtr->Style & WS_DISABLED)) + { + Last->u.Link.state |= LIS_ENABLED; + } + /* Copy the tag parameters */ + if(lpID != NULL) + { + nc = min(lenId, (UINT)lstrlenW(lpID)); + nc = min(nc, MAX_LINKID_TEXT - 1); + Last->u.Link.szID = (WCHAR*)Alloc((nc + 1) * sizeof(WCHAR)); + if(Last->u.Link.szID != NULL) + { + lstrcpynW(Last->u.Link.szID, lpID, nc + 1); + } + } + else + Last->u.Link.szID = NULL; + if(lpUrl != NULL) + { + nc = min(lenUrl, (UINT)lstrlenW(lpUrl)); + nc = min(nc, L_MAX_URL_LENGTH - 1); + Last->u.Link.szUrl = (WCHAR*)Alloc((nc + 1) * sizeof(WCHAR)); + if(Last->u.Link.szUrl != NULL) + { + lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1); + } + } + else + Last->u.Link.szUrl = NULL; + } + linktext = NULL; + } + CurrentType = slText; + firsttag = NULL; + textstart = NULL; + continue; + } + else + { + /* we don't know what tag it is, so just continue */ + taglen = 1; + linklen++; + if(CurrentType == slText && textstart == NULL) + { + textstart = current; + } + } + + textlen += taglen; + current += taglen; + } + else + { + textlen++; + linklen++; + + /* save the pointer of the current text item if we couldn't find a tag */ + if(textstart == NULL && CurrentType == slText) + { + textstart = current; + } + + current++; + } + } + + if(textstart != NULL && textlen > 0) + { + Last = SYSLINK_AppendDocItem(infoPtr, textstart, textlen, CurrentType, Last); + if(Last == NULL) + { + ERR("Unable to create new document item!\n"); + return docitems; + } + if(CurrentType == slLink) + { + int nc; + + if(!(infoPtr->Style & WS_DISABLED)) + { + Last->u.Link.state |= LIS_ENABLED; + } + /* Copy the tag parameters */ + if(lpID != NULL) + { + nc = min(lenId, (UINT)lstrlenW(lpID)); + nc = min(nc, MAX_LINKID_TEXT - 1); + Last->u.Link.szID = (WCHAR*)Alloc((nc + 1) * sizeof(WCHAR)); + if(Last->u.Link.szID != NULL) + { + lstrcpynW(Last->u.Link.szID, lpID, nc + 1); + } + } + else + Last->u.Link.szID = NULL; + if(lpUrl != NULL) + { + nc = min(lenUrl, (UINT)lstrlenW(lpUrl)); + nc = min(nc, L_MAX_URL_LENGTH - 1); + Last->u.Link.szUrl = (WCHAR*)Alloc((nc + 1) * sizeof(WCHAR)); + if(Last->u.Link.szUrl != NULL) + { + lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1); + } + } + else + Last->u.Link.szUrl = NULL; + } + docitems++; + } + + if(linktext != NULL && linklen > 0) + { + /* we got an unclosed link, just display the text */ + Last = SYSLINK_AppendDocItem(infoPtr, linktext, linklen, slText, Last); + if(Last == NULL) + { + ERR("Unable to create new document item!\n"); + return docitems; + } + docitems++; + } + + return docitems; +} + +/*********************************************************************** + * SYSLINK_RepaintLink + * Repaints a link. + */ +static VOID SYSLINK_RepaintLink (const SYSLINK_INFO *infoPtr, const DOC_ITEM *DocItem) +{ + PDOC_TEXTBLOCK bl; + int n; + + if(DocItem->Type != slLink) + { + ERR("DocItem not a link!\n"); + return; + } + + bl = DocItem->Blocks; + if (bl != NULL) + { + n = DocItem->nText; + + while(n > 0) + { + InvalidateRect(infoPtr->Self, &bl->rc, TRUE); + n -= bl->nChars + bl->nSkip; + bl++; + } + } +} + +/*********************************************************************** + * SYSLINK_GetLinkItemByIndex + * Retrieves a document link by its index + */ +static PDOC_ITEM SYSLINK_GetLinkItemByIndex (const SYSLINK_INFO *infoPtr, int iLink) +{ + PDOC_ITEM Current = infoPtr->Items; + + while(Current != NULL) + { + if((Current->Type == slLink) && (iLink-- <= 0)) + { + return Current; + } + Current = Current->Next; + } + return NULL; +} + +/*********************************************************************** + * SYSLINK_GetFocusLink + * Retrieves the link that has the LIS_FOCUSED bit + */ +static PDOC_ITEM SYSLINK_GetFocusLink (const SYSLINK_INFO *infoPtr, int *LinkId) +{ + PDOC_ITEM Current = infoPtr->Items; + int id = 0; + + while(Current != NULL) + { + if((Current->Type == slLink)) + { + if(Current->u.Link.state & LIS_FOCUSED) + { + if(LinkId != NULL) + *LinkId = id; + return Current; + } + id++; + } + Current = Current->Next; + } + return NULL; +} + +/*********************************************************************** + * SYSLINK_GetNextLink + * Gets the next link + */ +static PDOC_ITEM SYSLINK_GetNextLink (const SYSLINK_INFO *infoPtr, PDOC_ITEM Current) +{ + for(Current = (Current != NULL ? Current->Next : infoPtr->Items); + Current != NULL; + Current = Current->Next) + { + if(Current->Type == slLink) + { + return Current; + } + } + return NULL; +} + +/*********************************************************************** + * SYSLINK_GetPrevLink + * Gets the previous link + */ +static PDOC_ITEM SYSLINK_GetPrevLink (const SYSLINK_INFO *infoPtr, PDOC_ITEM Current) +{ + if(Current == NULL) + { + /* returns the last link */ + PDOC_ITEM Last = NULL; + + for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) + { + if(Current->Type == slLink) + { + Last = Current; + } + } + return Last; + } + else + { + /* returns the previous link */ + PDOC_ITEM Cur, Prev = NULL; + + for(Cur = infoPtr->Items; Cur != NULL; Cur = Cur->Next) + { + if(Cur == Current) + { + break; + } + if(Cur->Type == slLink) + { + Prev = Cur; + } + } + return Prev; + } +} + +/*********************************************************************** + * SYSLINK_WrapLine + * Tries to wrap a line. + */ +static BOOL SYSLINK_WrapLine (LPWSTR Text, WCHAR BreakChar, int *LineLen, + int nFit, LPSIZE Extent) +{ + WCHAR *Current; + + if(nFit == *LineLen) + { + return FALSE; + } + + *LineLen = nFit; + + Current = Text + nFit; + + /* check if we're in the middle of a word */ + if((*Current) != BreakChar) + { + /* search for the beginning of the word */ + while(Current > Text && (*(Current - 1)) != BreakChar) + { + Current--; + (*LineLen)--; + } + + if((*LineLen) == 0) + { + Extent->cx = 0; + Extent->cy = 0; + } + return TRUE; + } + + return TRUE; +} + +/*********************************************************************** + * SYSLINK_Render + * Renders the document in memory + */ +static VOID SYSLINK_Render (const SYSLINK_INFO *infoPtr, HDC hdc, PRECT pRect) +{ + RECT rc; + PDOC_ITEM Current; + HGDIOBJ hOldFont; + int x, y, LineHeight; + SIZE szDoc; + + szDoc.cx = szDoc.cy = 0; + + rc = *pRect; + rc.right -= SL_RIGHTMARGIN; + rc.bottom -= SL_BOTTOMMARGIN; + + if(rc.right - SL_LEFTMARGIN < 0) + rc.right = MAXLONG; + if (rc.bottom - SL_TOPMARGIN < 0) + rc.bottom = MAXLONG; + + hOldFont = SelectObject(hdc, infoPtr->Font); + + x = SL_LEFTMARGIN; + y = SL_TOPMARGIN; + LineHeight = 0; + + for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) + { + int n, nBlocks; + LPWSTR tx; + PDOC_TEXTBLOCK bl, cbl; + INT nFit; + SIZE szDim; + + if(Current->nText == 0) + { + continue; + } + + tx = Current->Text; + n = Current->nText; + + Free(Current->Blocks); + Current->Blocks = NULL; + bl = NULL; + nBlocks = 0; + + if(Current->Type == slText) + { + SelectObject(hdc, infoPtr->Font); + } + else if(Current->Type == slLink) + { + SelectObject(hdc, infoPtr->LinkFont); + } + + while(n > 0) + { + int SkipChars = 0; + + /* skip break characters unless they're the first of the doc item */ + if(tx != Current->Text || x == SL_LEFTMARGIN) + { + while(n > 0 && (*tx) == infoPtr->BreakChar) + { + tx++; + SkipChars++; + n--; + } + } + + if((n == 0 && SkipChars != 0) || + GetTextExtentExPointW(hdc, tx, n, rc.right - x, &nFit, NULL, &szDim)) + { + int LineLen = n; + BOOL Wrap = FALSE; + PDOC_TEXTBLOCK nbl; + + if(n != 0) + { + Wrap = SYSLINK_WrapLine(tx, infoPtr->BreakChar, &LineLen, nFit, &szDim); + + if(LineLen == 0) + { + if(x > SL_LEFTMARGIN) + { + /* move one line down, the word didn't fit into the line */ + x = SL_LEFTMARGIN; + y += LineHeight; + LineHeight = 0; + continue; + } + else + { + /* the word starts at the beginning of the line and doesn't + fit into the line, so break it at the last character that fits */ + LineLen = max(nFit, 1); + } + } + + if(LineLen != n) + { + if(!GetTextExtentExPointW(hdc, tx, LineLen, rc.right - x, NULL, NULL, &szDim)) + { + if(bl != NULL) + { + Free(bl); + bl = NULL; + nBlocks = 0; + } + break; + } + } + } + + nbl = (PDOC_TEXTBLOCK)ReAlloc(bl, (nBlocks + 1) * sizeof(DOC_TEXTBLOCK)); + if (nbl != NULL) + { + bl = nbl; + nBlocks++; + + cbl = bl + nBlocks - 1; + + cbl->nChars = LineLen; + cbl->nSkip = SkipChars; + cbl->rc.left = x; + cbl->rc.top = y; + cbl->rc.right = x + szDim.cx; + cbl->rc.bottom = y + szDim.cy; + + if (cbl->rc.right > szDoc.cx) + szDoc.cx = cbl->rc.right; + if (cbl->rc.bottom > szDoc.cy) + szDoc.cy = cbl->rc.bottom; + + if(LineLen != 0) + { + x += szDim.cx; + LineHeight = max(LineHeight, szDim.cy); + + if(Wrap) + { + x = SL_LEFTMARGIN; + y += LineHeight; + LineHeight = 0; + } + } + } + else + { + Free(bl); + bl = NULL; + nBlocks = 0; + + ERR("Failed to alloc DOC_TEXTBLOCK structure!\n"); + break; + } + n -= LineLen; + tx += LineLen; + } + else + { + n--; + } + } + + if(nBlocks != 0) + { + Current->Blocks = bl; + } + } + + SelectObject(hdc, hOldFont); + + pRect->right = pRect->left + szDoc.cx; + pRect->bottom = pRect->top + szDoc.cy; +} + +/*********************************************************************** + * SYSLINK_Draw + * Draws the SysLink control. + */ +static LRESULT SYSLINK_Draw (const SYSLINK_INFO *infoPtr, HDC hdc) +{ + RECT rc; + PDOC_ITEM Current; + HFONT hOldFont; + COLORREF OldTextColor, OldBkColor; + + hOldFont = (HFONT)SelectObject(hdc, infoPtr->Font); + OldTextColor = SetTextColor(hdc, infoPtr->TextColor); + OldBkColor = SetBkColor(hdc, infoPtr->BackColor); + + GetClientRect(infoPtr->Self, &rc); + rc.right -= SL_RIGHTMARGIN + SL_LEFTMARGIN; + rc.bottom -= SL_BOTTOMMARGIN + SL_TOPMARGIN; + + if(rc.right < 0 || rc.bottom < 0) return 0; + + for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) + { + int n; + LPWSTR tx; + PDOC_TEXTBLOCK bl; + + bl = Current->Blocks; + if(bl != NULL) + { + tx = Current->Text; + n = Current->nText; + + if(Current->Type == slText) + { + SelectObject(hdc, infoPtr->Font); + SetTextColor(hdc, infoPtr->TextColor); + } + else + { + SelectObject(hdc, infoPtr->LinkFont); + SetTextColor(hdc, (!(Current->u.Link.state & LIS_VISITED) ? infoPtr->LinkColor : infoPtr->VisitedColor)); + } + + while(n > 0) + { + tx += bl->nSkip; + ExtTextOutW(hdc, bl->rc.left, bl->rc.top, ETO_OPAQUE | ETO_CLIPPED, &bl->rc, tx, bl->nChars, NULL); + if((Current->Type == slLink) && (Current->u.Link.state & LIS_FOCUSED) && infoPtr->HasFocus) + { + COLORREF PrevTextColor; + PrevTextColor = SetTextColor(hdc, infoPtr->TextColor); + DrawFocusRect(hdc, &bl->rc); + SetTextColor(hdc, PrevTextColor); + } + tx += bl->nChars; + n -= bl->nChars + bl->nSkip; + bl++; + } + } + } + + SetBkColor(hdc, OldBkColor); + SetTextColor(hdc, OldTextColor); + SelectObject(hdc, hOldFont); + + return 0; +} + + +/*********************************************************************** + * SYSLINK_Paint + * Handles the WM_PAINT message. + */ +static LRESULT SYSLINK_Paint (const SYSLINK_INFO *infoPtr, HDC hdcParam) +{ + HDC hdc; + PAINTSTRUCT ps; + + hdc = hdcParam ? hdcParam : BeginPaint (infoPtr->Self, &ps); + if (hdc) + { + SYSLINK_Draw (infoPtr, hdc); + if (!hdcParam) EndPaint (infoPtr->Self, &ps); + } + return 0; +} + +/*********************************************************************** + * SYSLINK_EraseBkgnd + * Handles the WM_ERASEBKGND message. + */ +static LRESULT SYSLINK_EraseBkgnd (const SYSLINK_INFO *infoPtr, HDC hdc) +{ + HBRUSH hbr; + RECT r; + + GetClientRect(infoPtr->Self, &r); + hbr = CreateSolidBrush(infoPtr->BackColor); + FillRect(hdc, &r, hbr); + DeleteObject(hbr); + + return 1; +} + +/*********************************************************************** + * SYSLINK_SetFont + * Set new Font for the SysLink control. + */ +static HFONT SYSLINK_SetFont (SYSLINK_INFO *infoPtr, HFONT hFont, BOOL bRedraw) +{ + HDC hdc; + LOGFONTA lf; + TEXTMETRICA tm; + RECT rcClient; + HFONT hOldFont = infoPtr->Font; + infoPtr->Font = hFont; + + /* free the underline font */ + if(infoPtr->LinkFont != NULL) + { + DeleteObject(infoPtr->LinkFont); + infoPtr->LinkFont = NULL; + } + + /* Render text position and word wrapping in memory */ + if (GetClientRect(infoPtr->Self, &rcClient)) + { + hdc = GetDC(infoPtr->Self); + if(hdc != NULL) + { + /* create a new underline font */ + if(GetTextMetricsA(hdc, &tm) && + GetObjectA(infoPtr->Font, sizeof(LOGFONTA), &lf)) + { + lf.lfUnderline = TRUE; + infoPtr->LinkFont = CreateFontIndirectA(&lf); + infoPtr->BreakChar = tm.tmBreakChar; + } + else + { + ERR("Failed to create link font!\n"); + } + + SYSLINK_Render(infoPtr, hdc, &rcClient); + ReleaseDC(infoPtr->Self, hdc); + } + } + + if(bRedraw) + { + RedrawWindow(infoPtr->Self, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + + return hOldFont; +} + +/*********************************************************************** + * SYSLINK_SetText + * Set new text for the SysLink control. + */ +static LRESULT SYSLINK_SetText (SYSLINK_INFO *infoPtr, LPCWSTR Text) +{ + /* clear the document */ + SYSLINK_ClearDoc(infoPtr); + + if(Text == NULL || *Text == 0) + { + return TRUE; + } + + /* let's parse the string and create a document */ + if(SYSLINK_ParseText(infoPtr, Text) > 0) + { + RECT rcClient; + + /* Render text position and word wrapping in memory */ + if (GetClientRect(infoPtr->Self, &rcClient)) + { + HDC hdc = GetDC(infoPtr->Self); + if (hdc != NULL) + { + SYSLINK_Render(infoPtr, hdc, &rcClient); + ReleaseDC(infoPtr->Self, hdc); + + InvalidateRect(infoPtr->Self, NULL, TRUE); + } + } + } + + return TRUE; +} + +/*********************************************************************** + * SYSLINK_SetFocusLink + * Updates the focus status bits and focusses the specified link. + * If no document item is specified, the focus bit will be removed from all links. + * Returns the previous focused item. + */ +static PDOC_ITEM SYSLINK_SetFocusLink (const SYSLINK_INFO *infoPtr, const DOC_ITEM *DocItem) +{ + PDOC_ITEM Current, PrevFocus = NULL; + + for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) + { + if(Current->Type == slLink) + { + if((PrevFocus == NULL) && (Current->u.Link.state & LIS_FOCUSED)) + { + PrevFocus = Current; + } + + if(Current == DocItem) + { + Current->u.Link.state |= LIS_FOCUSED; + } + else + { + Current->u.Link.state &= ~LIS_FOCUSED; + } + } + } + + return PrevFocus; +} + +/*********************************************************************** + * SYSLINK_SetItem + * Sets the states and attributes of a link item. + */ +static LRESULT SYSLINK_SetItem (const SYSLINK_INFO *infoPtr, const LITEM *Item) +{ + PDOC_ITEM di; + int nc; + PWSTR szId = NULL; + PWSTR szUrl = NULL; + BOOL Repaint = FALSE; + + if(!(Item->mask & LIF_ITEMINDEX) || !(Item->mask & (LIF_FLAGSMASK))) + { + ERR("Invalid Flags!\n"); + return FALSE; + } + + di = SYSLINK_GetLinkItemByIndex(infoPtr, Item->iLink); + if(di == NULL) + { + ERR("Link %d couldn't be found\n", Item->iLink); + return FALSE; + } + + if(Item->mask & LIF_ITEMID) + { + nc = min(lstrlenW(Item->szID), MAX_LINKID_TEXT - 1); + szId = (PWSTR)Alloc((nc + 1) * sizeof(WCHAR)); + if(szId) + { + lstrcpynW(szId, Item->szID, nc + 1); + } + else + { + ERR("Unable to allocate memory for link id\n"); + return FALSE; + } + } + + if(Item->mask & LIF_URL) + { + nc = min(lstrlenW(Item->szUrl), L_MAX_URL_LENGTH - 1); + szUrl = (PWSTR)Alloc((nc + 1) * sizeof(WCHAR)); + if(szUrl) + { + lstrcpynW(szUrl, Item->szUrl, nc + 1); + } + else + { + Free(szId); + + ERR("Unable to allocate memory for link url\n"); + return FALSE; + } + } + + if(Item->mask & LIF_ITEMID) + { + Free(di->u.Link.szID); + di->u.Link.szID = szId; + } + + if(Item->mask & LIF_URL) + { + Free(di->u.Link.szUrl); + di->u.Link.szUrl = szUrl; + } + + if(Item->mask & LIF_STATE) + { + UINT oldstate = di->u.Link.state; + /* clear the masked bits */ + di->u.Link.state &= ~(Item->stateMask & LIS_MASK); + /* copy the bits */ + di->u.Link.state |= (Item->state & Item->stateMask) & LIS_MASK; + Repaint = (oldstate != di->u.Link.state); + + /* update the focus */ + SYSLINK_SetFocusLink(infoPtr, ((di->u.Link.state & LIS_FOCUSED) ? di : NULL)); + } + + if(Repaint) + { + SYSLINK_RepaintLink(infoPtr, di); + } + + return TRUE; +} + +/*********************************************************************** + * SYSLINK_GetItem + * Retrieves the states and attributes of a link item. + */ +static LRESULT SYSLINK_GetItem (const SYSLINK_INFO *infoPtr, PLITEM Item) +{ + PDOC_ITEM di; + + if(!(Item->mask & LIF_ITEMINDEX) || !(Item->mask & (LIF_FLAGSMASK))) + { + ERR("Invalid Flags!\n"); + return FALSE; + } + + di = SYSLINK_GetLinkItemByIndex(infoPtr, Item->iLink); + if(di == NULL) + { + ERR("Link %d couldn't be found\n", Item->iLink); + return FALSE; + } + + if(Item->mask & LIF_STATE) + { + Item->state = (di->u.Link.state & Item->stateMask); + if(!infoPtr->HasFocus) + { + /* remove the LIS_FOCUSED bit if the control doesn't have focus */ + Item->state &= ~LIS_FOCUSED; + } + } + + if(Item->mask & LIF_ITEMID) + { + if(di->u.Link.szID) + { + lstrcpyW(Item->szID, di->u.Link.szID); + } + else + { + Item->szID[0] = 0; + } + } + + if(Item->mask & LIF_URL) + { + if(di->u.Link.szUrl) + { + lstrcpyW(Item->szUrl, di->u.Link.szUrl); + } + else + { + Item->szUrl[0] = 0; + } + } + + return TRUE; +} + +/*********************************************************************** + * SYSLINK_PtInDocItem + * Determines if a point is in the region of a document item + */ +static BOOL SYSLINK_PtInDocItem (const DOC_ITEM *DocItem, POINT pt) +{ + PDOC_TEXTBLOCK bl; + int n; + + bl = DocItem->Blocks; + if (bl != NULL) + { + n = DocItem->nText; + + while(n > 0) + { + if (PtInRect(&bl->rc, pt)) + { + return TRUE; + } + n -= bl->nChars + bl->nSkip; + bl++; + } + } + + return FALSE; +} + +/*********************************************************************** + * SYSLINK_HitTest + * Determines the link the user clicked on. + */ +static LRESULT SYSLINK_HitTest (const SYSLINK_INFO *infoPtr, PLHITTESTINFO HitTest) +{ + PDOC_ITEM Current; + int id = 0; + + for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) + { + if(Current->Type == slLink) + { + if(SYSLINK_PtInDocItem(Current, HitTest->pt)) + { + HitTest->item.mask = 0; + HitTest->item.iLink = id; + HitTest->item.state = 0; + HitTest->item.stateMask = 0; + if(Current->u.Link.szID) + { + lstrcpyW(HitTest->item.szID, Current->u.Link.szID); + } + else + { + HitTest->item.szID[0] = 0; + } + if(Current->u.Link.szUrl) + { + lstrcpyW(HitTest->item.szUrl, Current->u.Link.szUrl); + } + else + { + HitTest->item.szUrl[0] = 0; + } + return TRUE; + } + id++; + } + } + + return FALSE; +} + +/*********************************************************************** + * SYSLINK_GetIdealHeight + * Returns the preferred height of a link at the current control's width. + */ +static LRESULT SYSLINK_GetIdealHeight (const SYSLINK_INFO *infoPtr) +{ + HDC hdc = GetDC(infoPtr->Self); + if(hdc != NULL) + { + LRESULT height; + TEXTMETRICA tm; + HGDIOBJ hOldFont = SelectObject(hdc, infoPtr->Font); + + if(GetTextMetricsA(hdc, &tm)) + { + height = tm.tmHeight; + } + else + { + height = 0; + } + SelectObject(hdc, hOldFont); + ReleaseDC(infoPtr->Self, hdc); + + return height; + } + return 0; +} + +/*********************************************************************** + * SYSLINK_SendParentNotify + * Sends a WM_NOTIFY message to the parent window. + */ +static LRESULT SYSLINK_SendParentNotify (const SYSLINK_INFO *infoPtr, UINT code, const DOC_ITEM *Link, int iLink) +{ + NMLINK nml; + + nml.hdr.hwndFrom = infoPtr->Self; + nml.hdr.idFrom = GetWindowLongA(infoPtr->Self, GWLP_ID); + nml.hdr.code = code; + + nml.item.mask = 0; + nml.item.iLink = iLink; + nml.item.state = 0; + nml.item.stateMask = 0; + if(Link->u.Link.szID) + { + lstrcpyW(nml.item.szID, Link->u.Link.szID); + } + else + { + nml.item.szID[0] = 0; + } + if(Link->u.Link.szUrl) + { + lstrcpyW(nml.item.szUrl, Link->u.Link.szUrl); + } + else + { + nml.item.szUrl[0] = 0; + } + + return SendMessageA(infoPtr->Notify, WM_NOTIFY, nml.hdr.idFrom, (LPARAM)&nml); +} + +/*********************************************************************** + * SYSLINK_SetFocus + * Handles receiving the input focus. + */ +static LRESULT SYSLINK_SetFocus (SYSLINK_INFO *infoPtr) +{ + PDOC_ITEM Focus; + + infoPtr->HasFocus = TRUE; + + /* We always select the first link, even if we activated the control using + SHIFT+TAB. This is the default behavior */ + Focus = SYSLINK_GetNextLink(infoPtr, NULL); + if(Focus != NULL) + { + SYSLINK_SetFocusLink(infoPtr, Focus); + SYSLINK_RepaintLink(infoPtr, Focus); + } + return 0; +} + +/*********************************************************************** + * SYSLINK_KillFocus + * Handles losing the input focus. + */ +static LRESULT SYSLINK_KillFocus (SYSLINK_INFO *infoPtr) +{ + PDOC_ITEM Focus; + + infoPtr->HasFocus = FALSE; + Focus = SYSLINK_GetFocusLink(infoPtr, NULL); + + if(Focus != NULL) + { + SYSLINK_RepaintLink(infoPtr, Focus); + } + + return 0; +} + +/*********************************************************************** + * SYSLINK_LinkAtPt + * Returns a link at the specified position + */ +static PDOC_ITEM SYSLINK_LinkAtPt (const SYSLINK_INFO *infoPtr, const POINT *pt, int *LinkId, BOOL MustBeEnabled) +{ + PDOC_ITEM Current; + int id = 0; + + for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) + { + if((Current->Type == slLink) && SYSLINK_PtInDocItem(Current, *pt) && + (!MustBeEnabled || (MustBeEnabled && (Current->u.Link.state & LIS_ENABLED)))) + { + if(LinkId != NULL) + { + *LinkId = id; + } + return Current; + } + id++; + } + + return NULL; +} + +/*********************************************************************** + * SYSLINK_LButtonDown + * Handles mouse clicks + */ +static LRESULT SYSLINK_LButtonDown (SYSLINK_INFO *infoPtr, const POINT *pt) +{ + PDOC_ITEM Current, Old; + int id; + + Current = SYSLINK_LinkAtPt(infoPtr, pt, &id, TRUE); + if(Current != NULL) + { + SetFocus(infoPtr->Self); + + Old = SYSLINK_SetFocusLink(infoPtr, Current); + if(Old != NULL && Old != Current) + { + SYSLINK_RepaintLink(infoPtr, Old); + } + infoPtr->MouseDownID = id; + SYSLINK_RepaintLink(infoPtr, Current); + } + + return 0; +} + +/*********************************************************************** + * SYSLINK_LButtonUp + * Handles mouse clicks + */ +static LRESULT SYSLINK_LButtonUp (SYSLINK_INFO *infoPtr, const POINT *pt) +{ + if(infoPtr->MouseDownID > -1) + { + PDOC_ITEM Current; + int id; + + Current = SYSLINK_LinkAtPt(infoPtr, pt, &id, TRUE); + if((Current != NULL) && (Current->u.Link.state & LIS_FOCUSED) && (infoPtr->MouseDownID == id)) + { + SYSLINK_SendParentNotify(infoPtr, NM_CLICK, Current, id); + } + } + + infoPtr->MouseDownID = -1; + + return 0; +} + +/*********************************************************************** + * SYSLINK_OnEnter + * Handles ENTER key events + */ +static BOOL SYSLINK_OnEnter (const SYSLINK_INFO *infoPtr) +{ + if(infoPtr->HasFocus && !infoPtr->IgnoreReturn) + { + PDOC_ITEM Focus; + int id; + + Focus = SYSLINK_GetFocusLink(infoPtr, &id); + if(Focus) + { + SYSLINK_SendParentNotify(infoPtr, NM_RETURN, Focus, id); + return TRUE; + } + } + return FALSE; +} + +/*********************************************************************** + * SYSKEY_SelectNextPrevLink + * Changes the currently focused link + */ +static BOOL SYSKEY_SelectNextPrevLink (const SYSLINK_INFO *infoPtr, BOOL Prev) +{ + if(infoPtr->HasFocus) + { + PDOC_ITEM Focus; + int id; + + Focus = SYSLINK_GetFocusLink(infoPtr, &id); + if(Focus != NULL) + { + PDOC_ITEM NewFocus, OldFocus; + + if(Prev) + NewFocus = SYSLINK_GetPrevLink(infoPtr, Focus); + else + NewFocus = SYSLINK_GetNextLink(infoPtr, Focus); + + if(NewFocus != NULL) + { + OldFocus = SYSLINK_SetFocusLink(infoPtr, NewFocus); + + if(OldFocus && OldFocus != NewFocus) + { + SYSLINK_RepaintLink(infoPtr, OldFocus); + } + SYSLINK_RepaintLink(infoPtr, NewFocus); + return TRUE; + } + } + } + return FALSE; +} + +/*********************************************************************** + * SYSKEY_SelectNextPrevLink + * Determines if there's a next or previous link to decide whether the control + * should capture the tab key message + */ +static BOOL SYSLINK_NoNextLink (const SYSLINK_INFO *infoPtr, BOOL Prev) +{ + PDOC_ITEM Focus, NewFocus; + + Focus = SYSLINK_GetFocusLink(infoPtr, NULL); + if(Prev) + NewFocus = SYSLINK_GetPrevLink(infoPtr, Focus); + else + NewFocus = SYSLINK_GetNextLink(infoPtr, Focus); + + return NewFocus == NULL; +} + +/*********************************************************************** + * SYSLINK_GetIdealSize + * Calculates the ideal size of a link control at a given maximum width. + */ +static VOID SYSLINK_GetIdealSize (const SYSLINK_INFO *infoPtr, int cxMaxWidth, LPSIZE lpSize) +{ + RECT rc; + HDC hdc; + + rc.left = rc.top = rc.bottom = 0; + rc.right = cxMaxWidth; + + hdc = GetDC(infoPtr->Self); + if (hdc != NULL) + { + HGDIOBJ hOldFont = SelectObject(hdc, infoPtr->Font); + + SYSLINK_Render(infoPtr, hdc, &rc); + + SelectObject(hdc, hOldFont); + ReleaseDC(infoPtr->Self, hdc); + + lpSize->cx = rc.right; + lpSize->cy = rc.bottom; + } +} + +/*********************************************************************** + * SysLinkWindowProc + */ +static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + SYSLINK_INFO *infoPtr; + + TRACE("hwnd=%p msg=%04x wparam=%lx lParam=%lx\n", hwnd, message, wParam, lParam); + + infoPtr = (SYSLINK_INFO *)GetWindowLongA(hwnd, 0); + + if (!infoPtr && message != WM_CREATE) + goto HandleDefaultMessage; + + switch(message) { + case WM_PRINTCLIENT: + case WM_PAINT: + return SYSLINK_Paint (infoPtr, (HDC)wParam); + + case WM_ERASEBKGND: + return SYSLINK_EraseBkgnd(infoPtr, (HDC)wParam); + + case WM_SETCURSOR: + { + LHITTESTINFO ht; + DWORD mp = GetMessagePos(); + + ht.pt.x = (short)LOWORD(mp); + ht.pt.y = (short)HIWORD(mp); + + ScreenToClient(infoPtr->Self, &ht.pt); + if(SYSLINK_HitTest (infoPtr, &ht)) + { + SetCursor(LoadCursorA(0, (LPCSTR)IDC_HAND)); + return TRUE; + } + /* let the default window proc handle this message */ + goto HandleDefaultMessage; + } + + case WM_SIZE: + { + RECT rcClient; + if (GetClientRect(infoPtr->Self, &rcClient)) + { + HDC hdc = GetDC(infoPtr->Self); + if(hdc != NULL) + { + SYSLINK_Render(infoPtr, hdc, &rcClient); + ReleaseDC(infoPtr->Self, hdc); + } + } + return 0; + } + + case WM_GETFONT: + return (LRESULT)infoPtr->Font; + + case WM_SETFONT: + return (LRESULT)SYSLINK_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam); + + case WM_SETTEXT: + SYSLINK_SetText(infoPtr, (LPWSTR)lParam); + goto HandleDefaultMessage; + + case WM_LBUTTONDOWN: + { + POINT pt; + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + return SYSLINK_LButtonDown(infoPtr, &pt); + } + case WM_LBUTTONUP: + { + POINT pt; + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + return SYSLINK_LButtonUp(infoPtr, &pt); + } + + case WM_KEYDOWN: + { + switch(wParam) + { + case VK_RETURN: + SYSLINK_OnEnter(infoPtr); + return 0; + case VK_TAB: + { + BOOL shift = GetKeyState(VK_SHIFT) & 0x8000; + SYSKEY_SelectNextPrevLink(infoPtr, shift); + return 0; + } + } + goto HandleDefaultMessage; + } + + case WM_GETDLGCODE: + { + LRESULT Ret = DLGC_HASSETSEL; + int vk = (lParam != 0 ? (int)((LPMSG)lParam)->wParam : 0); + switch(vk) + { + case VK_RETURN: + Ret |= DLGC_WANTMESSAGE; + break; + case VK_TAB: + { + BOOL shift = GetKeyState(VK_SHIFT) & 0x8000; + if(!SYSLINK_NoNextLink(infoPtr, shift)) + { + Ret |= DLGC_WANTTAB; + } + else + { + Ret |= DLGC_WANTCHARS; + } + break; + } + } + return Ret; + } + + case WM_NCHITTEST: + { + POINT pt; + RECT rc; + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + + GetClientRect(infoPtr->Self, &rc); + ScreenToClient(infoPtr->Self, &pt); + if(pt.x < 0 || pt.y < 0 || pt.x > rc.right || pt.y > rc.bottom) + { + return HTNOWHERE; + } + + if(SYSLINK_LinkAtPt(infoPtr, &pt, NULL, FALSE)) + { + return HTCLIENT; + } + + return HTTRANSPARENT; + } + + case LM_HITTEST: + return SYSLINK_HitTest(infoPtr, (PLHITTESTINFO)lParam); + + case LM_SETITEM: + return SYSLINK_SetItem(infoPtr, (PLITEM)lParam); + + case LM_GETITEM: + return SYSLINK_GetItem(infoPtr, (PLITEM)lParam); + + case LM_GETIDEALHEIGHT: + if (lParam) + { + /* LM_GETIDEALSIZE */ + SYSLINK_GetIdealSize(infoPtr, (int)wParam, (LPSIZE)lParam); + } + return SYSLINK_GetIdealHeight(infoPtr); + + case WM_SETFOCUS: + return SYSLINK_SetFocus(infoPtr); + + case WM_KILLFOCUS: + return SYSLINK_KillFocus(infoPtr); + + case WM_ENABLE: + infoPtr->Style &= ~WS_DISABLED; + infoPtr->Style |= (wParam ? 0 : WS_DISABLED); + InvalidateRect (infoPtr->Self, NULL, FALSE); + return 0; + + case WM_STYLECHANGED: + if (wParam == GWL_STYLE) + { + infoPtr->Style = ((LPSTYLESTRUCT)lParam)->styleNew; + + InvalidateRect(infoPtr->Self, NULL, TRUE); + } + return 0; + + case WM_CREATE: + /* allocate memory for info struct */ + infoPtr = (SYSLINK_INFO *)Alloc (sizeof(SYSLINK_INFO)); + if (!infoPtr) return -1; + SetWindowLongA(hwnd, 0, (DWORD_PTR)infoPtr); + + /* initialize the info struct */ + infoPtr->Self = hwnd; + infoPtr->Notify = ((LPCREATESTRUCTW)lParam)->hwndParent; + infoPtr->Style = ((LPCREATESTRUCTW)lParam)->style; + infoPtr->Font = 0; + infoPtr->LinkFont = 0; + infoPtr->Items = NULL; + infoPtr->HasFocus = FALSE; + infoPtr->MouseDownID = -1; + infoPtr->TextColor = GetSysColor(COLOR_WINDOWTEXT); + infoPtr->LinkColor = GetSysColor(COLOR_HIGHLIGHT); + infoPtr->VisitedColor = GetSysColor(COLOR_HIGHLIGHT); + infoPtr->BackColor = infoPtr->Style & LWS_TRANSPARENT ? + GetSysColor(COLOR_WINDOW) : GetSysColor(COLOR_BTNFACE); + infoPtr->BreakChar = ' '; + infoPtr->IgnoreReturn = infoPtr->Style & LWS_IGNORERETURN; + TRACE("SysLink Ctrl creation, hwnd=%p\n", hwnd); + SYSLINK_SetText(infoPtr, ((LPCREATESTRUCTW)lParam)->lpszName); + return 0; + + case WM_DESTROY: + TRACE("SysLink Ctrl destruction, hwnd=%p\n", hwnd); + SYSLINK_ClearDoc(infoPtr); + if(infoPtr->Font != 0) DeleteObject(infoPtr->Font); + if(infoPtr->LinkFont != 0) DeleteObject(infoPtr->LinkFont); + SetWindowLongA(hwnd, 0, 0); + Free (infoPtr); + return 0; + + case WM_SYSCOLORCHANGE: + if (infoPtr->Style & LWS_TRANSPARENT) + infoPtr->BackColor = GetSysColor(COLOR_WINDOW); + return 0; + + default: +HandleDefaultMessage: + return DefWindowProcW(hwnd, message, wParam, lParam); + } +} + + +/*********************************************************************** + * SYSLINK_Register [Internal] + * + * Registers the SysLink window class. + */ +VOID SYSLINK_Register (void) +{ + WNDCLASSW wndClass; + + ZeroMemory (&wndClass, sizeof(wndClass)); + wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; + wndClass.lpfnWndProc = SysLinkWindowProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = sizeof (SYSLINK_INFO *); + wndClass.hCursor = LoadCursorA(NULL,(LPSTR)IDC_ARROW); + wndClass.lpszClassName = WC_LINK; + + RegisterClassW(&wndClass); +} diff --git a/apilibs/kexbases/comdlg32/PrintDlgEx.c b/apilibs/kexbases/comdlg32/PrintDlgEx.c index 6ce25b6..957c631 100755 --- a/apilibs/kexbases/comdlg32/PrintDlgEx.c +++ b/apilibs/kexbases/comdlg32/PrintDlgEx.c @@ -19,7 +19,10 @@ * */ +#define WIN32_LEAN_AND_MEAN #include +#include +#include /* MAKE_EXPORT PrintDlgEx_new=PrintDlgExA * MAKE_EXPORT PrintDlgEx_new=PrintDlgExW diff --git a/apilibs/kexbases/comdlg32/_comdlg32_apilist.h b/apilibs/kexbases/comdlg32/_comdlg32_apilist.h index 5bde373..130c551 100755 --- a/apilibs/kexbases/comdlg32/_comdlg32_apilist.h +++ b/apilibs/kexbases/comdlg32/_comdlg32_apilist.h @@ -23,6 +23,8 @@ #define _COMDLG32_APILIST_H #include "kexcoresdk.h" +#include +#include BOOL init_comdlg32(); extern const apilib_api_table apitable_comdlg32; diff --git a/apilibs/kexbases/common.c b/apilibs/kexbases/common.c index 346e7ff..1b7db4e 100755 --- a/apilibs/kexbases/common.c +++ b/apilibs/kexbases/common.c @@ -50,3 +50,9 @@ char* file_fixWprefix(char* in) } return in; } + +void fatal_error(const char* msg) +{ + MessageBox(NULL, msg, "KernelEx error", MB_OK | MB_ICONERROR); + ExitProcess(1); +} diff --git a/apilibs/kexbases/common.h b/apilibs/kexbases/common.h index 5f9560f..36d0b98 100755 --- a/apilibs/kexbases/common.h +++ b/apilibs/kexbases/common.h @@ -22,13 +22,17 @@ #ifndef __COMMON_H #define __COMMON_H +#define WIN32_LEAN_AND_MEAN #include #include +#include "kexcoresdk.h" #ifdef __cplusplus extern "C" { #endif +void* __cdecl recalloc(void* ptr, size_t size); + typedef int __stdcall STUB(void); typedef int __stdcall FWDPROC(void); @@ -36,6 +40,7 @@ extern int acp_mcs; BOOL common_init(void); int WINAPI CommonUnimpStub(void); char* file_fixWprefix(char* in); +void fatal_error(const char* msg); #ifdef __cplusplus }; diff --git a/apilibs/kexbases/dirlist b/apilibs/kexbases/dirlist index fe65ef2..90a25ea 100755 --- a/apilibs/kexbases/dirlist +++ b/apilibs/kexbases/dirlist @@ -5,3 +5,4 @@ advapi32 comdlg32 shell32 version +comctl32 diff --git a/apilibs/kexbases/kexbases.dsp b/apilibs/kexbases/kexbases.dsp index b8e60b7..15be6d4 100755 --- a/apilibs/kexbases/kexbases.dsp +++ b/apilibs/kexbases/kexbases.dsp @@ -117,6 +117,10 @@ SOURCE=.\Kernel32\CopyFileEx.c # End Source File # Begin Source File +SOURCE=.\Kernel32\CreateFiberEx.c +# End Source File +# Begin Source File + SOURCE=.\Kernel32\CreateThread_fix.c # End Source File # Begin Source File @@ -141,6 +145,10 @@ SOURCE=.\Kernel32\GetModuleHandleEx.c # End Source File # Begin Source File +SOURCE=.\Kernel32\GetProcessId.c +# End Source File +# Begin Source File + SOURCE=.\Kernel32\GlobalMemoryStatusEx.c # End Source File # Begin Source File @@ -217,14 +225,26 @@ SOURCE=.\Kernel32\OpenThread.c # End Source File # Begin Source File +SOURCE=.\Kernel32\pointer.c +# End Source File +# Begin Source File + SOURCE=.\Kernel32\RemoteDesktop.c # End Source File # Begin Source File +SOURCE=.\Kernel32\RtlCaptureContext.c +# End Source File +# Begin Source File + SOURCE=.\Kernel32\SetFilePointerEx.c # End Source File # Begin Source File +SOURCE=.\Kernel32\time.c +# End Source File +# Begin Source File + SOURCE=.\Kernel32\TryEnterCriticalSection.c # End Source File # Begin Source File @@ -317,6 +337,14 @@ SOURCE=.\User32\SendMessage_fix.c # End Source File # Begin Source File +SOURCE=.\User32\SetParent_fix.c +# End Source File +# Begin Source File + +SOURCE=.\User32\SystemParametersInfo_fix.c +# End Source File +# Begin Source File + SOURCE=.\User32\thuni_conv.c # End Source File # Begin Source File @@ -492,6 +520,26 @@ SOURCE=.\shell32\CommandLineToArgvW.c SOURCE=.\shell32\IsUserAnAdmin.c # End Source File # End Group +# Begin Group "comctl32" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\comctl32\_comctl32_apilist.c +# End Source File +# Begin Source File + +SOURCE=.\comctl32\_comctl32_apilist.h +# End Source File +# Begin Source File + +SOURCE=.\comctl32\newclassreg.c +# End Source File +# Begin Source File + +SOURCE=.\comctl32\syslink.c +# End Source File +# End Group # Begin Source File SOURCE=.\common.c @@ -582,10 +630,6 @@ InputPath=.\kexbases.def SOURCE=.\main.c # End Source File -# Begin Source File - -SOURCE=.\Kernel32\RtlCaptureContext.c -# End Source File # End Group # Begin Group "Header Files" diff --git a/apilibs/kexbases/main.c b/apilibs/kexbases/main.c index 376f057..f059d2b 100755 --- a/apilibs/kexbases/main.c +++ b/apilibs/kexbases/main.c @@ -28,10 +28,11 @@ #include "comdlg32/_comdlg32_apilist.h" #include "shell32/_shell32_apilist.h" #include "version/_version_apilist.h" +#include "comctl32/_comctl32_apilist.h" //#include "/__apilist.h" static LONG inited = 0; -static apilib_api_table api_table[8]; +static apilib_api_table api_table[9]; static void fill_apitable() { @@ -42,6 +43,7 @@ static void fill_apitable() api_table[4] = apitable_comdlg32; api_table[5] = apitable_shell32; api_table[6] = apitable_version; + api_table[7] = apitable_comctl32; //last entry is null terminator } @@ -55,7 +57,7 @@ const apilib_api_table* get_api_table() BOOL init_once() { - return common_init() && init_kernel32() && init_gdi32() && init_user32() && init_advapi32() && init_comdlg32() && init_shell32() && init_version(); + return common_init() && init_kernel32() && init_gdi32() && init_user32() && init_advapi32() && init_comdlg32() && init_shell32() && init_version() && init_comctl32(); } BOOL APIENTRY DllMain(HINSTANCE instance, DWORD reason, BOOL load_static) diff --git a/apilibs/settings.reg b/apilibs/settings.reg index 2c862cf..61d6add 100755 --- a/apilibs/settings.reg +++ b/apilibs/settings.reg @@ -25,12 +25,14 @@ REGEDIT4 ;-AbiWord "*\\BIN\\ABIWORD.EXE"="VISTA" ;-Flash Player -"*\\NPSWF32.DLL"="WINXP" -"%WINDIR%\\SYSTEM\\MACROMED\\FLASH\\FLASH10*.OCX"="WINXP" +"*\\NPSWF32.DLL"="NT2K" +"%WINDIR%\\SYSTEM\\MACROMED\\FLASH\\FLASH10*.OCX"="NT2K" ;-GTA:SA "*\\GTA_SA.EXE"="NOHEAP" ;-Rally Championship '99 "*\\RAL.EXE"="NOHEAP" +;-Wizard101 +"*\\BIN\\WIZARDGRAPHICALCLIENT.EXE"="NOHEAP" ;-MPC Home Cinema Setup "*\\MPC-HOMECINEMA.1.*.EXE"="WINXP" diff --git a/common/version.h b/common/version.h index 4075e97..dfc2ce0 100755 --- a/common/version.h +++ b/common/version.h @@ -22,9 +22,9 @@ #ifndef __VERSION_H #define __VERSION_H -#define VERSION_STR "4.5 RC 1" -#define VERSION_CODE 0x0405000B -#define RCVERSION 4, 5, 1, 1 -#define _RCVERSION_ "4, 5, 1, 1" +#define VERSION_STR "4.5 RC 4" +#define VERSION_CODE 0x0405000E +#define RCVERSION 4, 5, 1, 4 +#define _RCVERSION_ "4, 5, 1, 4" #endif diff --git a/core/internals.cpp b/core/internals.cpp index 62ef105..b63a75e 100755 --- a/core/internals.cpp +++ b/core/internals.cpp @@ -250,7 +250,7 @@ static IMTE*** find_mod_table() IMTE*** ret; - DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, (LPSTR)23), 0x20, pat, pat_len, pat_name); + DWORD* res = find_unique_pattern((void*) GetK32OrdinalAddress(23), 0x20, pat, pat_len, pat_name); ret = (IMTE***)*res; DBGPRINTF(("%s @ 0x%08x\n", pat_name, ret)); @@ -265,7 +265,7 @@ static MRFromHLib_t find_MRFromHLib() MRFromHLib_t ret; - DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, (LPSTR)23), 0x20, pat, pat_len, pat_name); + DWORD* res = find_unique_pattern((void*) GetK32OrdinalAddress(23), 0x20, pat, pat_len, pat_name); if (!res) return NULL; @@ -441,9 +441,9 @@ int internals_init() DBGPRINTF(("internals_init()\n")); h_kernel32 = GetModuleHandle("kernel32"); ppmteModTable = find_mod_table(); + MRFromHLib = find_MRFromHLib(); krnl32lock = find_krnl32lock(); pppdbCur = find_curPDB(); - MRFromHLib = find_MRFromHLib(); pimteMax = find_pimteMax(); TIDtoTDB = find_TIDtoTDB(); MRLoadTree = find_MRLoadTree(); @@ -454,7 +454,7 @@ int internals_init() is_winme = (GetVersion() == 0xc0005a04); bool modinit_rslt = ModuleInitializer_init(); - if (!h_kernel32 || !ppmteModTable || !krnl32lock || !pppdbCur || !MRFromHLib + if (!h_kernel32 || !ppmteModTable || !MRFromHLib || !krnl32lock || !pppdbCur || !pimteMax || !TIDtoTDB || !MRLoadTree || !FreeLibTree || !FreeLibRemove || !AllocHandle || !instdir_rslt || !modinit_rslt) diff --git a/core/resolver.cpp b/core/resolver.cpp index 2eb1b22..75b44e0 100755 --- a/core/resolver.cpp +++ b/core/resolver.cpp @@ -659,8 +659,8 @@ static BOOL WINAPI IsKnownKexDLL(char* name, const char* ext) { LONG res; DWORD type; - char path[MAX_PATH]; - DWORD size = sizeof(path); + char new_path[MAX_PATH]; + DWORD size = sizeof(new_path); if (ext && strcmp(ext, "DLL") != 0) return FALSE; @@ -670,12 +670,33 @@ static BOOL WINAPI IsKnownKexDLL(char* name, const char* ext) if (are_extensions_enabled()) { - //workaround windows bug - int pos = strlen(name) - 4; - if (pos > 0 && name[pos] == '.') - name[pos] = '\0'; + int len = strlen(name); - res = RegQueryValueEx(known_dlls_key, name, NULL, &type, (BYTE*) path, &size); + //workaround windows bug + int pos = len - 4; + if (pos > 0 && name[pos] == '.') + { + name[pos] = '\0'; + len = pos; + } + + char* file = name; + + //find where directory part ends + while (len > 0) + { + len--; + if (name[len] == '\\') + { + file = name + len + 1; + break; + } + } + + if (!len || (len == system_path_len && !strncmp(name, system_path, len))) + res = RegQueryValueEx(known_dlls_key, file, NULL, &type, (BYTE*) new_path, &size); + else + res = ERROR_INVALID_FUNCTION; } else res = ERROR_INVALID_FUNCTION; @@ -683,7 +704,7 @@ static BOOL WINAPI IsKnownKexDLL(char* name, const char* ext) if (res == ERROR_SUCCESS && type == REG_SZ) { memcpy(name, (const char*) kernelex_dir, kernelex_dir.length()); - memcpy(name + kernelex_dir.length(), path, size); + memcpy(name + kernelex_dir.length(), new_path, size); return TRUE; } else @@ -725,13 +746,31 @@ static BOOL WINAPI KexResourceCheck(DWORD un0, DWORD un1, DWORD un2, DWORD* pNam return GetOrdinal(un0, un1, un2, pNameOrId, pResult, un3); } +/** Retrieves address of kernel32 function exported by ordinal. + * @param [in] ord function ordinal number + * @return function address or NULL if not found + */ +PROC WINAPI GetK32OrdinalAddress(WORD wOrd) +{ + IMAGE_DOS_HEADER* dosh = (IMAGE_DOS_HEADER*) h_kernel32; + IMAGE_NT_HEADERS* nth = (IMAGE_NT_HEADERS*)((LONG)dosh + dosh->e_lfanew); + return OriExportFromOrdinal(nth, wOrd); +} + +/** GetProcAddress variant used to bypass CORE's resolver hook + * (get real procedure address not overridden one). + * @param [in] hModule module handle + * @param [in] lpProcName procedure name or ordinal number (high word zeroed) + * @return function address or NULL if not found + */ PROC WINAPI iGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { - IMAGE_DOS_HEADER* dos_hdr; - IMAGE_NT_HEADERS* nt_hdr; + DBGASSERT(MRFromHLib != NULL); + DBGASSERT(ppmteModTable != NULL); - dos_hdr = (IMAGE_DOS_HEADER*) hModule; - nt_hdr = (IMAGE_NT_HEADERS*)((int)dos_hdr + dos_hdr->e_lfanew); + MODREF* mr = MRFromHLib(hModule); + IMTE* imte = (*ppmteModTable)[mr->mteIndex]; + IMAGE_NT_HEADERS* nt_hdr = imte->pNTHdr; if ((DWORD)lpProcName < 0x10000) return OriExportFromOrdinal(nt_hdr, LOWORD(lpProcName)); diff --git a/core/resolver.h b/core/resolver.h index 47cfb4b..3b4654e 100755 --- a/core/resolver.h +++ b/core/resolver.h @@ -90,6 +90,7 @@ extern LONG old_jtab[]; bool are_extensions_enabled(); bool are_extensions_enabled_module(const char* path); DWORD encode_address(DWORD addr, const ApiLibrary* apilib); +PROC WINAPI GetK32OrdinalAddress(WORD wOrd); PROC WINAPI iGetProcAddress(HMODULE hModule, LPCSTR lpProcName); PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, BOOL is_static, WORD ordinal); PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, BOOL is_static, WORD hint, LPCSTR name); diff --git a/util/prep/prep.cpp b/util/prep/prep.cpp index 4b731c5..421ec68 100755 --- a/util/prep/prep.cpp +++ b/util/prep/prep.cpp @@ -294,12 +294,14 @@ void FileDeclParser::parse_forward_to_unicows(const string& line) throw(exceptio int FileDeclParser::find_matching_export(const string& s) { int count = 0; + size_t pos; //try named exports first vector::iterator itn = exports_named.begin(); while (itn != exports_named.end()) { - if (s.find(itn->source_name) != string::npos) + pos = s.find(itn->source_name); + if (pos != string::npos && is_full_decl(s, pos, itn->source_name.length())) count++; itn++; } @@ -307,13 +309,23 @@ int FileDeclParser::find_matching_export(const string& s) vector::iterator ito = exports_ordinal.begin(); while (ito != exports_ordinal.end()) { - if (s.find(ito->source_name) != string::npos) + pos = s.find(ito->source_name); + if (pos != string::npos && is_full_decl(s, pos, ito->source_name.length())) count++; ito++; } return count; } +bool FileDeclParser::is_full_decl(const string& s, int beg, int len) +{ + if (beg > 0 && (isalnum(s[beg-1]) || s[beg-1] == '_')) + return false; + if (beg + len < s.length() && (isalnum(s[beg+len]) || s[beg+len] == '_')) + return false; + return true; +} + void FileDeclParser::prefilter() throw(exception) { //erase C-style comments diff --git a/util/prep/prep.h b/util/prep/prep.h index 5bd153a..bcf7d6f 100755 --- a/util/prep/prep.h +++ b/util/prep/prep.h @@ -101,6 +101,9 @@ protected: void parse_forward_to_unicows(const string& line) throw(exception); int find_matching_export(const string& s); void filter_declaration(string& s); + +private: + bool is_full_decl(const string& s, int beg, int len); }; //////////////////////////////////////////////////////////////////////////