Commit 489d87d1 authored by Alexandre Julliard's avatar Alexandre Julliard

kernel32: Renamed the kernel directory to kernel32.

Also get rid of the kernel/messages subdirectory.
parent 6406f60f
......@@ -1461,7 +1461,7 @@ AH_TOP([#define __WINE_CONFIG_H])
WINE_CONFIG_EXTRA_DIR(dlls/gdi/enhmfdrv)
WINE_CONFIG_EXTRA_DIR(dlls/gdi/mfdrv)
WINE_CONFIG_EXTRA_DIR(dlls/kernel/messages)
WINE_CONFIG_EXTRA_DIR(dlls/kernel/nls)
WINE_CONFIG_EXTRA_DIR(dlls/user/resources)
WINE_CONFIG_EXTRA_DIR(dlls/wineps.drv/data)
WINE_CONFIG_EXTRA_DIR(include/wine)
......@@ -1575,8 +1575,8 @@ dlls/inseng/Makefile
dlls/iphlpapi/Makefile
dlls/iphlpapi/tests/Makefile
dlls/itss/Makefile
dlls/kernel/Makefile
dlls/kernel/tests/Makefile
dlls/kernel32/Makefile
dlls/kernel32/tests/Makefile
dlls/localspl/Makefile
dlls/lz32/Makefile
dlls/lz32/tests/Makefile
......
......@@ -18,7 +18,6 @@
/keyboard.drv16
/krnl386.exe16
/libgdi32.def
/libkernel32.def
/libuser32.def
/libwinspool.def
/lzexpand.dll16
......@@ -100,7 +99,7 @@ icmp/libicmp.def
imagehlp/libimagehlp.def
imm32/libimm32.def
iphlpapi/libiphlpapi.def
kernel/libkernel32.def
kernel32/libkernel32.def
lz32/liblz32.def
mapi32/libmapi32.def
mlang/libmlang.def
......
......@@ -80,7 +80,7 @@ BASEDIRS = \
inseng \
iphlpapi \
itss \
kernel \
kernel32 \
localspl \
lz32 \
mapi32 \
......@@ -227,7 +227,7 @@ TESTSUBDIRS = \
hlink/tests \
infosoft/tests \
iphlpapi/tests \
kernel/tests \
kernel32/tests \
lz32/tests \
mapi32/tests \
mlang/tests \
......@@ -337,7 +337,6 @@ SYMLINKS_SO = \
@WIN16_FILES@ \
gdi32.dll.so \
joystick.drv.so \
kernel32.dll.so \
user32.dll.so \
winealsa.drv.so \
winearts.drv.so \
......@@ -366,9 +365,6 @@ gdi32.dll.so: gdi/gdi32.dll.so
joystick.drv.so: winmm/joystick/joystick.drv.so
$(RM) $@ && $(LN_S) winmm/joystick/joystick.drv.so $@
kernel32.dll.so: kernel/kernel32.dll.so
$(RM) $@ && $(LN_S) kernel/kernel32.dll.so $@
user32.dll.so: user/user32.dll.so
$(RM) $@ && $(LN_S) user/user32.dll.so $@
......@@ -485,7 +481,6 @@ STATIC_IMPLIBEXT = $(IMPLIBEXT:def=def.a)
IMPORT_SYMLINKS = \
libgdi32.$(IMPLIBEXT) \
libkernel32.$(IMPLIBEXT) \
libuser32.$(IMPLIBEXT) \
libwinspool.$(IMPLIBEXT)
......@@ -541,7 +536,7 @@ IMPORT_LIBS = \
imagehlp/libimagehlp.$(IMPLIBEXT) \
imm32/libimm32.$(IMPLIBEXT) \
iphlpapi/libiphlpapi.$(IMPLIBEXT) \
kernel/libkernel32.$(IMPLIBEXT) \
kernel32/libkernel32.$(IMPLIBEXT) \
lz32/liblz32.$(IMPLIBEXT) \
mapi32/libmapi32.$(IMPLIBEXT) \
mlang/libmlang.$(IMPLIBEXT) \
......@@ -749,8 +744,8 @@ imm32/libimm32.$(IMPLIBEXT): imm32/imm32.spec $(WINEBUILD)
iphlpapi/libiphlpapi.$(IMPLIBEXT): iphlpapi/iphlpapi.spec $(WINEBUILD)
@cd iphlpapi && $(MAKE) libiphlpapi.$(IMPLIBEXT)
kernel/libkernel32.$(IMPLIBEXT): kernel/kernel32.spec $(WINEBUILD)
@cd kernel && $(MAKE) libkernel32.$(IMPLIBEXT)
kernel32/libkernel32.$(IMPLIBEXT): kernel32/kernel32.spec $(WINEBUILD)
@cd kernel32 && $(MAKE) libkernel32.$(IMPLIBEXT)
lz32/liblz32.$(IMPLIBEXT): lz32/lz32.spec $(WINEBUILD)
@cd lz32 && $(MAKE) liblz32.$(IMPLIBEXT)
......@@ -971,9 +966,6 @@ wtsapi32/libwtsapi32.$(IMPLIBEXT): wtsapi32/wtsapi32.spec $(WINEBUILD)
libgdi32.$(IMPLIBEXT): gdi/libgdi32.$(IMPLIBEXT)
$(RM) $@ && $(LN_S) gdi/libgdi32.$(IMPLIBEXT) $@
libkernel32.$(IMPLIBEXT): kernel/libkernel32.$(IMPLIBEXT)
$(RM) $@ && $(LN_S) kernel/libkernel32.$(IMPLIBEXT) $@
libuser32.$(IMPLIBEXT): user/libuser32.$(IMPLIBEXT)
$(RM) $@ && $(LN_S) user/libuser32.$(IMPLIBEXT) $@
......@@ -987,7 +979,6 @@ $(INSTALLSUBDIRS:%=%/__install__) $(INSTALLSUBDIRS:%=%/__install-lib__): $(IMPOR
gdi/gdi32.dll.so: gdi
winmm/joystick/joystick.drv.so: winmm/joystick
kernel/kernel32.dll.so: kernel
user/user32.dll.so: user
winmm/winealsa/winealsa.drv.so: winmm/winealsa
winmm/winearts/winearts.drv.so: winmm/winearts
......
/*
* Unit test suite for environment functions.
*
* Copyright 2002 Dmitry Timoshkov
*
* 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
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
static void test_GetSetEnvironmentVariableA(void)
{
char buf[256];
BOOL ret;
DWORD ret_size;
static const char name[] = "SomeWildName";
static const char name_cased[] = "sOMEwILDnAME";
static const char value[] = "SomeWildValue";
ret = SetEnvironmentVariableA(name, value);
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableA, GetLastError=%ld\n",
GetLastError());
/* Try to retrieve the environment variable we just set */
ret_size = GetEnvironmentVariableA(name, NULL, 0);
ok(ret_size == strlen(value) + 1,
"should return length with terminating 0 ret_size=%ld\n", ret_size);
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value));
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
ok(ret_size == strlen(value) + 1,
"should return length with terminating 0 ret_size=%ld\n", ret_size);
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == strlen(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name_cased, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == strlen(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
/* Remove that environment variable */
ret = SetEnvironmentVariableA(name_cased, NULL);
ok(ret == TRUE, "should erase existing variable\n");
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
/* Check behavior of SetEnvironmentVariableA(name, "") */
ret = SetEnvironmentVariableA(name, value);
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableA, GetLastError=%ld\n",
GetLastError());
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name_cased, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == strlen(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
ret = SetEnvironmentVariableA(name_cased, "");
ok(ret == TRUE,
"should not fail with empty value but GetLastError=%ld\n", GetLastError());
lstrcpyA(buf, "foo");
SetLastError(0);
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
ok(ret_size == 0 &&
((GetLastError() == 0 && lstrcmpA(buf, "") == 0) ||
(GetLastError() == ERROR_ENVVAR_NOT_FOUND)),
"%s should be set to \"\" (NT) or removed (Win9x) but ret_size=%ld GetLastError=%ld and buf=%s\n",
name, ret_size, GetLastError(), buf);
/* Test the limits */
ret_size = GetEnvironmentVariableA(NULL, NULL, 0);
ok(ret_size == 0 && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret_size = GetEnvironmentVariableA(NULL, buf, lstrlenA(value) + 1);
ok(ret_size == 0 && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret_size = GetEnvironmentVariableA("", buf, lstrlenA(value) + 1);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
}
static void test_GetSetEnvironmentVariableW(void)
{
WCHAR buf[256];
BOOL ret;
DWORD ret_size;
static const WCHAR name[] = {'S','o','m','e','W','i','l','d','N','a','m','e',0};
static const WCHAR value[] = {'S','o','m','e','W','i','l','d','V','a','l','u','e',0};
static const WCHAR name_cased[] = {'s','O','M','E','w','I','L','D','n','A','M','E',0};
static const WCHAR empty_strW[] = { 0 };
static const WCHAR fooW[] = {'f','o','o',0};
ret = SetEnvironmentVariableW(name, value);
if (ret == FALSE && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
{
/* Must be Win9x which doesn't support the Unicode functions */
return;
}
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableW, GetLastError=%ld\n",
GetLastError());
/* Try to retrieve the environment variable we just set */
ret_size = GetEnvironmentVariableW(name, NULL, 0);
ok(ret_size == lstrlenW(value) + 1,
"should return length with terminating 0 ret_size=%ld\n",
ret_size);
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value));
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(ret_size == lstrlenW(value) + 1,
"should return length with terminating 0 ret_size=%ld\n", ret_size);
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == lstrlenW(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name_cased, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == lstrlenW(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
/* Remove that environment variable */
ret = SetEnvironmentVariableW(name_cased, NULL);
ok(ret == TRUE, "should erase existing variable\n");
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
/* Check behavior of SetEnvironmentVariableW(name, "") */
ret = SetEnvironmentVariableW(name, value);
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableW, GetLastError=%ld\n",
GetLastError());
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == lstrlenW(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
ret = SetEnvironmentVariableW(name_cased, empty_strW);
ok(ret == TRUE, "should not fail with empty value but GetLastError=%ld\n", GetLastError());
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ok(lstrcmpW(buf, empty_strW) == 0, "should copy an empty string\n");
/* Test the limits */
ret_size = GetEnvironmentVariableW(NULL, NULL, 0);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret_size = GetEnvironmentVariableW(NULL, buf, lstrlenW(value) + 1);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret = SetEnvironmentVariableW(NULL, NULL);
ok(ret == FALSE && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
"should fail with NULL, NULL but ret=%d and GetLastError=%ld\n",
ret, GetLastError());
}
static void test_ExpandEnvironmentStringsA(void)
{
char buf[256], buf1[256], buf2[0x8000];
DWORD ret_size, ret_size1;
/* test a large destination size */
strcpy(buf, "12345");
ret_size = ExpandEnvironmentStringsA(buf, buf2, sizeof(buf2));
ok(!strcmp(buf, buf2), "ExpandEnvironmentStrings failed %s vs %s. ret_size = %ld\n", buf, buf2, ret_size);
ret_size1 = GetWindowsDirectoryA(buf1,256);
ok ((ret_size1 >0) && (ret_size1<256), "GetWindowsDirectory Failed\n");
ret_size = ExpandEnvironmentStringsA("%SystemRoot%",buf,sizeof(buf));
if (ERROR_ENVVAR_NOT_FOUND == GetLastError())
return;
ok(!strcmp(buf, buf1), "ExpandEnvironmentStrings failed %s vs %s. ret_size = %ld\n", buf, buf1, ret_size);
}
START_TEST(environ)
{
test_GetSetEnvironmentVariableA();
test_GetSetEnvironmentVariableW();
test_ExpandEnvironmentStringsA();
}
/* Unit test suite for FormatMessageA
*
* Copyright 2002 Mike McCormack for CodeWeavers
*
* 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
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
/* #define ok(cond,failstr) if(!(cond)) {printf("line %d : %s\n",__LINE__,failstr);exit(1);} */
static DWORD doit(DWORD flags, LPCVOID src, DWORD msg_id, DWORD lang_id,
LPSTR out, DWORD outsize, ... )
{
va_list list;
DWORD r;
va_start(list, outsize);
r = FormatMessageA(flags, src, msg_id,
lang_id, out, outsize, &list);
va_end(list);
return r;
}
static void test_message_from_string(void)
{
CHAR out[0x100] = {0};
DWORD r;
static const WCHAR szwTest[] = { 't','e','s','t',0};
/* the basics */
r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0,
0, out, sizeof(out)/sizeof(CHAR),NULL);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* using the format feature */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0,
0, out, sizeof(out)/sizeof(CHAR), "test");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* no format */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
0, out, sizeof(out)/sizeof(CHAR), "test");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* two pieces */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%2", 0,
0, out, sizeof(out)/sizeof(CHAR), "te","st");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* three pieces */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%3%2%1", 0,
0, out, sizeof(out)/sizeof(CHAR), "t","s","e");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* s doesn't seem to work in format strings */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%!s!", 0,
0, out, sizeof(out)/sizeof(CHAR), "test");
ok(!strcmp("!s!", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%ld\n",r);
/* S is unicode */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!S!", 0,
0, out, sizeof(out)/sizeof(CHAR), szwTest);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* as characters */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!c!%2!c!%3!c!%1!c!", 0,
0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* some numbers */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!d!%2!d!%3!d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 1,2,3);
ok(!strcmp("123", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%ld\n",r);
/* a single digit with some spacing */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 1);
ok(!strcmp(" 1", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a single digit, left justified */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 1);
ok(!strcmp("1 ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* two digit decimal number */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp(" 11", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a hex number */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4x!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp(" b", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a hex number, upper case */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp(" B", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a hex number, upper case, left justified */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4X!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp("B ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a long hex number, upper case */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
ok(!strcmp(" 1AB", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* two percent... */
r = doit(FORMAT_MESSAGE_FROM_STRING, " %%%% ", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" %% ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* periods are special cases */
r = doit(FORMAT_MESSAGE_FROM_STRING, " %.%. %1!d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
ok(!strcmp(" .. 427", out),"failed out=[%s]\n",out);
ok(r==7,"failed: r=%ld\n",r);
/* %0 ends the line */
r = doit(FORMAT_MESSAGE_FROM_STRING, "test%0test", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* %! prints an exclaimation */
r = doit(FORMAT_MESSAGE_FROM_STRING, "yah%!%0 ", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("yah!", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* %space */
r = doit(FORMAT_MESSAGE_FROM_STRING, "% % ", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "\r", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("\r\n", out),"failed out=[%s]\n",out);
ok(r==2,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "\r\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("\r\n\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* change of pace... test the low byte of dwflags */
/* line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi ", out) || !strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==3 || r==4,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi ", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==1,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==2,"failed: r=%ld\n",r);
}
START_TEST(format_msg)
{
test_message_from_string();
}
/*
* Unit tests for module/DLL/library API
*
* Copyright (c) 2004 Eric Pouech
*
* 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
*/
#include "wine/test.h"
#include <windows.h>
static BOOL is_unicode_enabled = TRUE;
static BOOL cmpStrAW(const char* a, const WCHAR* b, DWORD lenA, DWORD lenB)
{
WCHAR aw[1024];
DWORD len = MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
a, lenA, aw, sizeof(aw) / sizeof(aw[0]) );
if (len != lenB) return FALSE;
return memcmp(aw, b, len * sizeof(WCHAR)) == 0;
}
static void testGetModuleFileName(const char* name)
{
HMODULE hMod;
char bufA[MAX_PATH];
WCHAR bufW[MAX_PATH];
DWORD len1A, len1W = 0, len2A, len2W = 0;
hMod = (name) ? GetModuleHandle(name) : NULL;
/* first test, with enough space in buffer */
memset(bufA, '-', sizeof(bufA));
len1A = GetModuleFileNameA(hMod, bufA, sizeof(bufA));
ok(len1A > 0, "Getting module filename for handle %p\n", hMod);
if (is_unicode_enabled)
{
memset(bufW, '-', sizeof(bufW));
len1W = GetModuleFileNameW(hMod, bufW, sizeof(bufW) / sizeof(WCHAR));
ok(len1W > 0, "Getting module filename for handle %p\n", hMod);
}
ok(len1A == strlen(bufA), "Unexpected length of GetModuleFilenameA (%ld/%d)\n", len1A, lstrlenA(bufA));
if (is_unicode_enabled)
{
ok(len1W == lstrlenW(bufW), "Unexpected length of GetModuleFilenameW (%ld/%d)\n", len1W, lstrlenW(bufW));
ok(cmpStrAW(bufA, bufW, len1A, len1W), "Comparing GetModuleFilenameAW results\n");
}
/* second test with a buffer too small */
memset(bufA, '-', sizeof(bufA));
len2A = GetModuleFileNameA(hMod, bufA, len1A / 2);
ok(len2A > 0, "Getting module filename for handle %p\n", hMod);
if (is_unicode_enabled)
{
memset(bufW, '-', sizeof(bufW));
len2W = GetModuleFileNameW(hMod, bufW, len1W / 2);
ok(len2W > 0, "Getting module filename for handle %p\n", hMod);
ok(cmpStrAW(bufA, bufW, len2A, len2W), "Comparing GetModuleFilenameAW results with buffer too small\n" );
ok(len1W / 2 == len2W, "Correct length in GetModuleFilenameW with buffer too small (%ld/%ld)\n", len1W / 2, len2W);
}
ok(len1A / 2 == len2A ||
len1A / 2 == len2A + 1, /* Win9x */
"Correct length in GetModuleFilenameA with buffer too small (%ld/%ld)\n", len1A / 2, len2A);
}
static void testGetModuleFileName_Wrong(void)
{
char bufA[MAX_PATH];
WCHAR bufW[MAX_PATH];
/* test wrong handle */
if (is_unicode_enabled)
{
bufW[0] = '*';
ok(GetModuleFileNameW((void*)0xffffffff, bufW, sizeof(bufW) / sizeof(WCHAR)) == 0, "Unexpected success in module handle\n");
ok(bufW[0] == '*', "When failing, buffer shouldn't be written to\n");
}
bufA[0] = '*';
ok(GetModuleFileNameA((void*)0xffffffff, bufA, sizeof(bufA)) == 0, "Unexpected success in module handle\n");
ok(bufA[0] == '*' ||
bufA[0] == 0 /* Win9x */,
"When failing, buffer shouldn't be written to\n");
}
static void testLoadLibraryA(void)
{
HMODULE hModule, hModule1;
FARPROC fp;
SetLastError(0xdeadbeef);
hModule = LoadLibraryA("kernel32.dll");
ok( hModule != NULL, "kernel32.dll should be loadable\n");
ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %08lx\n", GetLastError());
fp = GetProcAddress(hModule, "CreateFileA");
ok( fp != NULL, "CreateFileA should be there\n");
ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %08lx\n", GetLastError());
SetLastError(0xdeadbeef);
hModule1 = LoadLibraryA("kernel32 ");
/* Only winNT does this */
if (GetLastError() != ERROR_DLL_NOT_FOUND)
{
ok( hModule1 != NULL, "\"kernel32 \" should be loadable\n");
ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %08lx\n", GetLastError());
ok( hModule == hModule1, "Loaded wrong module\n");
FreeLibrary(hModule1);
}
FreeLibrary(hModule);
}
static void testLoadLibraryA_Wrong(void)
{
HMODULE hModule;
/* Try to load a nonexistent dll */
SetLastError(0xdeadbeef);
hModule = LoadLibraryA("non_ex_pv.dll");
ok( !hModule, "non_ex_pv.dll should be not loadable\n");
ok( GetLastError() == ERROR_MOD_NOT_FOUND || GetLastError() == ERROR_DLL_NOT_FOUND,
"Expected ERROR_MOD_NOT_FOUND or ERROR_DLL_NOT_FOUND (win9x), got %08lx\n", GetLastError());
/* Just in case */
FreeLibrary(hModule);
}
static void testGetProcAddress_Wrong(void)
{
FARPROC fp;
SetLastError(0xdeadbeef);
fp = GetProcAddress(NULL, "non_ex_call");
ok( !fp, "non_ex_call should not be found\n");
ok( GetLastError() == ERROR_PROC_NOT_FOUND || GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_PROC_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %08lx\n", GetLastError());
SetLastError(0xdeadbeef);
fp = GetProcAddress((HMODULE)0xdeadbeef, "non_ex_call");
ok( !fp, "non_ex_call should not be found\n");
ok( GetLastError() == ERROR_MOD_NOT_FOUND || GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %08lx\n", GetLastError());
}
START_TEST(module)
{
WCHAR filenameW[MAX_PATH];
/* Test if we can use GetModuleFileNameW */
SetLastError(0xdeadbeef);
GetModuleFileNameW(NULL, filenameW, MAX_PATH);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
trace("GetModuleFileNameW not existing on this platform, skipping W-calls\n");
is_unicode_enabled = FALSE;
}
testGetModuleFileName(NULL);
testGetModuleFileName("kernel32.dll");
testGetModuleFileName_Wrong();
testLoadLibraryA();
testLoadLibraryA_Wrong();
testGetProcAddress_Wrong();
}
/*
* Unit tests for profile functions
*
* Copyright (c) 2003 Stefan Leichter
*
* 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
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "windows.h"
#define KEY "ProfileInt"
#define SECTION "Test"
#define TESTFILE ".\\testwine.ini"
#define TESTFILE2 ".\\testwine2.ini"
struct _profileInt {
LPCSTR section;
LPCSTR key;
LPCSTR value;
LPCSTR iniFile;
INT defaultVal;
UINT result;
UINT result9x;
};
static void test_profile_int(void)
{
struct _profileInt profileInt[]={
{ NULL, NULL, NULL, NULL, 70, 0 , 0}, /* 0 */
{ NULL, NULL, NULL, TESTFILE, -1, 4294967295U, 0},
{ NULL, NULL, NULL, TESTFILE, 1, 1 , 0},
{ SECTION, NULL, NULL, TESTFILE, -1, 4294967295U, 0},
{ SECTION, NULL, NULL, TESTFILE, 1, 1 , 0},
{ NULL, KEY, NULL, TESTFILE, -1, 4294967295U, 0}, /* 5 */
{ NULL, KEY, NULL, TESTFILE, 1, 1 , 0},
{ SECTION, KEY, NULL, TESTFILE, -1, 4294967295U, 4294967295U},
{ SECTION, KEY, NULL, TESTFILE, 1, 1 , 1},
{ SECTION, KEY, "-1", TESTFILE, -1, 4294967295U, 4294967295U},
{ SECTION, KEY, "-1", TESTFILE, 1, 4294967295U, 4294967295U}, /* 10 */
{ SECTION, KEY, "1", TESTFILE, -1, 1 , 1},
{ SECTION, KEY, "1", TESTFILE, 1, 1 , 1},
{ SECTION, KEY, "+1", TESTFILE, -1, 1 , 0},
{ SECTION, KEY, "+1", TESTFILE, 1, 1 , 0},
{ SECTION, KEY, "4294967296", TESTFILE, -1, 0 , 0}, /* 15 */
{ SECTION, KEY, "4294967296", TESTFILE, 1, 0 , 0},
{ SECTION, KEY, "4294967297", TESTFILE, -1, 1 , 1},
{ SECTION, KEY, "4294967297", TESTFILE, 1, 1 , 1},
{ SECTION, KEY, "-4294967297", TESTFILE, -1, 4294967295U, 4294967295U},
{ SECTION, KEY, "-4294967297", TESTFILE, 1, 4294967295U, 4294967295U}, /* 20 */
{ SECTION, KEY, "42A94967297", TESTFILE, -1, 42 , 42},
{ SECTION, KEY, "42A94967297", TESTFILE, 1, 42 , 42},
{ SECTION, KEY, "B4294967297", TESTFILE, -1, 0 , 0},
{ SECTION, KEY, "B4294967297", TESTFILE, 1, 0 , 0},
};
int i, num_test = (sizeof(profileInt)/sizeof(struct _profileInt));
UINT res;
DeleteFileA( TESTFILE);
for (i=0; i < num_test; i++) {
if (profileInt[i].value)
WritePrivateProfileStringA(SECTION, KEY, profileInt[i].value,
profileInt[i].iniFile);
res = GetPrivateProfileIntA(profileInt[i].section, profileInt[i].key,
profileInt[i].defaultVal, profileInt[i].iniFile);
ok((res == profileInt[i].result) || (res == profileInt[i].result9x),
"test<%02d>: ret<%010u> exp<%010u><%010u>\n",
i, res, profileInt[i].result, profileInt[i].result9x);
}
DeleteFileA( TESTFILE);
}
static void test_profile_string(void)
{
HANDLE h;
int ret;
DWORD count;
char buf[100];
char *p;
/* test that lines without an '=' will not be enumerated */
/* in the case below, name2 is a key while name3 is not. */
char content[]="[s]\r\nname1=val1\r\nname2=\r\nname3\r\nname4=val4\r\n";
DeleteFileA( TESTFILE2);
h = CreateFileA( TESTFILE2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", TESTFILE2);
if( h == INVALID_HANDLE_VALUE) return;
WriteFile( h, content, sizeof(content), &count, NULL);
CloseHandle( h);
/* enumerate the keys */
ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
TESTFILE2);
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
p[-1] = ',';
/* and test */
ok( ret == 18 && !strcmp( buf, "name1,name2,name4"), "wrong keys returned(%d): %s\n", ret,
buf);
ret=GetPrivateProfileSectionA("s", buf, sizeof(buf), TESTFILE2);
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
p[-1] = ',';
/* and test */
ok( ret == 35 && !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned(%d): %s\n",
ret, buf);
/* add a new key to test that the file is quite usable */
WritePrivateProfileStringA( "s", "name5", "val5", TESTFILE2);
ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
TESTFILE2);
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
p[-1] = ',';
ok( ret == 24 && !strcmp( buf, "name1,name2,name4,name5"), "wrong keys returned(%d): %s\n",
ret, buf);
DeleteFileA( TESTFILE2);
}
static void test_profile_sections(void)
{
HANDLE h;
int ret;
DWORD count;
char buf[100];
WCHAR bufW[100];
static const char content[]="[section1]\r\n[section2]\r\n[section3]\r\n";
static const char testfile3[]=".\\testwine3.ini";
static const WCHAR testfile3W[]={ '.','\\','t','e','s','t','w','i','n','e','3','.','i','n','i',0 };
DeleteFileA( testfile3 );
h = CreateFileA( testfile3, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", testfile3);
if( h == INVALID_HANDLE_VALUE) return;
WriteFile( h, content, sizeof(content), &count, NULL);
CloseHandle( h);
/* Test with sufficiently large buffer */
ret = GetPrivateProfileSectionNamesA( buf, 29, testfile3 );
ok( ret == 27, "expected return size 27, got %d\n", ret );
ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
/* Test with exactly fitting buffer */
ret = GetPrivateProfileSectionNamesA( buf, 28, testfile3 );
ok( ret == 26, "expected return size 26, got %d\n", ret );
ok( buf[ret+1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
/* Test with a buffer too small */
ret = GetPrivateProfileSectionNamesA( buf, 27, testfile3 );
ok( ret == 25, "expected return size 25, got %d\n", ret );
ok( buf[ret+1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
/* Test with sufficiently large buffer */
ret = GetPrivateProfileSectionNamesW( bufW, 29, testfile3W );
ok( ret == 27, "expected return size 27, got %d\n", ret );
ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
/* Test with exactly fitting buffer */
ret = GetPrivateProfileSectionNamesW( bufW, 28, testfile3W );
ok( ret == 26, "expected return size 26, got %d\n", ret );
ok( buf[ret+1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
/* Test with a buffer too small */
ret = GetPrivateProfileSectionNamesW( bufW, 27, testfile3W );
ok( ret == 25, "expected return size 25, got %d\n", ret );
ok( buf[ret+1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
DeleteFileA( testfile3 );
}
START_TEST(profile)
{
test_profile_int();
test_profile_string();
test_profile_sections();
}
/*
* Synchronization tests
*
* Copyright 2005 Mike McCormack for CodeWeavers
*
* 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
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#include "wine/test.h"
static void test_signalandwait(void)
{
DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
HMODULE kernel32;
DWORD r;
int i;
HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
kernel32 = GetModuleHandle("kernel32");
pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
if (!pSignalObjectAndWait)
return;
/* invalid parameters */
r = pSignalObjectAndWait(NULL, NULL, 0, 0);
if (r == ERROR_INVALID_FUNCTION)
{
trace("SignalObjectAndWait not implemented, skipping tests\n");
return; /* Win98/ME */
}
ok( r == WAIT_FAILED, "should fail\n");
event[0] = CreateEvent(NULL, 0, 0, NULL);
event[1] = CreateEvent(NULL, 1, 1, NULL);
ok( event[0] && event[1], "failed to create event flags\n");
r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
/* valid parameters */
r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* event[0] is now signalled */
r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* event[0] is not signalled */
r = WaitForSingleObject(event[0], 0);
ok( r == WAIT_TIMEOUT, "event was signalled\n");
r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* clear event[1] and check for a timeout */
ok(ResetEvent(event[1]), "failed to clear event[1]\n");
r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
ok( r == WAIT_TIMEOUT, "should timeout\n");
CloseHandle(event[0]);
CloseHandle(event[1]);
/* create the maximum number of events and make sure
* we can wait on that many */
for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
{
maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
ok( maxevents[i] != 0, "should create enough events\n");
}
r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
if (maxevents[i]) CloseHandle(maxevents[i]);
/* semaphores */
semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
r = ReleaseSemaphore(semaphore[0],1,NULL);
ok( r == FALSE, "should fail\n");
r = ReleaseSemaphore(semaphore[1],1,NULL);
ok( r == TRUE, "should succeed\n");
CloseHandle(semaphore[0]);
CloseHandle(semaphore[1]);
/* try a registry key */
file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
r = pSignalObjectAndWait(file, file, 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
CloseHandle(file);
}
static void test_mutex(void)
{
DWORD wait_ret;
BOOL ret;
HANDLE hCreated;
HANDLE hOpened;
hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
ok(hCreated != NULL, "CreateMutex failed with error %ld\n", GetLastError());
wait_ret = WaitForSingleObject(hCreated, INFINITE);
ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08lx\n", wait_ret);
/* yes, opening with just READ_CONTROL access allows us to successfully
* call ReleaseMutex */
hOpened = OpenMutex(READ_CONTROL, FALSE, "WineTestMutex");
ok(hOpened != NULL, "OpenMutex failed with error %ld\n", GetLastError());
ret = ReleaseMutex(hOpened);
todo_wine ok(ret, "ReleaseMutex failed with error %ld\n", GetLastError());
ret = ReleaseMutex(hCreated);
todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
"ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %ld\n", GetLastError());
CloseHandle(hOpened);
CloseHandle(hCreated);
}
START_TEST(sync)
{
test_signalandwait();
test_mutex();
}
/*
* Unit test suite for version functions
*
* Copyright 2006 Robert Shearman
*
* 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
*/
#include <assert.h>
#include "wine/test.h"
#include "winbase.h"
static BOOL (WINAPI * pVerifyVersionInfoA)(LPOSVERSIONINFOEXA, DWORD, DWORDLONG);
static ULONGLONG (WINAPI * pVerSetConditionMask)(ULONGLONG, DWORD, BYTE);
#define KERNEL32_GET_PROC(func) \
p##func = (void *)GetProcAddress(hKernel32, #func); \
if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func);
static void init_function_pointers(void)
{
HMODULE hKernel32;
pVerifyVersionInfoA = NULL;
pVerSetConditionMask = NULL;
hKernel32 = GetModuleHandleA("kernel32.dll");
assert(hKernel32);
KERNEL32_GET_PROC(VerifyVersionInfoA);
KERNEL32_GET_PROC(VerSetConditionMask);
}
START_TEST(version)
{
OSVERSIONINFOEX info = { sizeof(info) };
BOOL ret;
init_function_pointers();
if(!pVerifyVersionInfoA || !pVerSetConditionMask) return;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION,
pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
ret = pVerifyVersionInfoA(&info, VER_BUILDNUMBER | VER_MAJORVERSION |
VER_MINORVERSION/* | VER_PLATFORMID | VER_SERVICEPACKMAJOR |
VER_SERVICEPACKMINOR | VER_SUITENAME | VER_PRODUCT_TYPE */,
pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL));
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %ld\n", GetLastError());
/* tests special handling of VER_SUITENAME */
ret = pVerifyVersionInfoA(&info, VER_SUITENAME,
pVerSetConditionMask(0, VER_SUITENAME, VER_AND));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
ret = pVerifyVersionInfoA(&info, VER_SUITENAME,
pVerSetConditionMask(0, VER_SUITENAME, VER_OR));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
/* test handling of version numbers */
/* v3.10 is always less than v4.x even
* if the minor version is tested */
info.dwMajorVersion = 3;
info.dwMinorVersion = 10;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
VER_MAJORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
info.dwMinorVersion = 0;
info.wServicePackMajor = 10;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
VER_MAJORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
info.wServicePackMajor = 0;
info.wServicePackMinor = 10;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
VER_MAJORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.wServicePackMinor++;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.wServicePackMajor--;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.wServicePackMajor--;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.wServicePackMajor++;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.wServicePackMajor++;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_LESS_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.wServicePackMajor--;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL));
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %ld\n", GetLastError());
/* test the failure hierarchy for the four version fields */
GetVersionEx((OSVERSIONINFO *)&info);
info.wServicePackMajor++;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.dwMinorVersion++;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.dwMajorVersion++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %ld\n", GetLastError());
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
GetVersionEx((OSVERSIONINFO *)&info);
info.dwBuildNumber++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %ld\n", GetLastError());
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
/* test bad dwOSVersionInfoSize */
GetVersionEx((OSVERSIONINFO *)&info);
info.dwOSVersionInfoSize = 0;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
}
/*
* Misc Toolhelp functions
*
* Copyright 1996 Marcus Meissner
*
* 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
*/
#include "config.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <ctype.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "winerror.h"
#include "wine/winbase16.h"
#include "toolhelp.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(toolhelp);
/* FIXME: to make this work, we have to call back all these registered
* functions from all over the WINE code. Someone with more knowledge than
* me please do that. -Marcus
*/
static struct notify
{
HTASK16 htask;
FARPROC16 lpfnCallback;
WORD wFlags;
} *notifys = NULL;
static int nrofnotifys = 0;
static FARPROC16 HookNotify = NULL;
/***********************************************************************
* TaskFindHandle (TOOLHELP.65)
*/
BOOL16 WINAPI TaskFindHandle16( TASKENTRY *lpte, HTASK16 hTask )
{
lpte->hNext = hTask;
return TaskNext16( lpte );
}
/***********************************************************************
* NotifyRegister (TOOLHELP.73)
*/
BOOL16 WINAPI NotifyRegister16( HTASK16 htask, FARPROC16 lpfnCallback,
WORD wFlags )
{
int i;
FIXME("(%x,%lx,%x), semi-stub.\n",
htask, (DWORD)lpfnCallback, wFlags );
if (!htask) htask = GetCurrentTask();
for (i=0;i<nrofnotifys;i++)
if (notifys[i].htask==htask)
break;
if (i==nrofnotifys) {
if (notifys==NULL)
notifys=HeapAlloc( GetProcessHeap(), 0,
sizeof(struct notify) );
else
notifys=HeapReAlloc( GetProcessHeap(), 0, notifys,
sizeof(struct notify)*(nrofnotifys+1));
if (!notifys) return FALSE;
nrofnotifys++;
}
notifys[i].htask=htask;
notifys[i].lpfnCallback=lpfnCallback;
notifys[i].wFlags=wFlags;
return TRUE;
}
/***********************************************************************
* NotifyUnregister (TOOLHELP.74)
*/
BOOL16 WINAPI NotifyUnregister16( HTASK16 htask )
{
int i;
FIXME("(%x), semi-stub.\n", htask );
if (!htask) htask = GetCurrentTask();
for (i=nrofnotifys;i--;)
if (notifys[i].htask==htask)
break;
if (i==-1)
return FALSE;
memcpy(notifys+i,notifys+(i+1),sizeof(struct notify)*(nrofnotifys-i-1));
notifys=HeapReAlloc( GetProcessHeap(), 0, notifys,
(nrofnotifys-1)*sizeof(struct notify));
nrofnotifys--;
return TRUE;
}
/***********************************************************************
* StackTraceCSIPFirst (TOOLHELP.67)
*/
BOOL16 WINAPI StackTraceCSIPFirst16(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
{
FIXME("(%p, ss %04x, cs %04x, ip %04x, bp %04x): stub.\n", ste, wSS, wCS, wIP, wBP);
return TRUE;
}
/***********************************************************************
* StackTraceFirst (TOOLHELP.66)
*/
BOOL16 WINAPI StackTraceFirst16(STACKTRACEENTRY *ste, HTASK16 Task)
{
FIXME("(%p, %04x), stub.\n", ste, Task);
return TRUE;
}
/***********************************************************************
* StackTraceNext (TOOLHELP.68)
*/
BOOL16 WINAPI StackTraceNext16(STACKTRACEENTRY *ste)
{
FIXME("(%p), stub.\n", ste);
return TRUE;
}
/***********************************************************************
* InterruptRegister (TOOLHELP.75)
*/
BOOL16 WINAPI InterruptRegister16( HTASK16 task, FARPROC callback )
{
FIXME("(%04x, %p), stub.\n", task, callback);
return TRUE;
}
/***********************************************************************
* InterruptUnRegister (TOOLHELP.76)
*/
BOOL16 WINAPI InterruptUnRegister16( HTASK16 task )
{
FIXME("(%04x), stub.\n", task);
return TRUE;
}
/***********************************************************************
* TimerCount (TOOLHELP.80)
*/
BOOL16 WINAPI TimerCount16( TIMERINFO *pTimerInfo )
{
/* FIXME
* In standard mode, dwmsSinceStart = dwmsThisVM
*
* I tested this, under Windows in enhanced mode, and
* if you never switch VM (ie start/stop DOS) these
* values should be the same as well.
*
* Also, Wine should adjust for the hardware timer
* to reduce the amount of error to ~1ms.
* I can't be bothered, can you?
*/
pTimerInfo->dwmsSinceStart = pTimerInfo->dwmsThisVM = GetTickCount();
return TRUE;
}
/***********************************************************************
* SystemHeapInfo (TOOLHELP.71)
*/
BOOL16 WINAPI SystemHeapInfo16( SYSHEAPINFO *pHeapInfo )
{
STACK16FRAME* stack16 = MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved);
HANDLE16 oldDS = stack16->ds;
WORD user = LoadLibrary16( "USER.EXE" );
WORD gdi = LoadLibrary16( "GDI.EXE" );
stack16->ds = user;
pHeapInfo->wUserFreePercent = (int)LocalCountFree16() * 100 / LocalHeapSize16();
stack16->ds = gdi;
pHeapInfo->wGDIFreePercent = (int)LocalCountFree16() * 100 / LocalHeapSize16();
stack16->ds = oldDS;
pHeapInfo->hUserSegment = user;
pHeapInfo->hGDISegment = gdi;
FreeLibrary16( user );
FreeLibrary16( gdi );
return TRUE;
}
/***********************************************************************
* ToolHelpHook (KERNEL.341)
* see "Undocumented Windows"
*/
FARPROC16 WINAPI ToolHelpHook16(FARPROC16 lpfnNotifyHandler)
{
FARPROC16 tmp;
FIXME("(%p), stub.\n", lpfnNotifyHandler);
tmp = HookNotify;
HookNotify = lpfnNotifyHandler;
/* just return previously installed notification function */
return tmp;
}
/*
* Win32s Universal Thunk API
*
* Copyright 1999 Ulrich Weigand
*
* 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
*/
#include <stdarg.h>
#include "wine/winbase16.h"
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "wownt32.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(thunk);
#include "pshpack1.h"
typedef struct
{
BYTE popl_eax;
BYTE pushl;
DWORD target;
BYTE pushl_eax;
BYTE ljmp;
DWORD utglue16;
} UT16THUNK;
typedef struct
{
BYTE popl_eax;
BYTE pushl;
DWORD target;
BYTE pushl_eax;
BYTE jmp;
DWORD utglue32;
} UT32THUNK;
#include "poppack.h"
typedef struct _UTINFO
{
struct _UTINFO *next;
HMODULE hModule;
HMODULE16 hModule16;
UT16THUNK ut16;
UT32THUNK ut32;
} UTINFO;
static UTINFO *UT_head; /* head of Universal Thunk list */
typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
LPSTR lpszInitName, LPSTR lpszProcName,
FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
LPVOID lpBuff );
VOID WINAPI UTUnRegister( HMODULE hModule );
/****************************************************************************
* UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
*/
DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
UTGLUEPROC target )
{
INT i;
/* Convert arguments to flat pointers */
if ( translationList )
for ( i = 0; translationList[i]; i++ )
{
LPVOID flatPtr = MapSL( translationList[i] );
*(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
}
/* Call 32-bit routine */
return target( lpBuff, dwUserDefined );
}
/****************************************************************************
* UTGlue32
*/
static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
LPVOID translationList[] )
{
SEGPTR segBuff, *segptrList = NULL;
INT i, nList = 0;
DWORD retv;
WORD args[4];
/* Convert arguments to SEGPTRs */
if ( translationList )
for ( nList = 0; translationList[nList]; nList++ )
;
if ( nList )
{
segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
if ( !segptrList )
{
FIXME("Unable to allocate segptrList!\n" );
return 0;
}
for ( i = 0; i < nList; i++ )
segptrList[i] = *(SEGPTR *)translationList[i]
= MapLS( *(LPVOID *)translationList[i] );
}
segBuff = MapLS( lpBuff );
/* Call 16-bit routine */
args[3] = SELECTOROF(segBuff);
args[2] = OFFSETOF(segBuff);
args[1] = HIWORD(dwUserDefined);
args[0] = LOWORD(dwUserDefined);
WOWCallback16Ex( (DWORD)target, WCB16_PASCAL, sizeof(args), args, &retv );
/* Free temporary selectors */
UnMapLS( segBuff );
if ( nList )
{
for ( i = 0; i < nList; i++ )
UnMapLS( segptrList[i] );
HeapFree( GetProcessHeap(), 0, segptrList );
}
return retv;
}
/****************************************************************************
* UTAlloc
*/
static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
FARPROC16 target16, FARPROC target32 )
{
static FARPROC16 UTGlue16_Segptr = NULL;
UTINFO *ut;
if ( !UTGlue16_Segptr )
{
HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
if ( !UTGlue16_Segptr ) return NULL;
}
ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
if ( !ut ) return NULL;
ut->hModule = hModule;
ut->hModule16 = hModule16;
ut->ut16.popl_eax = 0x58;
ut->ut16.pushl = 0x68;
ut->ut16.target = (DWORD)target32;
ut->ut16.pushl_eax = 0x50;
ut->ut16.ljmp = 0xea;
ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
ut->ut32.popl_eax = 0x58;
ut->ut32.pushl = 0x68;
ut->ut32.target = (DWORD)target16;
ut->ut32.pushl_eax = 0x50;
ut->ut32.jmp = 0xe9;
ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
ut->next = UT_head;
UT_head = ut;
return ut;
}
/****************************************************************************
* UTFree
*/
static void UTFree( UTINFO *ut )
{
UTINFO **ptr;
for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
if ( *ptr == ut )
{
*ptr = ut->next;
break;
}
HeapFree( GetProcessHeap(), 0, ut );
}
/****************************************************************************
* UTFind
*/
static UTINFO *UTFind( HMODULE hModule )
{
UTINFO *ut;
for ( ut = UT_head; ut; ut =ut->next )
if ( ut->hModule == hModule )
break;
return ut;
}
/****************************************************************************
* UTRegister (KERNEL32.@)
*/
BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
LPSTR lpszInitName, LPSTR lpszProcName,
FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
LPVOID lpBuff )
{
UTINFO *ut;
HMODULE16 hModule16;
FARPROC16 target16, init16;
/* Load 16-bit DLL and get UTProc16 entry point */
if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
|| (target16 = GetProcAddress16( hModule16, lpszProcName )) == 0 )
return FALSE;
/* Allocate UTINFO struct */
RtlAcquirePebLock();
if ( (ut = UTFind( hModule )) != NULL )
ut = NULL;
else
ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
RtlReleasePebLock();
if ( !ut )
{
FreeLibrary16( hModule16 );
return FALSE;
}
/* Call UTInit16 if present */
if ( lpszInitName
&& (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
{
SEGPTR callback = MapLS( &ut->ut16 );
SEGPTR segBuff = MapLS( lpBuff );
WORD args[4];
DWORD ret;
args[3] = SELECTOROF(callback);
args[2] = OFFSETOF(callback);
args[1] = SELECTOROF(segBuff);
args[0] = OFFSETOF(segBuff);
WOWCallback16Ex( (DWORD)init16, WCB16_PASCAL, sizeof(args), args, &ret );
UnMapLS( segBuff );
UnMapLS( callback );
if (!ret)
{
UTUnRegister( hModule );
return FALSE;
}
}
/* Return 32-bit thunk */
*ppfn32Thunk = (FARPROC) &ut->ut32;
return TRUE;
}
/****************************************************************************
* UTUnRegister (KERNEL32.@)
*/
VOID WINAPI UTUnRegister( HMODULE hModule )
{
UTINFO *ut;
HMODULE16 hModule16 = 0;
RtlAcquirePebLock();
ut = UTFind( hModule );
if ( !ut )
{
hModule16 = ut->hModule16;
UTFree( ut );
}
RtlReleasePebLock();
if ( hModule16 )
FreeLibrary16( hModule16 );
}
/****************************************************************************
* UTInit (KERNEL.493)
*/
WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
{
FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
return 0;
}
/*
* Copyright 1993 Bob Amstadt
*
* 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
*/
#include <stdlib.h>
#include "windef.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(int);
struct Win87EmInfoStruct
{
unsigned short Version;
unsigned short SizeSaveArea;
unsigned short WinDataSeg;
unsigned short WinCodeSeg;
unsigned short Have80x87;
unsigned short Unused;
};
/* Implementing this is easy cause Linux and *BSD* ALWAYS have a numerical
* coprocessor. (either real or emulated on kernellevel)
*/
/* win87em.dll also sets interrupt vectors: 2 (NMI), 0x34 - 0x3f (emulator
* calls of standard libraries, see Ralph Browns interrupt list), 0x75
* (int13 error reporting of coprocessor)
*/
/* have a look at /usr/src/linux/arch/i386/math-emu/ *.[ch] for more info
* especially control_w.h and status_w.h
*/
/* FIXME: Still rather skeletal implementation only */
static BOOL Installed = 0;
static WORD RefCount = 0;
static WORD CtrlWord_1 = 0;
static WORD CtrlWord_2 = 0;
static WORD CtrlWord_Internal = 0;
static WORD StatusWord_1 = 0x000b;
static WORD StatusWord_2 = 0;
static WORD StatusWord_3 = 0;
static WORD StackTop = 175;
static WORD StackBottom = 0;
static WORD Inthandler02hVar = 1;
static void WIN87_ClearCtrlWord( CONTEXT86 *context )
{
context->Eax &= ~0xffff; /* set AX to 0 */
if (Installed)
#ifdef __i386__
__asm__("fclex");
#else
;
#endif
StatusWord_3 = StatusWord_2 = 0;
}
static void WIN87_SetCtrlWord( CONTEXT86 *context )
{
CtrlWord_1 = LOWORD(context->Eax);
context->Eax &= ~0x00c3;
if (Installed) {
CtrlWord_Internal = LOWORD(context->Eax);
#ifdef __i386__
__asm__("wait;fldcw %0" : : "m" (CtrlWord_Internal));
#endif
}
CtrlWord_2 = LOWORD(context->Eax);
}
static void WIN87_Init( CONTEXT86 *context )
{
if (Installed) {
#ifdef __i386__
__asm__("fninit");
__asm__("fninit");
#endif
}
StackBottom = StackTop;
context->Eax = (context->Eax & ~0xffff) | 0x1332;
WIN87_SetCtrlWord(context);
WIN87_ClearCtrlWord(context);
}
/***********************************************************************
* _fpMath (WIN87EM.1)
*/
void WINAPI WIN87_fpmath( CONTEXT86 *context )
{
TRACE("(cs:eip=%x:%lx es=%x bx=%04x ax=%04x dx=%04x)\n",
(WORD)context->SegCs, context->Eip,
(WORD)context->SegEs, (WORD)context->Ebx,
(WORD)context->Eax, (WORD)context->Edx );
switch(LOWORD(context->Ebx))
{
case 0: /* install (increase instanceref) emulator, install NMI vector */
RefCount++;
#if 0
if (Installed)
InstallIntVecs02hAnd75h();
#endif
WIN87_Init(context);
context->Eax &= ~0xffff; /* set AX to 0 */
break;
case 1: /* Init Emulator */
WIN87_Init(context);
break;
case 2: /* deinstall emulator (decrease instanceref), deinstall NMI vector
* if zero. Every '0' call should have a matching '2' call.
*/
WIN87_Init(context);
RefCount--;
#if 0
if (!RefCount && Installed)
RestoreInt02h();
#endif
break;
case 3:
/*INT_SetHandler(0x3E,MAKELONG(AX,DX));*/
break;
case 4: /* set control word (& ~(CW_Denormal|CW_Invalid)) */
/* OUT: newset control word in AX */
WIN87_SetCtrlWord(context);
break;
case 5: /* return internal control word in AX */
context->Eax = (context->Eax & ~0xffff) | CtrlWord_1;
break;
case 6: /* round top of stack to integer using method AX & 0x0C00 */
/* returns current controlword */
{
DWORD dw=0;
WORD save,mask;
/* I don't know much about asm() programming. This could be
* wrong.
*/
#ifdef __i386__
__asm__ __volatile__("fstcw %0;wait" : "=m" (save) : : "memory");
__asm__ __volatile__("fstcw %0;wait" : "=m" (mask) : : "memory");
__asm__ __volatile__("orw $0xC00,%0" : "=m" (mask) : : "memory");
__asm__ __volatile__("fldcw %0;wait" : : "m" (mask));
__asm__ __volatile__("frndint");
__asm__ __volatile__("fist %0;wait" : "=m" (dw) : : "memory");
__asm__ __volatile__("fldcw %0" : : "m" (save));
#endif
TRACE("On top of stack is %ld\n",dw);
}
break;
case 7: /* POP top of stack as integer into DX:AX */
/* IN: AX&0x0C00 rounding protocol */
/* OUT: DX:AX variable popped */
{
DWORD dw=0;
/* I don't know much about asm() programming. This could be
* wrong.
*/
/* FIXME: could someone who really understands asm() fix this please? --AJ */
/* __asm__("fistp %0;wait" : "=m" (dw) : : "memory"); */
TRACE("On top of stack was %ld\n",dw);
context->Eax = (context->Eax & ~0xffff) | LOWORD(dw);
context->Edx = (context->Edx & ~0xffff) | HIWORD(dw);
}
break;
case 8: /* restore internal status words from emulator status word */
context->Eax &= ~0xffff; /* set AX to 0 */
if (Installed) {
#ifdef __i386__
__asm__("fstsw %0;wait" : "=m" (StatusWord_1));
#endif
context->Eax |= StatusWord_1 & 0x3f;
}
context->Eax = (context->Eax | StatusWord_2) & ~0xe000;
StatusWord_2 = LOWORD(context->Eax);
break;
case 9: /* clear emu control word and some other things */
WIN87_ClearCtrlWord(context);
break;
case 10: /* dunno. but looks like returning nr. of things on stack in AX */
context->Eax &= ~0xffff; /* set AX to 0 */
break;
case 11: /* just returns the installed flag in DX:AX */
context->Edx &= ~0xffff; /* set DX to 0 */
context->Eax = (context->Eax & ~0xffff) | Installed;
break;
case 12: /* save AX in some internal state var */
Inthandler02hVar = LOWORD(context->Eax);
break;
default: /* error. Say that loud and clear */
FIXME("unhandled switch %d\n",LOWORD(context->Ebx));
context->Eax |= 0xffff;
context->Edx |= 0xffff;
break;
}
}
/***********************************************************************
* __WinEm87Info (WIN87EM.3)
*/
void WINAPI WIN87_WinEm87Info(struct Win87EmInfoStruct *pWIS,
int cbWin87EmInfoStruct)
{
FIXME("(%p,%d), stub !\n",pWIS,cbWin87EmInfoStruct);
}
/***********************************************************************
* __WinEm87Restore (WIN87EM.4)
*/
void WINAPI WIN87_WinEm87Restore(void *pWin87EmSaveArea,
int cbWin87EmSaveArea)
{
FIXME("(%p,%d), stub !\n",
pWin87EmSaveArea,cbWin87EmSaveArea);
}
/***********************************************************************
* __WinEm87Save (WIN87EM.5)
*/
void WINAPI WIN87_WinEm87Save(void *pWin87EmSaveArea, int cbWin87EmSaveArea)
{
FIXME("(%p,%d), stub !\n",
pWin87EmSaveArea,cbWin87EmSaveArea);
}
1 stub WINDEBUG
# 2 stub WEP
3 pascal -register WinNotify() WinNotify16
......@@ -90,11 +90,11 @@ RC_SRCS16 = \
version16.rc
MC_SRCS = \
messages/winerr_enu.mc
nls/winerr_enu.mc
EXTRA_OBJS = relay16asm.o
EXTRASUBDIRS = messages nls
EXTRASUBDIRS = nls
@MAKE_DLL_RULES@
......
......@@ -18,6 +18,6 @@
#include "locale_rc.rc"
#include "messages/winerr_enu.mc.rc"
#include "nls/winerr_enu.mc.rc"
#include "version.rc"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment