mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-28 19:26:16 +00:00
Kamil Hornicek <[email protected]>
- Update tests to Wine head (as of 11th of May, 2008). svn path=/trunk/; revision=33464
This commit is contained in:
@@ -67,10 +67,10 @@
|
||||
<directory name="odbccp32">
|
||||
<xi:include href="odbccp32/odbccp32.rbuild" />
|
||||
</directory>
|
||||
<!--directory name="ole32">
|
||||
<directory name="ole32">
|
||||
<xi:include href="ole32/ole32.rbuild" />
|
||||
</directory>
|
||||
<directory name="oleaut32">
|
||||
<!--<directory name="oleaut32">
|
||||
<xi:include href="oleaut32/oleaut32.rbuild" />
|
||||
</directory-->
|
||||
<directory name="psapi">
|
||||
|
||||
@@ -50,8 +50,8 @@ static WCHAR sTooLongPassword[] = {'a','b','c','d','e','f','g','h','a','b','c','
|
||||
'a', 0};
|
||||
|
||||
static WCHAR sTestUserName[] = {'t', 'e', 's', 't', 'u', 's', 'e', 'r', 0};
|
||||
static WCHAR sTestUserOldPass[] = {'o', 'l', 'd', 'p', 'a', 's', 's', 0};
|
||||
static WCHAR sTestUserNewPass[] = {'n', 'e', 'w', 'p', 'a', 's', 's', 0};
|
||||
static WCHAR sTestUserOldPass[] = {'O', 'l', 'd', 'P', 'a', 's', 's', 'W', '0', 'r', 'd', 'S', 'e', 't', '!', '~', 0};
|
||||
static WCHAR sTestUserNewPass[] = {'N', 'e', 'w', 'P', 'a', 's', 's', 'W', '0', 'r', 'd', 'S', 'e', 't', '!', '~', 0};
|
||||
static const WCHAR sBadNetPath[] = {'\\','\\','B','a',' ',' ','p','a','t','h',0};
|
||||
static const WCHAR sInvalidName[] = {'\\',0};
|
||||
static const WCHAR sInvalidName2[] = {'\\','\\',0};
|
||||
@@ -301,7 +301,10 @@ static void run_userhandling_tests(void)
|
||||
|
||||
ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserOldPass,
|
||||
sTestUserOldPass);
|
||||
ok(ret == NERR_Success,
|
||||
/* Apparently NERR_PasswordTooShort can be returned on windows xp if a
|
||||
* strict password policy is enforced
|
||||
*/
|
||||
ok(ret == NERR_Success || ret == NERR_PasswordTooShort,
|
||||
"Changing old password to old password returned 0x%08x.\n", ret);
|
||||
|
||||
ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserNewPass,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="netapi32_winetest" type="win32cui" installbase="bin" installname="netapi32_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="netapi32_winetest" type="win32cui" installbase="bin" installname="netapi32_winetest.exe" allowwarnings="true">
|
||||
<include base="netapi32_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -80,7 +80,17 @@ static void run_wkstausergetinfo_tests(void)
|
||||
|
||||
/* Level 0 */
|
||||
ok(pNetWkstaUserGetInfo(NULL, 0, (LPBYTE *)&ui0) == NERR_Success,
|
||||
"NetWkstaUserGetInfo is successful\n");
|
||||
"NetWkstaUserGetInfo is unsuccessful\n");
|
||||
|
||||
ok(ui0 != NULL, "ui0 is NULL\n");
|
||||
/* This failure occured when I ran sshd as service and didn't authenticate
|
||||
* Since the test dereferences ui0, the rest of this test is worthless
|
||||
*/
|
||||
if (!ui0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ok(!lstrcmpW(user_name, ui0->wkui0_username), "This is really user name\n");
|
||||
pNetApiBufferSize(ui0, &dwSize);
|
||||
ok(dwSize >= (sizeof(WKSTA_USER_INFO_0) +
|
||||
|
||||
+102
-102
@@ -25,7 +25,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
/* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
|
||||
/* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
|
||||
* definition errors when we get to winnt.h
|
||||
*/
|
||||
#define WIN32_NO_STATUS
|
||||
@@ -89,7 +89,7 @@ static void InitFunctionPtr(void)
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD RtlAtomTestThread(LPVOID Table)
|
||||
static DWORD WINAPI RtlAtomTestThread(LPVOID Table)
|
||||
{
|
||||
RTL_ATOM_TABLE AtomTable = *(PRTL_ATOM_TABLE)Table;
|
||||
RTL_ATOM Atom;
|
||||
@@ -98,30 +98,30 @@ static DWORD RtlAtomTestThread(LPVOID Table)
|
||||
WCHAR Name[64];
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &Atom);
|
||||
ok(!res, "Unable to find atom from another thread, retval: %lx\n", res);
|
||||
ok(!res, "Unable to find atom from another thread, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &Atom);
|
||||
ok(!res, "Unable to lookup pinned atom in table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to lookup pinned atom in table, retval: %x\n", res);
|
||||
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len);
|
||||
ok(res == STATUS_BUFFER_TOO_SMALL, "We got wrong retval: %lx\n", res);
|
||||
ok(res == STATUS_BUFFER_TOO_SMALL, "We got wrong retval: %x\n", res);
|
||||
|
||||
Len = 64;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len);
|
||||
ok(!res, "Failed with longenough buffer, retval: %lx\n", res);
|
||||
ok(RefCount == 1, "Refcount was not 1 but %lx\n", RefCount);
|
||||
ok(PinCount == 1, "Pincount was not 1 but %lx\n", PinCount);
|
||||
ok(!res, "Failed with longenough buffer, retval: %x\n", res);
|
||||
ok(RefCount == 1, "Refcount was not 1 but %x\n", RefCount);
|
||||
ok(PinCount == 1, "Pincount was not 1 but %x\n", PinCount);
|
||||
ok(!lstrcmpW(Name, testAtom2), "We found wrong atom!!\n");
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len);
|
||||
|
||||
Len = 64;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom, NULL, NULL, Name, &Len);
|
||||
ok(!res, "RtlQueryAtomInAtomTable with optional args invalid failed, retval: %lx\n", res);
|
||||
ok(!res, "RtlQueryAtomInAtomTable with optional args invalid failed, retval: %x\n", res);
|
||||
ok(!lstrcmpW(Name, testAtom2), "Found Wrong atom!\n");
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %x\n", res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -143,140 +143,140 @@ static void test_NtAtom(void)
|
||||
if (!res)
|
||||
{
|
||||
res = pRtlDestroyAtomTable(AtomTable);
|
||||
ok(!res, "We could create the atom table, but we couldn't destroy it! retval: %lx\n", res);
|
||||
ok(!res, "We could create the atom table, but we couldn't destroy it! retval: %x\n", res);
|
||||
}
|
||||
|
||||
AtomTable = NULL;
|
||||
res = pRtlCreateAtomTable(37, &AtomTable);
|
||||
ok(!res, "We're unable to create an atom table with a valid table size retval: %lx\n", res);
|
||||
ok(!res, "We're unable to create an atom table with a valid table size retval: %x\n", res);
|
||||
if (!res)
|
||||
{
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
|
||||
ok(!res, "We were unable to add a simple atom to the atom table, retval: %lx\n", res);
|
||||
ok(!res, "We were unable to add a simple atom to the atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Cap, &testAtom);
|
||||
ok(!res, "We were unable to find capital version of the atom, retval: %lx\n", res);
|
||||
ok(!res, "We were unable to find capital version of the atom, retval: %x\n", res);
|
||||
ok(Atom1 == testAtom, "Found wrong atom in table when querying capital atom\n");
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Low, &testAtom);
|
||||
ok(!res, "Unable to find lowercase version of the atom, retval: %lx\n", res);
|
||||
ok(!res, "Unable to find lowercase version of the atom, retval: %x\n", res);
|
||||
ok(testAtom == Atom1, "Found wrong atom when querying lowercase atom\n");
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, EmptyAtom, &testEAtom);
|
||||
ok(res == STATUS_OBJECT_NAME_INVALID, "Got wrong retval, retval: %lx\n", res);
|
||||
ok(res == STATUS_OBJECT_NAME_INVALID, "Got wrong retval, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
|
||||
ok(!res, "Failed to find totally legitimate atom, retval: %lx\n", res);
|
||||
ok(!res, "Failed to find totally legitimate atom, retval: %x\n", res);
|
||||
ok(testAtom == Atom1, "Found wrong atom!\n");
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom2, &Atom2);
|
||||
ok(!res, "Unable to add other legitimate atom to table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add other legitimate atom to table, retval: %x\n", res);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, Atom2);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %x\n", res);
|
||||
|
||||
testThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RtlAtomTestThread, &AtomTable, 0, NULL);
|
||||
testThread = CreateThread(NULL, 0, RtlAtomTestThread, &AtomTable, 0, NULL);
|
||||
WaitForSingleObject(testThread, INFINITE);
|
||||
|
||||
Len = 64;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name, &Len);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
|
||||
ok(RefCount == 1, "RefCount is not 1 but %lx\n", RefCount);
|
||||
ok(PinCount == 1, "PinCount is not 1 but %lx\n", PinCount);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %x\n", res);
|
||||
ok(RefCount == 1, "RefCount is not 1 but %x\n", RefCount);
|
||||
ok(PinCount == 1, "PinCount is not 1 but %x\n", PinCount);
|
||||
ok(!lstrcmpW(Name, testAtom2), "We found wrong atom\n");
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len);
|
||||
|
||||
res = pRtlEmptyAtomTable(AtomTable, FALSE);
|
||||
ok(!res, "Unable to empty atom table, retval %lx\n", res);
|
||||
ok(!res, "Unable to empty atom table, retval %x\n", res);
|
||||
|
||||
Len = 64;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name, &Len);
|
||||
ok(!res, "It seems RtlEmptyAtomTable deleted our pinned atom eaven though we asked it not to, retval: %lx\n", res);
|
||||
ok(RefCount == 1, "RefCount is not 1 but %lx\n", RefCount);
|
||||
ok(PinCount == 1, "PinCount is not 1 but %lx\n", PinCount);
|
||||
ok(!res, "It seems RtlEmptyAtomTable deleted our pinned atom eaven though we asked it not to, retval: %x\n", res);
|
||||
ok(RefCount == 1, "RefCount is not 1 but %x\n", RefCount);
|
||||
ok(PinCount == 1, "PinCount is not 1 but %x\n", PinCount);
|
||||
ok(!lstrcmpW(Name, testAtom2), "We found wrong atom\n");
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
|
||||
ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len);
|
||||
|
||||
Len = 8;
|
||||
Name[0] = Name[1] = Name[2] = Name[3] = Name[4] = 0x55AA;
|
||||
Name[0] = Name[1] = Name[2] = Name[3] = Name[4] = 0x1337;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, NULL, NULL, Name, &Len);
|
||||
ok(!res, "query atom %lx\n", res);
|
||||
ok(Len == 6, "wrong length %lu\n", Len);
|
||||
ok(!res, "query atom %x\n", res);
|
||||
ok(Len == 6, "wrong length %u\n", Len);
|
||||
ok(!memcmp(Name, testAtom2, Len), "wrong atom string\n");
|
||||
ok(!Name[3], "wrong string termination\n");
|
||||
ok(Name[4] == 0x55AA, "buffer overwrite\n");
|
||||
ok(Name[4] == 0x1337, "buffer overwrite\n");
|
||||
|
||||
Len = lstrlenW(testAtom2) * sizeof(WCHAR);
|
||||
memset(Name, '.', sizeof(Name));
|
||||
res = pRtlQueryAtomInAtomTable( AtomTable, Atom2, NULL, NULL, Name, &Len );
|
||||
ok(!res, "query atom %lx\n", res);
|
||||
ok(Len == (lstrlenW(testAtom2) - 1) * sizeof(WCHAR), "wrong length %lu\n", Len);
|
||||
ok(!res, "query atom %x\n", res);
|
||||
ok(Len == (lstrlenW(testAtom2) - 1) * sizeof(WCHAR), "wrong length %u\n", Len);
|
||||
ok(!memcmp(testAtom2, Name, (lstrlenW(testAtom2) - 1) * sizeof(WCHAR)), "wrong atom name\n");
|
||||
ok(Name[lstrlenW(testAtom2) - 1] == '\0', "wrong char\n");
|
||||
ok(Name[lstrlenW(testAtom2)] == ('.' << 8) + '.', "wrong char\n");
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
|
||||
ok(!res, "We can't find our pinned atom!! retval: %lx\n", res);
|
||||
ok(!res, "We can't find our pinned atom!! retval: %x\n", res);
|
||||
ok(testAtom == Atom2, "We found wrong atom!!!\n");
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "We found the atom in our table eaven though we asked RtlEmptyAtomTable to remove it, retval: %lx\n", res);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "We found the atom in our table eaven though we asked RtlEmptyAtomTable to remove it, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom3, &Atom3);
|
||||
ok(!res, "Unable to add atom to table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add atom to table, retval: %x\n", res);
|
||||
|
||||
res = pRtlEmptyAtomTable(AtomTable, TRUE);
|
||||
ok(!res, "Unable to empty atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to empty atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "The pinned atom should be removed, retval: %lx\n", res);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "The pinned atom should be removed, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom3, &testAtom);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Non pinned atom should also be removed, retval: %lx\n", res);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Non pinned atom should also be removed, retval: %x\n", res);
|
||||
|
||||
res = pRtlDestroyAtomTable(AtomTable);
|
||||
ok(!res, "Can't destroy atom table, retval: %lx\n", res);
|
||||
ok(!res, "Can't destroy atom table, retval: %x\n", res);
|
||||
}
|
||||
|
||||
AtomTable = NULL;
|
||||
res = pRtlCreateAtomTable(37, &AtomTable);
|
||||
ok(!res, "Unable to create atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to create atom table, retval: %x\n", res);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Didn't get expected retval with querying an empty atom table, retval: %lx\n", res);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Didn't get expected retval with querying an empty atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
|
||||
ok(!res, "Unable to add atom to atom table, retval %lx\n", res);
|
||||
ok(!res, "Unable to add atom to atom table, retval %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
|
||||
ok(!res, "Can't find previously added atom in table, retval: %lx\n", res);
|
||||
ok(testAtom == Atom1, "Found wrong atom! retval: %lx\n", res);
|
||||
ok(!res, "Can't find previously added atom in table, retval: %x\n", res);
|
||||
ok(testAtom == Atom1, "Found wrong atom! retval: %x\n", res);
|
||||
|
||||
res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
|
||||
ok(!res, "Unable to delete atom from table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to delete atom from table, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Able to find previously deleted atom in table, retval: %lx\n", res);
|
||||
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Able to find previously deleted atom in table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
|
||||
ok(!res, "Unable to add atom to atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add atom to atom table, retval: %x\n", res);
|
||||
|
||||
Len = 0;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom1, NULL, NULL, Name, &Len);
|
||||
ok(res == STATUS_BUFFER_TOO_SMALL, "Got wrong retval, retval: %lx\n", res);
|
||||
ok((lstrlenW(testAtom1) * sizeof(WCHAR)) == Len, "Got wrong length %lx\n", Len);
|
||||
ok(res == STATUS_BUFFER_TOO_SMALL, "Got wrong retval, retval: %x\n", res);
|
||||
ok((lstrlenW(testAtom1) * sizeof(WCHAR)) == Len, "Got wrong length %x\n", Len);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, Atom1);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
|
||||
ok(!res, "Unable to find atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to find atom in atom table, retval: %x\n", res);
|
||||
ok(testAtom == Atom1, "Wrong atom found\n");
|
||||
|
||||
res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
|
||||
ok(res == STATUS_WAS_LOCKED, "Unable to delete atom from table, retval: %lx\n", res);
|
||||
ok(res == STATUS_WAS_LOCKED, "Unable to delete atom from table, retval: %x\n", res);
|
||||
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
|
||||
ok(!res, "Able to find deleted atom in table\n");
|
||||
@@ -299,82 +299,82 @@ static void test_NtIntAtom(void)
|
||||
|
||||
AtomTable = NULL;
|
||||
res = pRtlCreateAtomTable(37, &AtomTable);
|
||||
ok(!res, "Unable to create atom table, %lx\n", res);
|
||||
ok(!res, "Unable to create atom table, %x\n", res);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
/* According to the kernel32 functions, integer atoms are only allowd from
|
||||
/* According to the kernel32 functions, integer atoms are only allowed from
|
||||
* 0x0001 to 0xbfff and not 0xc000 to 0xffff, which is correct */
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)0, &testAtom);
|
||||
ok(res == STATUS_INVALID_PARAMETER, "Didn't get expected result from adding 0 int atom, retval: %lx\n", res);
|
||||
ok(res == STATUS_INVALID_PARAMETER, "Didn't get expected result from adding 0 int atom, retval: %x\n", res);
|
||||
for (i = 1; i <= 0xbfff; i++)
|
||||
{
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
|
||||
ok(!res, "Unable to add valid integer atom %i, retval: %lx\n", i, res);
|
||||
ok(!res, "Unable to add valid integer atom %i, retval: %x\n", i, res);
|
||||
}
|
||||
|
||||
for (i = 1; i <= 0xbfff; i++)
|
||||
{
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)i, &testAtom);
|
||||
ok(!res, "Unable to find int atom %i, retval: %lx\n", i, res);
|
||||
ok(!res, "Unable to find int atom %i, retval: %x\n", i, res);
|
||||
if (!res)
|
||||
{
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
|
||||
ok(!res, "Unable to pin int atom %i, retval: %lx\n", i, res);
|
||||
ok(!res, "Unable to pin int atom %i, retval: %x\n", i, res);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0xc000; i <= 0xffff; i++)
|
||||
{
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
|
||||
ok(res, "Able to illeageal integer atom %i, retval: %lx\n", i, res);
|
||||
ok(res, "Able to illeageal integer atom %i, retval: %x\n", i, res);
|
||||
}
|
||||
|
||||
res = pRtlDestroyAtomTable(AtomTable);
|
||||
ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to destroy atom table, retval: %x\n", res);
|
||||
}
|
||||
|
||||
AtomTable = NULL;
|
||||
res = pRtlCreateAtomTable(37, &AtomTable);
|
||||
ok(!res, "Unable to create atom table, %lx\n", res);
|
||||
ok(!res, "Unable to create atom table, %x\n", res);
|
||||
if (!res)
|
||||
{
|
||||
res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)123, &testAtom);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtomInt, &testAtom);
|
||||
ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add int atom to table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtomIntInv, &testAtom);
|
||||
ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add int atom to table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
|
||||
ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add int atom to table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
|
||||
ok(!res, "Unable to re-add int atom to table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to re-add int atom to table, retval: %x\n", res);
|
||||
|
||||
Len = 64;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &RefCount, &PinCount, Name, &Len);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
|
||||
ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
|
||||
ok(RefCount == 1, "Expected refcount 1 but got %lx\n", RefCount);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %x\n", res);
|
||||
ok(PinCount == 1, "Expected pincount 1 but got %x\n", PinCount);
|
||||
ok(RefCount == 1, "Expected refcount 1 but got %x\n", RefCount);
|
||||
ok(!lstrcmpW(testAtomOTT, Name), "Got wrong atom name\n");
|
||||
ok((lstrlenW(testAtomOTT) * sizeof(WCHAR)) == Len, "Got wrong len %ld\n", Len);
|
||||
ok((lstrlenW(testAtomOTT) * sizeof(WCHAR)) == Len, "Got wrong len %d\n", Len);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
|
||||
ok(!res, "Unable to pin int atom, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin int atom, retval: %x\n", res);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
|
||||
ok(!res, "Unable to pin int atom, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin int atom, retval: %x\n", res);
|
||||
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &RefCount, &PinCount, NULL, NULL);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
|
||||
ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
|
||||
ok(RefCount == 1, "Expected refcount 1 but got %lx\n", RefCount);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %x\n", res);
|
||||
ok(PinCount == 1, "Expected pincount 1 but got %x\n", PinCount);
|
||||
ok(RefCount == 1, "Expected refcount 1 but got %x\n", RefCount);
|
||||
|
||||
res = pRtlDestroyAtomTable(AtomTable);
|
||||
ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to destroy atom table, retval: %x\n", res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,40 +388,40 @@ static void test_NtRefPinAtom(void)
|
||||
|
||||
AtomTable = NULL;
|
||||
res = pRtlCreateAtomTable(37, &AtomTable);
|
||||
ok(!res, "Unable to create atom table, %lx\n", res);
|
||||
ok(!res, "Unable to create atom table, %x\n", res);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
|
||||
ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add our atom to the atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
|
||||
ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add our atom to the atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
|
||||
ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to add our atom to the atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, NULL, NULL);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
|
||||
ok(PinCount == 0, "Expected pincount 0 but got %lx\n", PinCount);
|
||||
ok(RefCount == 3, "Expected refcount 3 but got %lx\n", RefCount);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %x\n", res);
|
||||
ok(PinCount == 0, "Expected pincount 0 but got %x\n", PinCount);
|
||||
ok(RefCount == 3, "Expected refcount 3 but got %x\n", RefCount);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to pin atom in atom table, retval: %x\n", res);
|
||||
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, NULL, NULL);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
|
||||
ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
|
||||
ok(RefCount == 3, "Expected refcount 3 but got %lx\n", RefCount);
|
||||
ok(!res, "Unable to query atom in atom table, retval: %x\n", res);
|
||||
ok(PinCount == 1, "Expected pincount 1 but got %x\n", PinCount);
|
||||
ok(RefCount == 3, "Expected refcount 3 but got %x\n", RefCount);
|
||||
|
||||
res = pRtlDestroyAtomTable(AtomTable);
|
||||
ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
|
||||
ok(!res, "Unable to destroy atom table, retval: %x\n", res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,29 +434,29 @@ static void test_Global(void)
|
||||
ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR);
|
||||
|
||||
res = pNtAddAtom(testAtom1, lstrlenW(testAtom1) * sizeof(WCHAR), &atom);
|
||||
ok(!res, "Added atom (%lx)\n", res);
|
||||
ok(!res, "Added atom (%x)\n", res);
|
||||
|
||||
memset(abi->Name, 0x55, 255 * sizeof(WCHAR));
|
||||
memset(abi->Name, 0xcc, 255 * sizeof(WCHAR));
|
||||
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
|
||||
ok(!res, "atom lookup\n");
|
||||
ok(!lstrcmpW(abi->Name, testAtom1), "ok strings\n");
|
||||
ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n");
|
||||
ok(abi->Name[lstrlenW(testAtom1)] == 0, "wrong string termination %x\n", abi->Name[lstrlenW(testAtom1)]);
|
||||
ok(abi->Name[lstrlenW(testAtom1) + 1] == 0x5555, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
|
||||
ok(abi->Name[lstrlenW(testAtom1) + 1] == 0xcccc, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
|
||||
|
||||
ptr_size = sizeof(ATOM_BASIC_INFORMATION);
|
||||
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
|
||||
ok(res == STATUS_BUFFER_TOO_SMALL, "wrong return status (%lx)\n", res);
|
||||
ok(res == STATUS_BUFFER_TOO_SMALL, "wrong return status (%x)\n", res);
|
||||
ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "ok string length\n");
|
||||
|
||||
memset(abi->Name, 0x55, lstrlenW(testAtom1) * sizeof(WCHAR));
|
||||
memset(abi->Name, 0xcc, lstrlenW(testAtom1) * sizeof(WCHAR));
|
||||
ptr_size = sizeof(ATOM_BASIC_INFORMATION) + lstrlenW(testAtom1) * sizeof(WCHAR);
|
||||
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
|
||||
ok(!res, "atom lookup %lx\n", res);
|
||||
ok(!res, "atom lookup %x\n", res);
|
||||
ok(!lstrcmpW(abi->Name, testAtom1), "strings don't match\n");
|
||||
ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n");
|
||||
ok(abi->Name[lstrlenW(testAtom1)] == 0, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1)]);
|
||||
ok(abi->Name[lstrlenW(testAtom1) + 1] == 0x5555, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
|
||||
ok(abi->Name[lstrlenW(testAtom1) + 1] == 0xcccc, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
|
||||
|
||||
ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 4 * sizeof(WCHAR);
|
||||
abi->Name[0] = abi->Name[1] = abi->Name[2] = abi->Name[3] = '\0';
|
||||
|
||||
@@ -59,7 +59,7 @@ static void test_ntncdf(void)
|
||||
|
||||
RemoveDirectoryW( subdir );
|
||||
RemoveDirectoryW( path );
|
||||
|
||||
|
||||
r = CreateDirectoryW(path, NULL);
|
||||
ok( r == TRUE, "failed to create directory\n");
|
||||
|
||||
@@ -67,7 +67,7 @@ static void test_ntncdf(void)
|
||||
ok(r==STATUS_ACCESS_VIOLATION, "should return access violation\n");
|
||||
|
||||
fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
|
||||
hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL,
|
||||
hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, fflags, NULL);
|
||||
ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
|
||||
|
||||
@@ -187,7 +187,7 @@ static void test_ntncdf_async(void)
|
||||
|
||||
RemoveDirectoryW( subdir );
|
||||
RemoveDirectoryW( path );
|
||||
|
||||
|
||||
r = CreateDirectoryW(path, NULL);
|
||||
ok( r == TRUE, "failed to create directory\n");
|
||||
|
||||
@@ -195,7 +195,7 @@ static void test_ntncdf_async(void)
|
||||
ok(r==STATUS_ACCESS_VIOLATION, "should return access violation\n");
|
||||
|
||||
fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
|
||||
hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL,
|
||||
hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, fflags, NULL);
|
||||
ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
|
||||
|
||||
@@ -316,16 +316,22 @@ static void test_ntncdf_async(void)
|
||||
START_TEST(change)
|
||||
{
|
||||
HMODULE hntdll = GetModuleHandle("ntdll");
|
||||
if (!hntdll)
|
||||
{
|
||||
skip("not running on NT, skipping test\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pNtNotifyChangeDirectoryFile = (fnNtNotifyChangeDirectoryFile)
|
||||
pNtNotifyChangeDirectoryFile = (fnNtNotifyChangeDirectoryFile)
|
||||
GetProcAddress(hntdll, "NtNotifyChangeDirectoryFile");
|
||||
pNtCancelIoFile = (fnNtCancelIoFile)
|
||||
GetProcAddress(hntdll, "NtCancelIoFile");
|
||||
|
||||
if (!pNtNotifyChangeDirectoryFile)
|
||||
return;
|
||||
if (!pNtCancelIoFile)
|
||||
if (!pNtNotifyChangeDirectoryFile || !pNtCancelIoFile)
|
||||
{
|
||||
skip("missing functions, skipping test\n");
|
||||
return;
|
||||
}
|
||||
|
||||
test_ntncdf();
|
||||
test_ntncdf_async();
|
||||
|
||||
@@ -99,23 +99,22 @@ static void testQuery(void)
|
||||
|
||||
pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->var, strlen(test->var)+1 );
|
||||
nts = pRtlQueryEnvironmentVariable_U(small_env, &name, &value);
|
||||
ok( nts == test->status, "[%d]: Wrong status for '%s', expecting %lx got %lx\n",
|
||||
ok( nts == test->status, "[%d]: Wrong status for '%s', expecting %x got %x\n",
|
||||
test - tests, test->var, test->status, nts );
|
||||
if (nts == test->status) switch (nts)
|
||||
{
|
||||
case STATUS_SUCCESS:
|
||||
pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->val, strlen(test->val)+1 );
|
||||
ok( value.Length == strlen(test->val) * sizeof(WCHAR), "Wrong length %d/%d for %s\n",
|
||||
value.Length, strlen(test->val) * sizeof(WCHAR), test->var );
|
||||
ok( value.Length == strlen(test->val) * sizeof(WCHAR), "Wrong length %d for %s\n",
|
||||
value.Length, test->var );
|
||||
ok((value.Length == strlen(test->val) * sizeof(WCHAR) && memcmp(bv, bn, test->len*sizeof(WCHAR)) == 0) ||
|
||||
lstrcmpW(bv, bn) == 0,
|
||||
lstrcmpW(bv, bn) == 0,
|
||||
"Wrong result for %s/%d\n", test->var, test->len);
|
||||
ok(bv[test->len] == '@', "Writing too far away in the buffer for %s/%d\n", test->var, test->len);
|
||||
break;
|
||||
case STATUS_BUFFER_TOO_SMALL:
|
||||
ok( value.Length == strlen(test->val) * sizeof(WCHAR),
|
||||
"Wrong returned length %d/%d (too small buffer) for %s\n",
|
||||
value.Length, strlen(test->val) * sizeof(WCHAR), test->var );
|
||||
ok( value.Length == strlen(test->val) * sizeof(WCHAR),
|
||||
"Wrong returned length %d (too small buffer) for %s\n", value.Length, test->var );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -140,7 +139,7 @@ static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATU
|
||||
pRtlMultiByteToUnicodeN( bval1, sizeof(bval1), NULL, val, strlen(val)+1 );
|
||||
}
|
||||
nts = pRtlSetEnvironmentVariable(env, &uvar, val ? &uval : NULL);
|
||||
ok(nts == ret, "Setting var %s=%s (%lx/%lx)\n", var, val, nts, ret);
|
||||
ok(nts == ret, "Setting var %s=%s (%x/%x)\n", var, val, nts, ret);
|
||||
if (nts == STATUS_SUCCESS)
|
||||
{
|
||||
uval.Length = 0;
|
||||
@@ -156,7 +155,7 @@ static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATU
|
||||
ok(val == NULL, "Couldn't find variable, but didn't delete it. val = %s\n", val);
|
||||
break;
|
||||
default:
|
||||
ok(0, "Wrong ret %lu for %s\n", nts, var);
|
||||
ok(0, "Wrong ret %u for %s\n", nts, var);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -214,8 +213,8 @@ static void testExpand(void)
|
||||
* {"hello%foo%world%=oOH%eeck", "hellototoworldIIIeeck"},
|
||||
* Interestingly enough, with a 8 WCHAR buffers, we get on 2k:
|
||||
* helloIII
|
||||
* so it seems like strings overflowing the buffer are written
|
||||
* (troncated) but the write cursor is not advanced :-/
|
||||
* so it seems like strings overflowing the buffer are written
|
||||
* (truncated) but the write cursor is not advanced :-/
|
||||
*/
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -240,22 +239,19 @@ static void testExpand(void)
|
||||
us_dst.Buffer = NULL;
|
||||
|
||||
nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
|
||||
ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
|
||||
"Wrong returned length for %s: %lu <> %u\n",
|
||||
test->src, ul, strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR));
|
||||
ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
|
||||
"Wrong returned length for %s: %u\n", test->src, ul );
|
||||
|
||||
us_dst.Length = 0;
|
||||
us_dst.MaximumLength = sizeof(dst);
|
||||
us_dst.Buffer = dst;
|
||||
|
||||
nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
|
||||
ok(nts == STATUS_SUCCESS, "Call failed (%lu)\n", nts);
|
||||
ok(ul == us_dst.Length + sizeof(WCHAR),
|
||||
"Wrong returned length for %s: %lu <> %u\n",
|
||||
test->src, ul, us_dst.Length + sizeof(WCHAR));
|
||||
ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
|
||||
"Wrong returned length for %s: %lu <> %u\n",
|
||||
test->src, ul, strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR));
|
||||
ok(nts == STATUS_SUCCESS, "Call failed (%u)\n", nts);
|
||||
ok(ul == us_dst.Length + sizeof(WCHAR),
|
||||
"Wrong returned length for %s: %u\n", test->src, ul);
|
||||
ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
|
||||
"Wrong returned length for %s: %u\n", test->src, ul);
|
||||
ok(lstrcmpW(dst, rst) == 0, "Wrong result for %s: expecting %s\n",
|
||||
test->src, test->dst);
|
||||
|
||||
@@ -264,10 +260,9 @@ static void testExpand(void)
|
||||
us_dst.Buffer = dst;
|
||||
dst[8] = '-';
|
||||
nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
|
||||
ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%lu)\n", nts);
|
||||
ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
|
||||
"Wrong returned length for %s (with buffer too small): %lu <> %u\n",
|
||||
test->src, ul, strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR));
|
||||
ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%u)\n", nts);
|
||||
ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
|
||||
"Wrong returned length for %s (with buffer too small): %u\n", test->src, ul);
|
||||
ok(memcmp(dst, rst, 8*sizeof(WCHAR)) == 0,
|
||||
"Wrong result for %s (with buffer too small): expecting %s\n",
|
||||
test->src, test->dst);
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
#include "winreg.h"
|
||||
#include "winternl.h"
|
||||
|
||||
/* FIXME!!! this test checks only mappings, defined by MSDN:
|
||||
* http://support.microsoft.com/default.aspx?scid=KB;EN-US;q113996&
|
||||
/* FIXME!!! this test checks only mappings, defined by MSDN
|
||||
* It is necessary to add other mappings and to test them up to Windows XP.
|
||||
*
|
||||
* Some Windows platforms don't know about all the mappings, and in such
|
||||
@@ -46,7 +45,7 @@
|
||||
* (of course older Windows platforms will fail to pass the strict mode)
|
||||
*/
|
||||
|
||||
static ULONG (WINAPI *statustodoserror)(NTSTATUS Status);
|
||||
static ULONG (WINAPI *pRtlNtStatusToDosError)(NTSTATUS Status);
|
||||
static int strict;
|
||||
|
||||
static int prepare_test(void)
|
||||
@@ -56,8 +55,8 @@ static int prepare_test(void)
|
||||
char** argv;
|
||||
|
||||
ntdll = LoadLibraryA("ntdll.dll");
|
||||
statustodoserror = (void*)GetProcAddress(ntdll, "RtlNtStatusToDosError");
|
||||
if (!statustodoserror)
|
||||
pRtlNtStatusToDosError = (void*)GetProcAddress(ntdll, "RtlNtStatusToDosError");
|
||||
if (!pRtlNtStatusToDosError)
|
||||
return 0;
|
||||
|
||||
argc = winetest_get_mainargs(&argv);
|
||||
@@ -69,9 +68,9 @@ static void cmp_call(NTSTATUS win_nt, ULONG win32, const char* message)
|
||||
{
|
||||
ULONG err;
|
||||
|
||||
err = statustodoserror(win_nt);
|
||||
err = pRtlNtStatusToDosError(win_nt);
|
||||
ok(err == win32,
|
||||
"%s (%lx): got %ld, expected %ld\n",
|
||||
"%s (%x): got %u, expected %u\n",
|
||||
message, win_nt, err, win32);
|
||||
}
|
||||
|
||||
@@ -79,10 +78,10 @@ static void cmp_call2(NTSTATUS win_nt, ULONG win32, const char* message)
|
||||
{
|
||||
ULONG err;
|
||||
|
||||
err = statustodoserror(win_nt);
|
||||
err = pRtlNtStatusToDosError(win_nt);
|
||||
ok(err == win32 ||
|
||||
(!strict && err == ERROR_MR_MID_NOT_FOUND),
|
||||
"%s (%lx): got %ld, expected %ld (or MID_NOT_FOUND)\n",
|
||||
"%s (%x): got %u, expected %u (or MID_NOT_FOUND)\n",
|
||||
message, win_nt, err, win32);
|
||||
}
|
||||
|
||||
@@ -90,9 +89,9 @@ static void cmp_call3(NTSTATUS win_nt, ULONG win32_1, ULONG win32_2, const char*
|
||||
{
|
||||
ULONG err;
|
||||
|
||||
err = statustodoserror(win_nt);
|
||||
err = pRtlNtStatusToDosError(win_nt);
|
||||
ok(err == win32_1 || (!strict && err == win32_2),
|
||||
"%s (%lx): got %ld, expected %ld or %ld\n",
|
||||
"%s (%x): got %u, expected %u or %u\n",
|
||||
message, win_nt, err, win32_1, win32_2);
|
||||
}
|
||||
|
||||
@@ -100,10 +99,10 @@ static void cmp_call4(NTSTATUS win_nt, ULONG win32_1, ULONG win32_2, const char*
|
||||
{
|
||||
ULONG err;
|
||||
|
||||
err = statustodoserror(win_nt);
|
||||
err = pRtlNtStatusToDosError(win_nt);
|
||||
ok(err == win32_1 ||
|
||||
(!strict && (err == win32_2 || err == ERROR_MR_MID_NOT_FOUND)),
|
||||
"%s (%lx): got %ld, expected %ld or %ld\n",
|
||||
"%s (%x): got %u, expected %u or %u\n",
|
||||
message, win_nt, err, win32_1, win32_2);
|
||||
}
|
||||
|
||||
@@ -245,11 +244,11 @@ static void run_error_tests(void)
|
||||
cmp2(STATUS_PKINIT_FAILURE, ERROR_PKINIT_FAILURE);
|
||||
cmp2(STATUS_SMARTCARD_SUBSYSTEM_FAILURE, ERROR_SMARTCARD_SUBSYSTEM_FAILURE);
|
||||
cmp2(STATUS_DOWNGRADE_DETECTED, ERROR_DOWNGRADE_DETECTED);
|
||||
cmp2(STATUS_SMARTCARD_CERT_REVOKED, SEC_E_SMARTCARD_CERT_REVOKED);
|
||||
cmp2(STATUS_ISSUING_CA_UNTRUSTED, SEC_E_ISSUING_CA_UNTRUSTED);
|
||||
cmp2(STATUS_REVOCATION_OFFLINE_C, SEC_E_REVOCATION_OFFLINE_C);
|
||||
cmp2(STATUS_PKINIT_CLIENT_FAILURE, SEC_E_PKINIT_CLIENT_FAILURE);
|
||||
cmp2(STATUS_SMARTCARD_CERT_EXPIRED, SEC_E_SMARTCARD_CERT_EXPIRED);
|
||||
cmp4(STATUS_SMARTCARD_CERT_REVOKED, SEC_E_SMARTCARD_CERT_REVOKED, 1266); /* FIXME: real name? */
|
||||
cmp4(STATUS_ISSUING_CA_UNTRUSTED, SEC_E_ISSUING_CA_UNTRUSTED, 1267); /* FIXME: real name? */
|
||||
cmp4(STATUS_REVOCATION_OFFLINE_C, SEC_E_REVOCATION_OFFLINE_C, 1268); /* FIXME: real name? */
|
||||
cmp4(STATUS_PKINIT_CLIENT_FAILURE, SEC_E_PKINIT_CLIENT_FAILURE, 1269); /* FIXME: real name? */
|
||||
cmp4(STATUS_SMARTCARD_CERT_EXPIRED, SEC_E_SMARTCARD_CERT_EXPIRED, 1270); /* FIXME: real name? */
|
||||
cmp2(STATUS_NO_KERB_KEY, SEC_E_NO_KERB_KEY);
|
||||
cmp2(STATUS_CURRENT_DOMAIN_NOT_ALLOWED, ERROR_CURRENT_DOMAIN_NOT_ALLOWED);
|
||||
cmp2(STATUS_SMARTCARD_WRONG_PIN, SCARD_W_WRONG_CHV);
|
||||
|
||||
@@ -19,20 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x500 /* For NTSTATUS */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/ntndk.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
/*
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
@@ -41,14 +28,23 @@
|
||||
#include "winnt.h"
|
||||
#include "winreg.h"
|
||||
#include "winternl.h"
|
||||
#include "excpt.h"
|
||||
#include "wine/exception.h"
|
||||
#include "wine/test.h"
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __i386__
|
||||
static int my_argc;
|
||||
static char** my_argv;
|
||||
static int test_stage;
|
||||
|
||||
static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
||||
static NTSTATUS (WINAPI *pNtGetContextThread)(HANDLE,CONTEXT*);
|
||||
static NTSTATUS (WINAPI *pNtSetContextThread)(HANDLE,CONTEXT*);
|
||||
static NTSTATUS (WINAPI *pRtlRaiseException)(EXCEPTION_RECORD *rec);
|
||||
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG first, PVECTORED_EXCEPTION_HANDLER func);
|
||||
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID handler);
|
||||
static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
|
||||
static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
|
||||
static void *code_mem;
|
||||
|
||||
/* Test various instruction combinations that cause a protection fault on the i386,
|
||||
* and check what the resulting exception looks like.
|
||||
@@ -105,7 +101,7 @@ static const struct exception
|
||||
|
||||
/* test loading an invalid selector */
|
||||
{ { 0xb8, 0xef, 0xbe, 0x00, 0x00, 0x8e, 0xe8, 0xc3 }, /* mov $beef,%ax; mov %ax,%gs; ret */
|
||||
5, 2, STATUS_ACCESS_VIOLATION, 2, { 0, 0xbee8 } },
|
||||
5, 2, STATUS_ACCESS_VIOLATION, 2, { 0, 0xbee8 } }, /* 0xbee8 or 0xffffffff */
|
||||
|
||||
/* test accessing a zero selector */
|
||||
{ { 0x06, 0x31, 0xc0, 0x8e, 0xc0, 0x26, 0xa1, 0, 0, 0, 0, 0x07, 0xc3 },
|
||||
@@ -118,7 +114,7 @@ static const struct exception
|
||||
|
||||
/* test overlong instruction (limit is 16 bytes) */
|
||||
{ { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
|
||||
0, 16, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
0, 16, STATUS_ILLEGAL_INSTRUCTION, 0 },
|
||||
{ { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
|
||||
0, 15, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
|
||||
@@ -154,9 +150,9 @@ static const struct exception
|
||||
{ { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffc,%eax; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffc } },
|
||||
{ { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffd,%eax; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffd } },
|
||||
{ { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffe,%eax; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffe } },
|
||||
{ { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xffffffff,%eax; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
|
||||
@@ -164,14 +160,172 @@ static const struct exception
|
||||
{ { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffc; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffc } },
|
||||
{ { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffd; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffd } },
|
||||
{ { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffe; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffe } },
|
||||
{ { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xffffffff; ret */
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
0, 5, STATUS_ACCESS_VIOLATION, 2, { 1, 0xffffffff } },
|
||||
};
|
||||
|
||||
static int got_exception;
|
||||
static BOOL have_vectored_api;
|
||||
|
||||
static void run_exception_test(void *handler, const void* context,
|
||||
const void *code, unsigned int code_size)
|
||||
{
|
||||
struct {
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
const void *context;
|
||||
} exc_frame;
|
||||
void (*func)(void) = code_mem;
|
||||
|
||||
exc_frame.frame.Handler = handler;
|
||||
exc_frame.frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
exc_frame.context = context;
|
||||
|
||||
memcpy(code_mem, code, code_size);
|
||||
|
||||
pNtCurrentTeb()->Tib.ExceptionList = &exc_frame.frame;
|
||||
func();
|
||||
pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
|
||||
}
|
||||
|
||||
LONG CALLBACK rtlraiseexception_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
||||
{
|
||||
PCONTEXT context = ExceptionInfo->ContextRecord;
|
||||
PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
|
||||
trace("vect. handler %08x addr:%p context.Eip:%x\n", rec->ExceptionCode,
|
||||
rec->ExceptionAddress, context->Eip);
|
||||
|
||||
todo_wine {
|
||||
ok(rec->ExceptionAddress == (char *)code_mem + 0xb, "ExceptionAddress at %p instead of %p\n",
|
||||
rec->ExceptionAddress, (char *)code_mem + 0xb);
|
||||
|
||||
if (pNtCurrentTeb()->Peb->BeingDebugged)
|
||||
ok((void *)context->Eax == pRtlRaiseException, "debugger managed to modify Eax to %x should be %p\n",
|
||||
context->Eax, pRtlRaiseException);
|
||||
}
|
||||
|
||||
/* check that context.Eip is fixed up only for EXCEPTION_BREAKPOINT
|
||||
* even if raised by RtlRaiseException
|
||||
*/
|
||||
if(rec->ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||
{
|
||||
ok(context->Eip == (DWORD)code_mem + 0xa, "Eip at %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem + 0xa);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(context->Eip == (DWORD)code_mem + 0xb, "Eip at %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem + 0xb);
|
||||
}
|
||||
|
||||
/* test if context change is preserved from vectored handler to stack handlers */
|
||||
context->Eax = 0xf00f00f0;
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
static DWORD rtlraiseexception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
trace( "exception: %08x flags:%x addr:%p context: Eip:%x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, context->Eip );
|
||||
|
||||
todo_wine {
|
||||
ok(rec->ExceptionAddress == (char *)code_mem + 0xb, "ExceptionAddress at %p instead of %p\n",
|
||||
rec->ExceptionAddress, (char *)code_mem + 0xb);
|
||||
}
|
||||
|
||||
/* check that context.Eip is fixed up only for EXCEPTION_BREAKPOINT
|
||||
* even if raised by RtlRaiseException
|
||||
*/
|
||||
if(rec->ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||
{
|
||||
ok(context->Eip == (DWORD)code_mem + 0xa, "Eip at %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem + 0xa);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(context->Eip == (DWORD)code_mem + 0xb, "Eip at %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem + 0xb);
|
||||
}
|
||||
|
||||
if(have_vectored_api)
|
||||
ok(context->Eax == 0xf00f00f0, "Eax is %x, should have been set to 0xf00f00f0 in vectored handler\n",
|
||||
context->Eax);
|
||||
|
||||
/* give the debugger a chance to examine the state a second time */
|
||||
/* without the exception handler changing Eip */
|
||||
if (test_stage == 2)
|
||||
return ExceptionContinueSearch;
|
||||
|
||||
/* Eip in context is decreased by 1
|
||||
* Increase it again, else execution will continue in the middle of a instruction */
|
||||
if(rec->ExceptionCode == EXCEPTION_BREAKPOINT && (context->Eip == (DWORD)code_mem + 0xa))
|
||||
context->Eip += 1;
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
|
||||
static const BYTE call_one_arg_code[] = {
|
||||
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp),%eax */
|
||||
0x50, /* push %eax */
|
||||
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp),%eax */
|
||||
0xff, 0xd0, /* call *%eax */
|
||||
0x90, /* nop */
|
||||
0x90, /* nop */
|
||||
0x90, /* nop */
|
||||
0x90, /* nop */
|
||||
0xc3, /* ret */
|
||||
};
|
||||
|
||||
|
||||
static void run_rtlraiseexception_test(DWORD exceptioncode)
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
EXCEPTION_RECORD record;
|
||||
PVOID vectored_handler = NULL;
|
||||
|
||||
void (*func)(void* function, EXCEPTION_RECORD* record) = code_mem;
|
||||
|
||||
record.ExceptionCode = exceptioncode;
|
||||
record.ExceptionFlags = 0;
|
||||
record.ExceptionRecord = NULL;
|
||||
record.ExceptionAddress = NULL; /* does not matter, copied return address */
|
||||
record.NumberParameters = 0;
|
||||
|
||||
frame.Handler = rtlraiseexception_handler;
|
||||
frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
|
||||
memcpy(code_mem, call_one_arg_code, sizeof(call_one_arg_code));
|
||||
|
||||
pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
if (have_vectored_api)
|
||||
{
|
||||
vectored_handler = pRtlAddVectoredExceptionHandler(TRUE, &rtlraiseexception_vectored_handler);
|
||||
ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
|
||||
}
|
||||
|
||||
func(pRtlRaiseException, &record);
|
||||
|
||||
if (have_vectored_api)
|
||||
pRtlRemoveVectoredExceptionHandler(vectored_handler);
|
||||
pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
}
|
||||
|
||||
static void test_rtlraiseexception(void)
|
||||
{
|
||||
if (!pRtlRaiseException)
|
||||
{
|
||||
skip("RtlRaiseException not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* test without debugger */
|
||||
run_rtlraiseexception_test(0x12345);
|
||||
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
|
||||
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
@@ -180,24 +334,42 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
|
||||
unsigned int i, entry = except - exceptions;
|
||||
|
||||
got_exception++;
|
||||
trace( "exception: %lx flags:%lx addr:%p\n",
|
||||
trace( "exception: %x flags:%x addr:%p\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
|
||||
ok( rec->ExceptionCode == except->status,
|
||||
"%u: Wrong exception code %lx/%lx\n", entry, rec->ExceptionCode, except->status );
|
||||
ok( rec->ExceptionAddress == except->code + except->offset,
|
||||
"%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
|
||||
ok( rec->ExceptionAddress == (char*)code_mem + except->offset,
|
||||
"%u: Wrong exception address %p/%p\n", entry,
|
||||
rec->ExceptionAddress, except->code + except->offset );
|
||||
rec->ExceptionAddress, (char*)code_mem + except->offset );
|
||||
|
||||
ok( rec->NumberParameters == except->nb_params,
|
||||
"%u: Wrong number of parameters %lu/%lu\n", entry, rec->NumberParameters, except->nb_params );
|
||||
"%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
|
||||
|
||||
/* Most CPUs (except Intel Core apparently) report a segment limit violation */
|
||||
/* instead of page faults for accesses beyond 0xffffffff */
|
||||
if (except->nb_params == 2 && except->params[1] >= 0xfffffffd)
|
||||
{
|
||||
if (rec->ExceptionInformation[0] == 0 && rec->ExceptionInformation[1] == 0xffffffff)
|
||||
goto skip_params;
|
||||
}
|
||||
|
||||
/* Seems that both 0xbee8 and 0xfffffffff can be returned in windows */
|
||||
if (except->nb_params == 2 && rec->NumberParameters == 2
|
||||
&& except->params[1] == 0xbee8 && rec->ExceptionInformation[1] == 0xffffffff
|
||||
&& except->params[0] == rec->ExceptionInformation[0])
|
||||
{
|
||||
goto skip_params;
|
||||
}
|
||||
|
||||
for (i = 0; i < rec->NumberParameters; i++)
|
||||
ok( rec->ExceptionInformation[i] == except->params[i],
|
||||
"%u: Wrong parameter %d: %lx/%lx\n",
|
||||
"%u: Wrong parameter %d: %lx/%x\n",
|
||||
entry, i, rec->ExceptionInformation[i], except->params[i] );
|
||||
|
||||
skip_params:
|
||||
/* don't handle exception if it's not the address we expected */
|
||||
if (rec->ExceptionAddress != except->code + except->offset) return ExceptionContinueSearch;
|
||||
if (rec->ExceptionAddress != (char*)code_mem + except->offset) return ExceptionContinueSearch;
|
||||
|
||||
context->Eip += except->length;
|
||||
return ExceptionContinueExecution;
|
||||
@@ -206,28 +378,12 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
|
||||
static void test_prot_fault(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
const struct exception *except;
|
||||
} exc_frame;
|
||||
|
||||
pNtCurrentTeb = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtCurrentTeb" );
|
||||
if (!pNtCurrentTeb)
|
||||
{
|
||||
trace( "NtCurrentTeb not found, skipping tests\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
exc_frame.frame.Handler = handler;
|
||||
exc_frame.frame.Next = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
pNtCurrentTeb()->Tib.ExceptionList = &exc_frame.frame;
|
||||
for (i = 0; i < sizeof(exceptions)/sizeof(exceptions[0]); i++)
|
||||
{
|
||||
void (*func)(void) = (void *)exceptions[i].code;
|
||||
exc_frame.except = &exceptions[i];
|
||||
got_exception = 0;
|
||||
func();
|
||||
run_exception_test(handler, &exceptions[i], &exceptions[i].code,
|
||||
sizeof(exceptions[i].code));
|
||||
if (!i && !got_exception)
|
||||
{
|
||||
trace( "No exception, assuming win9x, no point in testing further\n" );
|
||||
@@ -236,7 +392,439 @@ static void test_prot_fault(void)
|
||||
ok( got_exception == (exceptions[i].status != 0),
|
||||
"%u: bad exception count %d\n", i, got_exception );
|
||||
}
|
||||
pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Next;
|
||||
}
|
||||
|
||||
/* test handling of debug registers */
|
||||
static DWORD dreg_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
context->Eip += 2; /* Skips the popl (%eax) */
|
||||
context->Dr0 = 0x42424242;
|
||||
context->Dr1 = 0;
|
||||
context->Dr2 = 0;
|
||||
context->Dr3 = 0;
|
||||
context->Dr6 = 0;
|
||||
context->Dr7 = 0x155;
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
static const BYTE segfault_code[5] = {
|
||||
0x31, 0xc0, /* xor %eax,%eax */
|
||||
0x8f, 0x00, /* popl (%eax) - cause exception */
|
||||
0xc3 /* ret */
|
||||
};
|
||||
|
||||
/* test the single step exception behaviour */
|
||||
static DWORD single_step_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
got_exception++;
|
||||
ok (!(context->EFlags & 0x100), "eflags has single stepping bit set\n");
|
||||
|
||||
if( got_exception < 3)
|
||||
context->EFlags |= 0x100; /* single step until popf instruction */
|
||||
else {
|
||||
/* show that the last single step exception on the popf instruction
|
||||
* (which removed the TF bit), still is a EXCEPTION_SINGLE_STEP exception */
|
||||
ok( rec->ExceptionCode == EXCEPTION_SINGLE_STEP,
|
||||
"exception is not EXCEPTION_SINGLE_STEP: %x\n", rec->ExceptionCode);
|
||||
}
|
||||
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
static const BYTE single_stepcode[] = {
|
||||
0x9c, /* pushf */
|
||||
0x58, /* pop %eax */
|
||||
0x0d,0,1,0,0, /* or $0x100,%eax */
|
||||
0x50, /* push %eax */
|
||||
0x9d, /* popf */
|
||||
0x35,0,1,0,0, /* xor $0x100,%eax */
|
||||
0x50, /* push %eax */
|
||||
0x9d, /* popf */
|
||||
0xc3
|
||||
};
|
||||
|
||||
/* Test the alignment check (AC) flag handling. */
|
||||
static const BYTE align_check_code[] = {
|
||||
0x55, /* push %ebp */
|
||||
0x89,0xe5, /* mov %esp,%ebp */
|
||||
0x9c, /* pushf */
|
||||
0x58, /* pop %eax */
|
||||
0x0d,0,0,4,0, /* or $0x40000,%eax */
|
||||
0x50, /* push %eax */
|
||||
0x9d, /* popf */
|
||||
0x89,0xe0, /* mov %esp, %eax */
|
||||
0x8b,0x40,0x1, /* mov 0x1(%eax), %eax - cause exception */
|
||||
0x9c, /* pushf */
|
||||
0x58, /* pop %eax */
|
||||
0x35,0,0,4,0, /* xor $0x40000,%eax */
|
||||
0x50, /* push %eax */
|
||||
0x9d, /* popf */
|
||||
0x5d, /* pop %ebp */
|
||||
0xc3, /* ret */
|
||||
};
|
||||
|
||||
static DWORD align_check_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
ok (!(context->EFlags & 0x40000), "eflags has AC bit set\n");
|
||||
got_exception++;
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
/* Test the direction flag handling. */
|
||||
static const BYTE direction_flag_code[] = {
|
||||
0x55, /* push %ebp */
|
||||
0x89,0xe5, /* mov %esp,%ebp */
|
||||
0xfd, /* std */
|
||||
0xfa, /* cli - cause exception */
|
||||
0x5d, /* pop %ebp */
|
||||
0xc3, /* ret */
|
||||
};
|
||||
|
||||
static DWORD direction_flag_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
unsigned int flags;
|
||||
__asm__("pushfl; popl %0" : "=r" (flags) );
|
||||
/* older windows versions don't clear DF properly so don't test */
|
||||
if (flags & 0x400) trace( "eflags has DF bit set\n" );
|
||||
#endif
|
||||
ok( context->EFlags & 0x400, "context eflags has DF bit cleared\n" );
|
||||
got_exception++;
|
||||
context->Eip++; /* skip cli */
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
/* test single stepping over hardware breakpoint */
|
||||
static DWORD bpx_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
got_exception++;
|
||||
ok( rec->ExceptionCode == EXCEPTION_SINGLE_STEP,
|
||||
"wrong exception code: %x\n", rec->ExceptionCode);
|
||||
|
||||
if(got_exception == 1) {
|
||||
/* hw bp exception on first nop */
|
||||
ok( context->Eip == (DWORD)code_mem, "eip is wrong: %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem);
|
||||
ok( (context->Dr6 & 0xf) == 1, "B0 flag is not set in Dr6\n");
|
||||
ok( !(context->Dr6 & 0x4000), "BS flag is set in Dr6\n");
|
||||
context->Dr0 = context->Dr0 + 1; /* set hw bp again on next instruction */
|
||||
context->EFlags |= 0x100; /* enable single stepping */
|
||||
} else if( got_exception == 2) {
|
||||
/* single step exception on second nop */
|
||||
ok( context->Eip == (DWORD)code_mem + 1, "eip is wrong: %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem + 1);
|
||||
ok( (context->Dr6 & 0x4000), "BS flag is not set in Dr6\n");
|
||||
/* depending on the win version the B0 bit is already set here as well
|
||||
ok( (context->Dr6 & 0xf) == 0, "B0...3 flags in Dr6 shouldn't be set\n"); */
|
||||
context->EFlags |= 0x100;
|
||||
} else if( got_exception == 3) {
|
||||
/* hw bp exception on second nop */
|
||||
ok( context->Eip == (DWORD)code_mem + 1, "eip is wrong: %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem + 1);
|
||||
ok( (context->Dr6 & 0xf) == 1, "B0 flag is not set in Dr6\n");
|
||||
ok( !(context->Dr6 & 0x4000), "BS flag is set in Dr6\n");
|
||||
context->Dr0 = 0; /* clear breakpoint */
|
||||
context->EFlags |= 0x100;
|
||||
} else {
|
||||
/* single step exception on ret */
|
||||
ok( context->Eip == (DWORD)code_mem + 2, "eip is wrong: %x instead of %x\n",
|
||||
context->Eip, (DWORD)code_mem + 2);
|
||||
ok( (context->Dr6 & 0xf) == 0, "B0...3 flags in Dr6 shouldn't be set\n");
|
||||
ok( (context->Dr6 & 0x4000), "BS flag is not set in Dr6\n");
|
||||
}
|
||||
|
||||
context->Dr6 = 0; /* clear status register */
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
static const BYTE dummy_code[] = { 0x90, 0x90, 0xc3 }; /* nop, nop, ret */
|
||||
|
||||
/* test int3 handling */
|
||||
static DWORD int3_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
ok( rec->ExceptionAddress == code_mem, "exception address not at: %p, but at %p\n",
|
||||
code_mem, rec->ExceptionAddress);
|
||||
ok( context->Eip == (DWORD)code_mem, "eip not at: %p, but at %#x\n", code_mem, context->Eip);
|
||||
if(context->Eip == (DWORD)code_mem) context->Eip++; /* skip breakpoint */
|
||||
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
static const BYTE int3_code[] = { 0xCC, 0xc3 }; /* int 3, ret */
|
||||
|
||||
|
||||
static void test_exceptions(void)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
NTSTATUS res;
|
||||
|
||||
if (!pNtGetContextThread || !pNtSetContextThread)
|
||||
{
|
||||
skip( "NtGetContextThread/NtSetContextThread not found\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* test handling of debug registers */
|
||||
run_exception_test(dreg_handler, NULL, &segfault_code, sizeof(segfault_code));
|
||||
|
||||
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
res = pNtGetContextThread(GetCurrentThread(), &ctx);
|
||||
ok (res == STATUS_SUCCESS,"NtGetContextThread failed with %x\n", res);
|
||||
ok(ctx.Dr0 == 0x42424242,"failed to set debugregister 0 to 0x42424242, got %x\n", ctx.Dr0);
|
||||
ok((ctx.Dr7 & ~0xdc00) == 0x155,"failed to set debugregister 7 to 0x155, got %x\n", ctx.Dr7);
|
||||
|
||||
/* test single stepping behavior */
|
||||
got_exception = 0;
|
||||
run_exception_test(single_step_handler, NULL, &single_stepcode, sizeof(single_stepcode));
|
||||
ok(got_exception == 3, "expected 3 single step exceptions, got %d\n", got_exception);
|
||||
|
||||
/* test alignment exceptions */
|
||||
got_exception = 0;
|
||||
run_exception_test(align_check_handler, NULL, align_check_code, sizeof(align_check_code));
|
||||
ok(got_exception == 0, "got %d alignment faults, expected 0\n", got_exception);
|
||||
|
||||
/* test direction flag */
|
||||
got_exception = 0;
|
||||
run_exception_test(direction_flag_handler, NULL, direction_flag_code, sizeof(direction_flag_code));
|
||||
ok(got_exception == 1, "got %d exceptions, expected 1\n", got_exception);
|
||||
|
||||
/* test single stepping over hardware breakpoint */
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.Dr0 = (DWORD) code_mem; /* set hw bp on first nop */
|
||||
ctx.Dr7 = 3;
|
||||
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
res = pNtSetContextThread( GetCurrentThread(), &ctx);
|
||||
ok( res == STATUS_SUCCESS, "NtSetContextThread faild with %x\n", res);
|
||||
|
||||
got_exception = 0;
|
||||
run_exception_test(bpx_handler, NULL, dummy_code, sizeof(dummy_code));
|
||||
ok( got_exception == 4,"expected 4 exceptions, got %d\n", got_exception);
|
||||
|
||||
/* test int3 handling */
|
||||
run_exception_test(int3_handler, NULL, int3_code, sizeof(int3_code));
|
||||
}
|
||||
|
||||
static void test_debugger(void)
|
||||
{
|
||||
char cmdline[MAX_PATH];
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si = { 0 };
|
||||
DEBUG_EVENT de;
|
||||
DWORD continuestatus;
|
||||
PVOID code_mem_address = NULL;
|
||||
NTSTATUS status;
|
||||
SIZE_T size_read;
|
||||
BOOL ret;
|
||||
int counter = 0;
|
||||
si.cb = sizeof(si);
|
||||
|
||||
if(!pNtGetContextThread || !pNtSetContextThread || !pNtReadVirtualMemory || !pNtTerminateProcess)
|
||||
{
|
||||
skip("NtGetContextThread, NtSetContextThread, NtReadVirtualMemory or NtTerminateProcess not found\n)");
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(cmdline, "%s %s %s %p", my_argv[0], my_argv[1], "debuggee", &test_stage);
|
||||
ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
|
||||
ok(ret, "could not create child process error: %u\n", GetLastError());
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
continuestatus = DBG_CONTINUE;
|
||||
ok(WaitForDebugEvent(&de, INFINITE), "reading debug event\n");
|
||||
|
||||
if (de.dwThreadId != pi.dwThreadId)
|
||||
{
|
||||
trace("event %d not coming from main thread, ignoring\n", de.dwDebugEventCode);
|
||||
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
|
||||
{
|
||||
if(de.u.CreateProcessInfo.lpBaseOfImage != pNtCurrentTeb()->Peb->ImageBaseAddress)
|
||||
{
|
||||
skip("child process loaded at different address, terminating it\n");
|
||||
pNtTerminateProcess(pi.hProcess, 0);
|
||||
}
|
||||
}
|
||||
else if (de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
int stage;
|
||||
|
||||
counter++;
|
||||
status = pNtReadVirtualMemory(pi.hProcess, &code_mem, &code_mem_address,
|
||||
sizeof(code_mem_address), &size_read);
|
||||
ok(!status,"NtReadVirtualMemory failed with 0x%x\n", status);
|
||||
status = pNtReadVirtualMemory(pi.hProcess, &test_stage, &stage,
|
||||
sizeof(stage), &size_read);
|
||||
ok(!status,"NtReadVirtualMemory failed with 0x%x\n", status);
|
||||
|
||||
ctx.ContextFlags = CONTEXT_FULL;
|
||||
status = pNtGetContextThread(pi.hThread, &ctx);
|
||||
ok(!status, "NtGetContextThread failed with 0x%x\n", status);
|
||||
|
||||
trace("exception 0x%x at %p firstchance=%d Eip=0x%x, Eax=0x%x\n",
|
||||
de.u.Exception.ExceptionRecord.ExceptionCode,
|
||||
de.u.Exception.ExceptionRecord.ExceptionAddress, de.u.Exception.dwFirstChance, ctx.Eip, ctx.Eax);
|
||||
|
||||
if (counter > 100)
|
||||
{
|
||||
ok(FALSE, "got way too many exceptions, probaby caught in a infinite loop, terminating child\n");
|
||||
pNtTerminateProcess(pi.hProcess, 1);
|
||||
}
|
||||
else if (counter >= 2) /* skip startup breakpoint */
|
||||
{
|
||||
if (stage == 1)
|
||||
{
|
||||
ok((char *)ctx.Eip == (char *)code_mem_address + 0xb, "Eip at %x instead of %p\n",
|
||||
ctx.Eip, (char *)code_mem_address + 0xb);
|
||||
/* setting the context from debugger does not affect the context, the exception handlers gets */
|
||||
/* uncomment once wine is fixed */
|
||||
/* ctx.Eip = 0x12345; */
|
||||
ctx.Eax = 0xf00f00f1;
|
||||
|
||||
/* let the debuggee handle the exception */
|
||||
continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||
}
|
||||
else if (stage == 2)
|
||||
{
|
||||
if (de.u.Exception.dwFirstChance)
|
||||
{
|
||||
/* debugger gets first chance exception with unmodified ctx.Eip */
|
||||
ok((char *)ctx.Eip == (char *)code_mem_address + 0xb, "Eip at 0x%x instead of %p\n",
|
||||
ctx.Eip, (char *)code_mem_address + 0xb);
|
||||
|
||||
/* setting the context from debugger does not affect the context, the exception handlers gets */
|
||||
/* uncomment once wine is fixed */
|
||||
/* ctx.Eip = 0x12345; */
|
||||
ctx.Eax = 0xf00f00f1;
|
||||
|
||||
/* pass exception to debuggee
|
||||
* exception will not be handled and
|
||||
* a second chance exception will be raised */
|
||||
continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* debugger gets context after exception handler has played with it */
|
||||
/* ctx.Eip is the same value the exception handler got */
|
||||
if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||
{
|
||||
ok((char *)ctx.Eip == (char *)code_mem_address + 0xa, "Eip at 0x%x instead of %p\n",
|
||||
ctx.Eip, (char *)code_mem_address + 0xa);
|
||||
/* need to fixup Eip for debuggee */
|
||||
if ((char *)ctx.Eip == (char *)code_mem_address + 0xa)
|
||||
ctx.Eip += 1;
|
||||
}
|
||||
else
|
||||
ok((char *)ctx.Eip == (char *)code_mem_address + 0xb, "Eip at 0x%x instead of %p\n",
|
||||
ctx.Eip, (char *)code_mem_address + 0xb);
|
||||
/* here we handle exception */
|
||||
}
|
||||
}
|
||||
else
|
||||
ok(FALSE, "unexpected stage %x\n", stage);
|
||||
|
||||
status = pNtSetContextThread(pi.hThread, &ctx);
|
||||
ok(!status, "NtSetContextThread failed with 0x%x\n", status);
|
||||
}
|
||||
}
|
||||
|
||||
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, continuestatus);
|
||||
|
||||
} while (de.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
|
||||
|
||||
winetest_wait_child_process( pi.hProcess );
|
||||
ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
|
||||
ok(CloseHandle(pi.hProcess) != 0, "error %u\n", GetLastError());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static DWORD simd_fault_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
int *stage = *(int **)(frame + 1);
|
||||
|
||||
got_exception++;
|
||||
|
||||
if( *stage == 1) {
|
||||
/* fault while executing sse instruction */
|
||||
context->Eip += 3; /* skip addps */
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
/* stage 2 - divide by zero fault */
|
||||
if( rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)
|
||||
skip("system doesn't support SIMD exceptions\n");
|
||||
else {
|
||||
ok( rec->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS,
|
||||
"exception code: %#x, should be %#x\n",
|
||||
rec->ExceptionCode, STATUS_FLOAT_MULTIPLE_TRAPS);
|
||||
ok( rec->NumberParameters == 1, "# of params: %i, should be 1\n",
|
||||
rec->NumberParameters);
|
||||
if( rec->NumberParameters == 1 )
|
||||
ok( rec->ExceptionInformation[0] == 0, "param #1: %lx, should be 0\n", rec->ExceptionInformation[0]);
|
||||
}
|
||||
|
||||
context->Eip += 3; /* skip divps */
|
||||
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
static const BYTE simd_exception_test[] = {
|
||||
0x83, 0xec, 0x4, /* sub $0x4, %esp */
|
||||
0x0f, 0xae, 0x1c, 0x24, /* stmxcsr (%esp) */
|
||||
0x66, 0x81, 0x24, 0x24, 0xff, 0xfd, /* andw $0xfdff,(%esp) * enable divide by */
|
||||
0x0f, 0xae, 0x14, 0x24, /* ldmxcsr (%esp) * zero exceptions */
|
||||
0x6a, 0x01, /* push $0x1 */
|
||||
0x6a, 0x01, /* push $0x1 */
|
||||
0x6a, 0x01, /* push $0x1 */
|
||||
0x6a, 0x01, /* push $0x1 */
|
||||
0x0f, 0x10, 0x0c, 0x24, /* movups (%esp),%xmm1 * fill dividend */
|
||||
0x0f, 0x57, 0xc0, /* xorps %xmm0,%xmm0 * clear divisor */
|
||||
0x0f, 0x5e, 0xc8, /* divps %xmm0,%xmm1 * generate fault */
|
||||
0x83, 0xc4, 0x10, /* add $0x10,%esp */
|
||||
0x66, 0x81, 0x0c, 0x24, 0x00, 0x02, /* orw $0x200,(%esp) * disable exceptions */
|
||||
0x0f, 0xae, 0x14, 0x24, /* ldmxcsr (%esp) */
|
||||
0x83, 0xc4, 0x04, /* add $0x4,%esp */
|
||||
0xc3, /* ret */
|
||||
};
|
||||
|
||||
static const BYTE sse_check[] = {
|
||||
0x0f, 0x58, 0xc8, /* addps %xmm0,%xmm1 */
|
||||
0xc3, /* ret */
|
||||
};
|
||||
|
||||
static void test_simd_exceptions(void)
|
||||
{
|
||||
int stage;
|
||||
|
||||
/* test if CPU & OS can do sse */
|
||||
stage = 1;
|
||||
got_exception = 0;
|
||||
run_exception_test(simd_fault_handler, &stage, sse_check, sizeof(sse_check));
|
||||
if(got_exception) {
|
||||
skip("system doesn't support SSE\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* generate a SIMD exception */
|
||||
stage = 2;
|
||||
got_exception = 0;
|
||||
run_exception_test(simd_fault_handler, &stage, simd_exception_test,
|
||||
sizeof(simd_exception_test));
|
||||
ok( got_exception == 1, "got exception: %i, should be 1\n", got_exception);
|
||||
}
|
||||
|
||||
#endif /* __i386__ */
|
||||
@@ -244,6 +832,79 @@ static void test_prot_fault(void)
|
||||
START_TEST(exception)
|
||||
{
|
||||
#ifdef __i386__
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||
|
||||
pNtCurrentTeb = (void *)GetProcAddress( hntdll, "NtCurrentTeb" );
|
||||
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread" );
|
||||
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread" );
|
||||
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
|
||||
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException" );
|
||||
pNtTerminateProcess = (void *)GetProcAddress( hntdll, "NtTerminateProcess" );
|
||||
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll,
|
||||
"RtlAddVectoredExceptionHandler" );
|
||||
pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll,
|
||||
"RtlRemoveVectoredExceptionHandler" );
|
||||
if (!pNtCurrentTeb)
|
||||
{
|
||||
skip( "NtCurrentTeb not found\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
|
||||
have_vectored_api = TRUE;
|
||||
else
|
||||
skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
|
||||
|
||||
/* 1024 byte should be sufficient */
|
||||
code_mem = VirtualAlloc(NULL, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
if(!code_mem) {
|
||||
trace("VirtualAlloc failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
my_argc = winetest_get_mainargs( &my_argv );
|
||||
if (my_argc >= 4)
|
||||
{
|
||||
void *addr;
|
||||
sscanf( my_argv[3], "%p", &addr );
|
||||
|
||||
if (addr != &test_stage)
|
||||
{
|
||||
skip( "child process not mapped at same address (%p/%p)\n", &test_stage, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* child must be run under a debugger */
|
||||
if (!pNtCurrentTeb()->Peb->BeingDebugged)
|
||||
{
|
||||
ok(FALSE, "child process not being debugged?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pRtlRaiseException)
|
||||
{
|
||||
test_stage = 1;
|
||||
run_rtlraiseexception_test(0x12345);
|
||||
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
|
||||
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
|
||||
test_stage = 2;
|
||||
run_rtlraiseexception_test(0x12345);
|
||||
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
|
||||
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
|
||||
}
|
||||
else
|
||||
skip( "RtlRaiseException not found\n" );
|
||||
|
||||
/* rest of tests only run in parent */
|
||||
return;
|
||||
}
|
||||
|
||||
test_prot_fault();
|
||||
test_exceptions();
|
||||
test_rtlraiseexception();
|
||||
test_debugger();
|
||||
test_simd_exceptions();
|
||||
|
||||
VirtualFree(code_mem, 1024, MEM_RELEASE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,627 @@
|
||||
/* Unit test suite for Ntdll file functions
|
||||
*
|
||||
* Copyright 2007 Jeff Latimer
|
||||
* Copyright 2007 Andrey Turkin
|
||||
*
|
||||
* 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
|
||||
* We use function pointers here as there is no import library for NTDLL on
|
||||
* windows.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
|
||||
/* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
|
||||
* definition errors when we get to winnt.h
|
||||
*/
|
||||
#define WIN32_NO_STATUS
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "winternl.h"
|
||||
|
||||
#ifndef IO_COMPLETION_ALL_ACCESS
|
||||
#define IO_COMPLETION_ALL_ACCESS 0x001F0003
|
||||
#endif
|
||||
|
||||
static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
|
||||
static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
|
||||
ULONG, ULONG, ULONG, PLARGE_INTEGER );
|
||||
static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
|
||||
PIO_APC_ROUTINE apc, void* apc_user,
|
||||
PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
|
||||
PLARGE_INTEGER offset, PULONG key);
|
||||
static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
|
||||
PIO_APC_ROUTINE apc, void* apc_user,
|
||||
PIO_STATUS_BLOCK io_status,
|
||||
const void* buffer, ULONG length,
|
||||
PLARGE_INTEGER offset, PULONG key);
|
||||
static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
|
||||
|
||||
static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
|
||||
static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
|
||||
static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||
static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
|
||||
static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, ULONG);
|
||||
static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
|
||||
|
||||
static inline BOOL is_signaled( HANDLE obj )
|
||||
{
|
||||
return WaitForSingleObject( obj, 0 ) == 0;
|
||||
}
|
||||
|
||||
#define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
|
||||
|
||||
static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
|
||||
{
|
||||
*read = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
|
||||
1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
|
||||
ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
|
||||
|
||||
*write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||
ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HANDLE create_temp_file( ULONG flags )
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
HANDLE handle;
|
||||
|
||||
GetTempFileNameA( ".", "foo", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
|
||||
}
|
||||
|
||||
#define CVALUE_FIRST 0xfffabbcc
|
||||
#define CKEY_FIRST 0x1030341
|
||||
#define CKEY_SECOND 0x132E46
|
||||
|
||||
ULONG_PTR completionKey;
|
||||
IO_STATUS_BLOCK ioSb;
|
||||
ULONG_PTR completionValue;
|
||||
|
||||
static long get_pending_msgs(HANDLE h)
|
||||
{
|
||||
NTSTATUS res;
|
||||
ULONG a, req;
|
||||
|
||||
res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, (PVOID)&a, sizeof(a), &req );
|
||||
ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
|
||||
if (res != STATUS_SUCCESS) return -1;
|
||||
ok( req == sizeof(a), "Unexpected response size: %x\n", req );
|
||||
return a;
|
||||
}
|
||||
|
||||
static BOOL get_msg(HANDLE h)
|
||||
{
|
||||
LARGE_INTEGER timeout = {{-10000000*3}};
|
||||
DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
|
||||
ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
|
||||
if (res != STATUS_SUCCESS)
|
||||
{
|
||||
completionKey = completionValue = 0;
|
||||
memset(&ioSb, 0, sizeof(ioSb));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
|
||||
{
|
||||
int *count = arg;
|
||||
|
||||
trace( "apc called block %p iosb.status %x iosb.info %lu\n",
|
||||
iosb, U(*iosb).Status, iosb->Information );
|
||||
(*count)++;
|
||||
ok( !reserved, "reserved is not 0: %x\n", reserved );
|
||||
}
|
||||
|
||||
static void read_file_test(void)
|
||||
{
|
||||
const char text[] = "foobar";
|
||||
HANDLE handle, read, write;
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
DWORD written;
|
||||
int apc_count = 0;
|
||||
char buffer[128];
|
||||
LARGE_INTEGER offset;
|
||||
HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
|
||||
|
||||
buffer[0] = 1;
|
||||
|
||||
if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
|
||||
|
||||
/* try read with no data */
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
ok( is_signaled( read ), "read handle is not signaled\n" );
|
||||
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
|
||||
ok( status == STATUS_PENDING, "wrong status %x\n", status );
|
||||
ok( !is_signaled( read ), "read handle is signaled\n" );
|
||||
ok( !is_signaled( event ), "event is signaled\n" );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
/* iosb updated here by async i/o */
|
||||
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
|
||||
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
|
||||
ok( !is_signaled( read ), "read handle is signaled\n" );
|
||||
ok( is_signaled( event ), "event is not signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
apc_count = 0;
|
||||
SleepEx( 1, FALSE ); /* non-alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc not called\n" );
|
||||
|
||||
/* with no event, the pipe handle itself gets signaled */
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
ok( !is_signaled( read ), "read handle is not signaled\n" );
|
||||
status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
|
||||
ok( status == STATUS_PENDING, "wrong status %x\n", status );
|
||||
ok( !is_signaled( read ), "read handle is signaled\n" );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
/* iosb updated here by async i/o */
|
||||
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
|
||||
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( read ), "read handle is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
apc_count = 0;
|
||||
SleepEx( 1, FALSE ); /* non-alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc not called\n" );
|
||||
|
||||
/* now read with data ready */
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
ResetEvent( event );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
|
||||
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is not signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, FALSE ); /* non-alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc not called\n" );
|
||||
|
||||
/* try read with no data */
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
|
||||
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
|
||||
ok( status == STATUS_PENDING, "wrong status %x\n", status );
|
||||
ok( !is_signaled( event ), "event is signaled\n" );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
/* partial read is good enough */
|
||||
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc was not called\n" );
|
||||
|
||||
/* read from disconnected pipe */
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
CloseHandle( write );
|
||||
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
|
||||
ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
CloseHandle( read );
|
||||
|
||||
/* read from closed handle */
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
SetEvent( event );
|
||||
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
|
||||
ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" ); /* not reset on invalid handle */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
|
||||
/* disconnect while async read is in progress */
|
||||
if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
|
||||
ok( status == STATUS_PENDING, "wrong status %x\n", status );
|
||||
ok( !is_signaled( event ), "event is signaled\n" );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
CloseHandle( write );
|
||||
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
|
||||
ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc was not called\n" );
|
||||
CloseHandle( read );
|
||||
|
||||
/* now try a real file */
|
||||
if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
offset.QuadPart = 0;
|
||||
ResetEvent( event );
|
||||
pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
|
||||
ok( status == STATUS_PENDING, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc was not called\n" );
|
||||
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
offset.QuadPart = 0;
|
||||
ResetEvent( event );
|
||||
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
|
||||
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc was not called\n" );
|
||||
|
||||
/* read beyond eof */
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
offset.QuadPart = strlen(text) + 2;
|
||||
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
|
||||
ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
CloseHandle( handle );
|
||||
|
||||
/* now a non-overlapped file */
|
||||
if (!(handle = create_temp_file(0))) return;
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
offset.QuadPart = 0;
|
||||
pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
|
||||
ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc was not called\n" );
|
||||
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
offset.QuadPart = 0;
|
||||
ResetEvent( event );
|
||||
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
|
||||
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
todo_wine ok( !apc_count, "apc was called\n" );
|
||||
|
||||
/* read beyond eof */
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
offset.QuadPart = strlen(text) + 2;
|
||||
ResetEvent( event );
|
||||
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
|
||||
ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
|
||||
todo_wine ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
|
||||
todo_wine ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
|
||||
todo_wine ok( is_signaled( event ), "event is not signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
|
||||
CloseHandle( handle );
|
||||
|
||||
CloseHandle( event );
|
||||
}
|
||||
|
||||
static void nt_mailslot_test(void)
|
||||
{
|
||||
HANDLE hslot;
|
||||
ACCESS_MASK DesiredAccess;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
|
||||
ULONG CreateOptions;
|
||||
ULONG MailslotQuota;
|
||||
ULONG MaxMessageSize;
|
||||
LARGE_INTEGER TimeOut;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS rc;
|
||||
UNICODE_STRING str;
|
||||
WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
|
||||
'R',':','\\','F','R','E','D','\0' };
|
||||
|
||||
TimeOut.QuadPart = -1;
|
||||
|
||||
pRtlInitUnicodeString(&str, buffer1);
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
DesiredAccess = CreateOptions = MailslotQuota = MaxMessageSize = 0;
|
||||
|
||||
/*
|
||||
* Check for NULL pointer handling
|
||||
*/
|
||||
rc = pNtCreateMailslotFile(NULL, DesiredAccess,
|
||||
&attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
|
||||
&TimeOut);
|
||||
ok( rc == STATUS_ACCESS_VIOLATION, "rc = %x not c0000005 STATUS_ACCESS_VIOLATION\n", rc);
|
||||
|
||||
/*
|
||||
* Test to see if the Timeout can be NULL
|
||||
*/
|
||||
rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
|
||||
&attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
|
||||
NULL);
|
||||
ok( rc == STATUS_SUCCESS, "rc = %x not STATUS_SUCCESS\n", rc);
|
||||
ok( hslot != 0, "Handle is invalid\n");
|
||||
|
||||
if ( rc == STATUS_SUCCESS ) rc = pNtClose(hslot);
|
||||
|
||||
/*
|
||||
* Test that the length field is checked properly
|
||||
*/
|
||||
attr.Length = 0;
|
||||
rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
|
||||
&attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
|
||||
&TimeOut);
|
||||
todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
|
||||
|
||||
if (rc == STATUS_SUCCESS) pNtClose(hslot);
|
||||
|
||||
attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
|
||||
rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
|
||||
&attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
|
||||
&TimeOut);
|
||||
todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
|
||||
|
||||
if (rc == STATUS_SUCCESS) pNtClose(hslot);
|
||||
|
||||
/*
|
||||
* Test handling of a NULL unicode string in ObjectName
|
||||
*/
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
attr.ObjectName = NULL;
|
||||
rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
|
||||
&attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
|
||||
&TimeOut);
|
||||
ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD, "rc = %x not c000003b STATUS_OBJECT_PATH_SYNTAX_BAD\n", rc);
|
||||
|
||||
if (rc == STATUS_SUCCESS) pNtClose(hslot);
|
||||
|
||||
/*
|
||||
* Test a valid call
|
||||
*/
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
|
||||
&attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
|
||||
&TimeOut);
|
||||
ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x %u\n", rc, GetLastError());
|
||||
ok( hslot != 0, "Handle is invalid\n");
|
||||
|
||||
rc = pNtClose(hslot);
|
||||
ok( rc == STATUS_SUCCESS, "NtClose failed\n");
|
||||
}
|
||||
|
||||
static void test_iocp_setcompletion(HANDLE h)
|
||||
{
|
||||
NTSTATUS res;
|
||||
long count;
|
||||
|
||||
res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
|
||||
ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
|
||||
|
||||
count = get_pending_msgs(h);
|
||||
ok( count == 1, "Unexpected msg count: %ld\n", count );
|
||||
|
||||
if (get_msg(h))
|
||||
{
|
||||
ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
|
||||
ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
|
||||
ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
|
||||
ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
|
||||
}
|
||||
|
||||
count = get_pending_msgs(h);
|
||||
ok( !count, "Unexpected msg count: %ld\n", count );
|
||||
}
|
||||
|
||||
static void test_iocp_fileio(HANDLE h)
|
||||
{
|
||||
static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
|
||||
|
||||
IO_STATUS_BLOCK iosb;
|
||||
FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
|
||||
HANDLE hPipeSrv, hPipeClt;
|
||||
NTSTATUS res;
|
||||
|
||||
hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
|
||||
ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
|
||||
if (hPipeSrv != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
|
||||
ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
|
||||
if (hPipeClt != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
|
||||
ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
|
||||
CloseHandle(hPipeClt);
|
||||
}
|
||||
CloseHandle( hPipeSrv );
|
||||
}
|
||||
|
||||
hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
|
||||
ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
|
||||
if (hPipeSrv == INVALID_HANDLE_VALUE )
|
||||
return;
|
||||
|
||||
hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
|
||||
ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
|
||||
if (hPipeClt != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
OVERLAPPED o = {0,};
|
||||
BYTE buf[3];
|
||||
DWORD read;
|
||||
long count;
|
||||
|
||||
NTSTATUS res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
|
||||
ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
|
||||
|
||||
count = get_pending_msgs(h);
|
||||
ok( !count, "Unexpected msg count: %ld\n", count );
|
||||
ReadFile( hPipeSrv, buf, 3, &read, &o);
|
||||
count = get_pending_msgs(h);
|
||||
ok( !count, "Unexpected msg count: %ld\n", count );
|
||||
WriteFile( hPipeClt, buf, 3, &read, NULL );
|
||||
|
||||
if (get_msg(h))
|
||||
{
|
||||
ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
|
||||
ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
|
||||
ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
|
||||
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
|
||||
}
|
||||
count = get_pending_msgs(h);
|
||||
ok( !count, "Unexpected msg count: %ld\n", count );
|
||||
|
||||
WriteFile( hPipeClt, buf, 2, &read, NULL );
|
||||
count = get_pending_msgs(h);
|
||||
ok( !count, "Unexpected msg count: %ld\n", count );
|
||||
ReadFile( hPipeSrv, buf, 2, &read, &o);
|
||||
count = get_pending_msgs(h);
|
||||
ok( count == 1, "Unexpected msg count: %ld\n", count );
|
||||
if (get_msg(h))
|
||||
{
|
||||
ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
|
||||
ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
|
||||
ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
|
||||
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
|
||||
}
|
||||
|
||||
ReadFile( hPipeSrv, buf, sizeof(buf), &read, &o);
|
||||
CloseHandle( hPipeSrv );
|
||||
count = get_pending_msgs(h);
|
||||
ok( count == 1, "Unexpected msg count: %ld\n", count );
|
||||
if (get_msg(h))
|
||||
{
|
||||
ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
|
||||
ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
|
||||
/* wine sends wrong status here */
|
||||
todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
|
||||
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle( hPipeClt );
|
||||
}
|
||||
|
||||
static void test_iocompletion(void)
|
||||
{
|
||||
HANDLE h = INVALID_HANDLE_VALUE;
|
||||
NTSTATUS res;
|
||||
|
||||
res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
|
||||
|
||||
ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
|
||||
ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
|
||||
|
||||
if ( h && h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
test_iocp_setcompletion(h);
|
||||
test_iocp_fileio(h);
|
||||
pNtClose(h);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(file)
|
||||
{
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||
if (!hntdll)
|
||||
{
|
||||
skip("not running on NT, skipping test\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
|
||||
pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
|
||||
pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
|
||||
pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
|
||||
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
|
||||
pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
|
||||
pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
|
||||
pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
|
||||
pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
|
||||
pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
|
||||
pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
|
||||
|
||||
read_file_test();
|
||||
nt_mailslot_test();
|
||||
test_iocompletion();
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "wine/test.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Compability macros
|
||||
* Compatibility macros
|
||||
*/
|
||||
|
||||
#define DWORD_PTR UINT_PTR
|
||||
@@ -635,48 +635,8 @@ static void test_pack_IMAGE_LOAD_CONFIG_DIRECTORY(void)
|
||||
|
||||
static void test_pack_IMAGE_NT_HEADERS(void)
|
||||
{
|
||||
/* IMAGE_NT_HEADERS (pack 4) */
|
||||
/* IMAGE_NT_HEADERS */
|
||||
TEST_TYPE(IMAGE_NT_HEADERS, 248, 4);
|
||||
TEST_FIELD(IMAGE_NT_HEADERS, DWORD, Signature, 0, 4, 4);
|
||||
TEST_FIELD(IMAGE_NT_HEADERS, IMAGE_FILE_HEADER, FileHeader, 4, 20, 4);
|
||||
TEST_FIELD(IMAGE_NT_HEADERS, IMAGE_OPTIONAL_HEADER, OptionalHeader, 24, 224, 4);
|
||||
}
|
||||
|
||||
static void test_pack_IMAGE_OPTIONAL_HEADER(void)
|
||||
{
|
||||
/* IMAGE_OPTIONAL_HEADER (pack 4) */
|
||||
TEST_TYPE(IMAGE_OPTIONAL_HEADER, 224, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, Magic, 0, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, BYTE, MajorLinkerVersion, 2, 1, 1);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, BYTE, MinorLinkerVersion, 3, 1, 1);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfCode, 4, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfInitializedData, 8, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfUninitializedData, 12, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, AddressOfEntryPoint, 16, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, BaseOfCode, 20, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, BaseOfData, 24, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, ImageBase, 28, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SectionAlignment, 32, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, FileAlignment, 36, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, MajorOperatingSystemVersion, 40, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, MinorOperatingSystemVersion, 42, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, MajorImageVersion, 44, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, MinorImageVersion, 46, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, MajorSubsystemVersion, 48, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, MinorSubsystemVersion, 50, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, Win32VersionValue, 52, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfImage, 56, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfHeaders, 60, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, CheckSum, 64, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, Subsystem, 68, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, WORD, DllCharacteristics, 70, 2, 2);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfStackReserve, 72, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfStackCommit, 76, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfHeapReserve, 80, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, SizeOfHeapCommit, 84, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, LoaderFlags, 88, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, DWORD, NumberOfRvaAndSizes, 92, 4, 4);
|
||||
TEST_FIELD(IMAGE_OPTIONAL_HEADER, IMAGE_DATA_DIRECTORY[IMAGE_NUMBEROF_DIRECTORY_ENTRIES], DataDirectory, 96, 128, 4);
|
||||
}
|
||||
|
||||
static void test_pack_IMAGE_OS2_HEADER(void)
|
||||
@@ -795,19 +755,13 @@ static void test_pack_IMAGE_SYMBOL(void)
|
||||
|
||||
static void test_pack_IMAGE_THUNK_DATA(void)
|
||||
{
|
||||
/* IMAGE_THUNK_DATA (pack 4) */
|
||||
/* IMAGE_THUNK_DATA */
|
||||
}
|
||||
|
||||
static void test_pack_IMAGE_TLS_DIRECTORY(void)
|
||||
{
|
||||
/* IMAGE_TLS_DIRECTORY (pack 4) */
|
||||
/* IMAGE_TLS_DIRECTORY */
|
||||
TEST_TYPE(IMAGE_TLS_DIRECTORY, 24, 4);
|
||||
TEST_FIELD(IMAGE_TLS_DIRECTORY, DWORD, StartAddressOfRawData, 0, 4, 4);
|
||||
TEST_FIELD(IMAGE_TLS_DIRECTORY, DWORD, EndAddressOfRawData, 4, 4, 4);
|
||||
TEST_FIELD(IMAGE_TLS_DIRECTORY, LPDWORD, AddressOfIndex, 8, 4, 4);
|
||||
TEST_FIELD(IMAGE_TLS_DIRECTORY, PIMAGE_TLS_CALLBACK *, AddressOfCallBacks, 12, 4, 4);
|
||||
TEST_FIELD(IMAGE_TLS_DIRECTORY, DWORD, SizeOfZeroFill, 16, 4, 4);
|
||||
TEST_FIELD(IMAGE_TLS_DIRECTORY, DWORD, Characteristics, 20, 4, 4);
|
||||
}
|
||||
|
||||
static void test_pack_IMAGE_VXD_HEADER(void)
|
||||
@@ -920,12 +874,6 @@ static void test_pack_LONGLONG(void)
|
||||
TEST_TYPE_SIGNED(LONGLONG);
|
||||
}
|
||||
|
||||
static void test_pack_LPTOP_LEVEL_EXCEPTION_FILTER(void)
|
||||
{
|
||||
/* LPTOP_LEVEL_EXCEPTION_FILTER */
|
||||
TEST_TYPE(LPTOP_LEVEL_EXCEPTION_FILTER, 4, 4);
|
||||
}
|
||||
|
||||
static void test_pack_LUID(void)
|
||||
{
|
||||
/* LUID (pack 4) */
|
||||
@@ -949,7 +897,7 @@ static void test_pack_MEMORY_BASIC_INFORMATION(void)
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, LPVOID, BaseAddress, 0, 4, 4);
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, LPVOID, AllocationBase, 4, 4, 4);
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, DWORD, AllocationProtect, 8, 4, 4);
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, DWORD, RegionSize, 12, 4, 4);
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, SIZE_T, RegionSize, 12, 4, 4);
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, DWORD, State, 16, 4, 4);
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, DWORD, Protect, 20, 4, 4);
|
||||
TEST_FIELD(MEMORY_BASIC_INFORMATION, DWORD, Type, 24, 4, 4);
|
||||
@@ -1250,14 +1198,12 @@ static void test_pack_PIMAGE_NT_HEADERS(void)
|
||||
{
|
||||
/* PIMAGE_NT_HEADERS */
|
||||
TEST_TYPE(PIMAGE_NT_HEADERS, 4, 4);
|
||||
TEST_TYPE_POINTER(PIMAGE_NT_HEADERS, 248, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PIMAGE_OPTIONAL_HEADER(void)
|
||||
{
|
||||
/* PIMAGE_OPTIONAL_HEADER */
|
||||
TEST_TYPE(PIMAGE_OPTIONAL_HEADER, 4, 4);
|
||||
TEST_TYPE_POINTER(PIMAGE_OPTIONAL_HEADER, 224, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PIMAGE_OS2_HEADER(void)
|
||||
@@ -1342,7 +1288,6 @@ static void test_pack_PIMAGE_TLS_DIRECTORY(void)
|
||||
{
|
||||
/* PIMAGE_TLS_DIRECTORY */
|
||||
TEST_TYPE(PIMAGE_TLS_DIRECTORY, 4, 4);
|
||||
TEST_TYPE_POINTER(PIMAGE_TLS_DIRECTORY, 24, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PIMAGE_VXD_HEADER(void)
|
||||
@@ -1482,7 +1427,6 @@ static void test_pack_PRTL_CRITICAL_SECTION_DEBUG(void)
|
||||
{
|
||||
/* PRTL_CRITICAL_SECTION_DEBUG */
|
||||
TEST_TYPE(PRTL_CRITICAL_SECTION_DEBUG, 4, 4);
|
||||
TEST_TYPE_POINTER(PRTL_CRITICAL_SECTION_DEBUG, 32, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PRTL_OSVERSIONINFOEXW(void)
|
||||
@@ -1503,7 +1447,6 @@ static void test_pack_PRTL_RESOURCE_DEBUG(void)
|
||||
{
|
||||
/* PRTL_RESOURCE_DEBUG */
|
||||
TEST_TYPE(PRTL_RESOURCE_DEBUG, 4, 4);
|
||||
TEST_TYPE_POINTER(PRTL_RESOURCE_DEBUG, 32, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PSECURITY_DESCRIPTOR(void)
|
||||
@@ -1580,12 +1523,6 @@ static void test_pack_PTOKEN_USER(void)
|
||||
TEST_TYPE_POINTER(PTOKEN_USER, 8, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PTOP_LEVEL_EXCEPTION_FILTER(void)
|
||||
{
|
||||
/* PTOP_LEVEL_EXCEPTION_FILTER */
|
||||
TEST_TYPE(PTOP_LEVEL_EXCEPTION_FILTER, 4, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PTSTR(void)
|
||||
{
|
||||
/* PTSTR */
|
||||
@@ -1639,14 +1576,12 @@ static void test_pack_RTL_CRITICAL_SECTION(void)
|
||||
static void test_pack_RTL_CRITICAL_SECTION_DEBUG(void)
|
||||
{
|
||||
/* RTL_CRITICAL_SECTION_DEBUG (pack 4) */
|
||||
TEST_TYPE(RTL_CRITICAL_SECTION_DEBUG, 32, 4);
|
||||
TEST_FIELD(RTL_CRITICAL_SECTION_DEBUG, WORD, Type, 0, 2, 2);
|
||||
TEST_FIELD(RTL_CRITICAL_SECTION_DEBUG, WORD, CreatorBackTraceIndex, 2, 2, 2);
|
||||
TEST_FIELD(RTL_CRITICAL_SECTION_DEBUG, struct _RTL_CRITICAL_SECTION *, CriticalSection, 4, 4, 4);
|
||||
TEST_FIELD(RTL_CRITICAL_SECTION_DEBUG, LIST_ENTRY, ProcessLocksList, 8, 8, 4);
|
||||
TEST_FIELD(RTL_CRITICAL_SECTION_DEBUG, DWORD, EntryCount, 16, 4, 4);
|
||||
TEST_FIELD(RTL_CRITICAL_SECTION_DEBUG, DWORD, ContentionCount, 20, 4, 4);
|
||||
TEST_FIELD(RTL_CRITICAL_SECTION_DEBUG, DWORD[ 2 ], Spare, 24, 8, 4);
|
||||
}
|
||||
|
||||
static void test_pack_RTL_OSVERSIONINFOEXW(void)
|
||||
@@ -1681,14 +1616,12 @@ static void test_pack_RTL_OSVERSIONINFOW(void)
|
||||
static void test_pack_RTL_RESOURCE_DEBUG(void)
|
||||
{
|
||||
/* RTL_RESOURCE_DEBUG (pack 4) */
|
||||
TEST_TYPE(RTL_RESOURCE_DEBUG, 32, 4);
|
||||
TEST_FIELD(RTL_RESOURCE_DEBUG, WORD, Type, 0, 2, 2);
|
||||
TEST_FIELD(RTL_RESOURCE_DEBUG, WORD, CreatorBackTraceIndex, 2, 2, 2);
|
||||
TEST_FIELD(RTL_RESOURCE_DEBUG, struct _RTL_CRITICAL_SECTION *, CriticalSection, 4, 4, 4);
|
||||
TEST_FIELD(RTL_RESOURCE_DEBUG, LIST_ENTRY, ProcessLocksList, 8, 8, 4);
|
||||
TEST_FIELD(RTL_RESOURCE_DEBUG, DWORD, EntryCount, 16, 4, 4);
|
||||
TEST_FIELD(RTL_RESOURCE_DEBUG, DWORD, ContentionCount, 20, 4, 4);
|
||||
TEST_FIELD(RTL_RESOURCE_DEBUG, DWORD[ 2 ], Spare, 24, 8, 4);
|
||||
}
|
||||
|
||||
static void test_pack_SECURITY_CONTEXT_TRACKING_MODE(void)
|
||||
@@ -2029,13 +1962,6 @@ static void test_pack_LPPOINT(void)
|
||||
TEST_TYPE_POINTER(LPPOINT, 8, 4);
|
||||
}
|
||||
|
||||
static void test_pack_LPPOINTS(void)
|
||||
{
|
||||
/* LPPOINTS */
|
||||
TEST_TYPE(LPPOINTS, 4, 4);
|
||||
TEST_TYPE_POINTER(LPPOINTS, 4, 2);
|
||||
}
|
||||
|
||||
static void test_pack_LPRECT(void)
|
||||
{
|
||||
/* LPRECT */
|
||||
@@ -2079,14 +2005,6 @@ static void test_pack_POINTL(void)
|
||||
TEST_FIELD(POINTL, LONG, y, 4, 4, 4);
|
||||
}
|
||||
|
||||
static void test_pack_POINTS(void)
|
||||
{
|
||||
/* POINTS (pack 4) */
|
||||
TEST_TYPE(POINTS, 4, 2);
|
||||
TEST_FIELD(POINTS, SHORT, x, 0, 2, 2);
|
||||
TEST_FIELD(POINTS, SHORT, y, 2, 2, 2);
|
||||
}
|
||||
|
||||
static void test_pack_PPOINT(void)
|
||||
{
|
||||
/* PPOINT */
|
||||
@@ -2101,13 +2019,6 @@ static void test_pack_PPOINTL(void)
|
||||
TEST_TYPE_POINTER(PPOINTL, 8, 4);
|
||||
}
|
||||
|
||||
static void test_pack_PPOINTS(void)
|
||||
{
|
||||
/* PPOINTS */
|
||||
TEST_TYPE(PPOINTS, 4, 4);
|
||||
TEST_TYPE_POINTER(PPOINTS, 4, 2);
|
||||
}
|
||||
|
||||
static void test_pack_PRECT(void)
|
||||
{
|
||||
/* PRECT */
|
||||
@@ -2273,7 +2184,6 @@ static void test_pack(void)
|
||||
test_pack_IMAGE_LINENUMBER();
|
||||
test_pack_IMAGE_LOAD_CONFIG_DIRECTORY();
|
||||
test_pack_IMAGE_NT_HEADERS();
|
||||
test_pack_IMAGE_OPTIONAL_HEADER();
|
||||
test_pack_IMAGE_OS2_HEADER();
|
||||
test_pack_IMAGE_RELOCATION();
|
||||
test_pack_IMAGE_RESOURCE_DATA_ENTRY();
|
||||
@@ -2309,11 +2219,9 @@ static void test_pack(void)
|
||||
test_pack_LPCRECTL();
|
||||
test_pack_LPCVOID();
|
||||
test_pack_LPPOINT();
|
||||
test_pack_LPPOINTS();
|
||||
test_pack_LPRECT();
|
||||
test_pack_LPRECTL();
|
||||
test_pack_LPSIZE();
|
||||
test_pack_LPTOP_LEVEL_EXCEPTION_FILTER();
|
||||
test_pack_LRESULT();
|
||||
test_pack_LUID();
|
||||
test_pack_LUID_AND_ATTRIBUTES();
|
||||
@@ -2391,10 +2299,8 @@ static void test_pack(void)
|
||||
test_pack_POBJECT_TYPE_LIST();
|
||||
test_pack_POINT();
|
||||
test_pack_POINTL();
|
||||
test_pack_POINTS();
|
||||
test_pack_PPOINT();
|
||||
test_pack_PPOINTL();
|
||||
test_pack_PPOINTS();
|
||||
test_pack_PPRIVILEGE_SET();
|
||||
test_pack_PRECT();
|
||||
test_pack_PRECTL();
|
||||
@@ -2419,7 +2325,6 @@ static void test_pack(void)
|
||||
test_pack_PTOKEN_GROUPS();
|
||||
test_pack_PTOKEN_PRIVILEGES();
|
||||
test_pack_PTOKEN_USER();
|
||||
test_pack_PTOP_LEVEL_EXCEPTION_FILTER();
|
||||
test_pack_PTSTR();
|
||||
test_pack_PULARGE_INTEGER();
|
||||
test_pack_PVECTORED_EXCEPTION_HANDLER();
|
||||
|
||||
+243
-146
@@ -19,37 +19,39 @@
|
||||
*/
|
||||
|
||||
#include "ntdll_test.h"
|
||||
#include <winnls.h>
|
||||
|
||||
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||
static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
|
||||
|
||||
static HMODULE hntdll = 0;
|
||||
static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
|
||||
|
||||
/* one_before_last_pid is used to be able to compare values of a still running process
|
||||
with the output of the test_query_process_times and test_query_process_handlecount tests.
|
||||
*/
|
||||
static DWORD one_before_last_pid = 0;
|
||||
|
||||
#define NTDLL_GET_PROC(func) \
|
||||
#define NTDLL_GET_PROC(func) do { \
|
||||
p ## func = (void*)GetProcAddress(hntdll, #func); \
|
||||
if(!p ## func) { \
|
||||
trace("GetProcAddress(%s) failed\n", #func); \
|
||||
FreeLibrary(hntdll); \
|
||||
return FALSE; \
|
||||
}
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static BOOL InitFunctionPtrs(void)
|
||||
{
|
||||
hntdll = LoadLibraryA("ntdll.dll");
|
||||
if(!hntdll) {
|
||||
trace("Could not load ntdll.dll\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (hntdll)
|
||||
/* All needed functions are NT based, so using GetModuleHandle is a good check */
|
||||
HMODULE hntdll = GetModuleHandle("ntdll");
|
||||
if (!hntdll)
|
||||
{
|
||||
NTDLL_GET_PROC(NtQuerySystemInformation)
|
||||
NTDLL_GET_PROC(NtQueryInformationProcess)
|
||||
skip("Not running on NT\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTDLL_GET_PROC(NtQuerySystemInformation);
|
||||
NTDLL_GET_PROC(NtQueryInformationProcess);
|
||||
NTDLL_GET_PROC(NtReadVirtualMemory);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -59,40 +61,40 @@ static void test_query_basic(void)
|
||||
ULONG ReturnLength;
|
||||
SYSTEM_BASIC_INFORMATION sbi;
|
||||
|
||||
/* This test also covers some basic parameter testing that should be the same for
|
||||
/* This test also covers some basic parameter testing that should be the same for
|
||||
* every information class
|
||||
*/
|
||||
|
||||
/* Use a nonexistent info class */
|
||||
trace("Check nonexistent info class\n");
|
||||
status = pNtQuerySystemInformation(-1, NULL, 0, NULL);
|
||||
ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status);
|
||||
ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08x\n", status);
|
||||
|
||||
/* Use an existing class but with a zero-length buffer */
|
||||
trace("Check zero-length buffer\n");
|
||||
status = pNtQuerySystemInformation(SystemBasicInformation, NULL, 0, NULL);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
/* Use an existing class, correct length but no SystemInformation buffer */
|
||||
trace("Check no SystemInformation buffer\n");
|
||||
status = pNtQuerySystemInformation(SystemBasicInformation, NULL, sizeof(sbi), NULL);
|
||||
ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
|
||||
ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
|
||||
|
||||
/* Use a existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
|
||||
trace("Check no ReturnLength pointer\n");
|
||||
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
/* Check a too large buffer size */
|
||||
trace("Check a too large buffer size\n");
|
||||
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi) * 2, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
/* Finally some correct calls */
|
||||
trace("Check with correct parameters\n");
|
||||
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(sbi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(sbi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(sbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("Number of Processors : %d\n", sbi.NumberOfProcessors);
|
||||
@@ -106,12 +108,12 @@ static void test_query_cpu(void)
|
||||
SYSTEM_CPU_INFORMATION sci;
|
||||
|
||||
status = pNtQuerySystemInformation(SystemCpuInformation, &sci, sizeof(sci), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(sci), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("Processor FeatureSet : %08lx\n", sci.FeatureSet);
|
||||
ok( sci.FeatureSet != 0, "Expected some features for this processor, got %08lx\n", sci.FeatureSet);
|
||||
trace("Processor FeatureSet : %08x\n", sci.FeatureSet);
|
||||
ok( sci.FeatureSet != 0, "Expected some features for this processor, got %08x\n", sci.FeatureSet);
|
||||
}
|
||||
|
||||
static void test_query_performance(void)
|
||||
@@ -121,15 +123,15 @@ static void test_query_performance(void)
|
||||
SYSTEM_PERFORMANCE_INFORMATION spi;
|
||||
|
||||
status = pNtQuerySystemInformation(SystemPerformanceInformation, &spi, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemPerformanceInformation, &spi, sizeof(spi), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(spi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(spi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(spi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemPerformanceInformation, &spi, sizeof(spi) + 2, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(spi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(spi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(spi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Not return values yet, as struct members are unknown */
|
||||
}
|
||||
@@ -149,7 +151,7 @@ static void test_query_timeofday(void)
|
||||
} SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE, *PSYSTEM_TIMEOFDAY_INFORMATION_PRIVATE;
|
||||
|
||||
SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti;
|
||||
|
||||
|
||||
/* The struct size for NT (32 bytes) and Win2K/XP (48 bytes) differ.
|
||||
*
|
||||
* Windows 2000 and XP return STATUS_INFO_LENGTH_MISMATCH if the given buffer size is greater
|
||||
@@ -167,48 +169,48 @@ static void test_query_timeofday(void)
|
||||
if (status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
trace("Windows version is NT, we have to cater for differences with W2K/WinXP\n");
|
||||
|
||||
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
|
||||
|
||||
sti.uCurrentTimeZoneId = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 28, &ReturnLength);
|
||||
ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
|
||||
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( 32 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( 32 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
|
||||
|
||||
sti.uCurrentTimeZoneId = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 24, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( 24 == ReturnLength, "ReturnLength should be 24, it is (%ld)\n", ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( 24 == ReturnLength, "ReturnLength should be 24, it is (%d)\n", ReturnLength);
|
||||
ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
|
||||
|
||||
|
||||
sti.uCurrentTimeZoneId = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( 32 == ReturnLength, "ReturnLength should be 32, it is (%ld)\n", ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( 32 == ReturnLength, "ReturnLength should be 32, it is (%d)\n", ReturnLength);
|
||||
ok( 0xdeadbeef != sti.uCurrentTimeZoneId, "Buffer should have been partially filled\n");
|
||||
|
||||
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 49, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
|
||||
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(sti) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(sti), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(sti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
}
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("uCurrentTimeZoneId : (%ld)\n", sti.uCurrentTimeZoneId);
|
||||
trace("uCurrentTimeZoneId : (%d)\n", sti.uCurrentTimeZoneId);
|
||||
}
|
||||
|
||||
static void test_query_process(void)
|
||||
@@ -250,11 +252,11 @@ static void test_query_process(void)
|
||||
status = pNtQuerySystemInformation(SystemProcessInformation, spi, SystemInformationLength, &ReturnLength);
|
||||
|
||||
if (status != STATUS_INFO_LENGTH_MISMATCH) break;
|
||||
|
||||
|
||||
spi = HeapReAlloc(GetProcessHeap(), 0, spi , SystemInformationLength *= 2);
|
||||
}
|
||||
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
/* Get the first dwOffset, from this we can deduce the OS version we're running
|
||||
*
|
||||
@@ -275,14 +277,14 @@ static void test_query_process(void)
|
||||
|
||||
is_nt = ( spi->dwOffset - (sbi.NumberOfProcessors * sizeof(SYSTEM_THREAD_INFORMATION)) == 136);
|
||||
|
||||
if (is_nt) trace("Windows version is NT, we will skip thread tests\n");
|
||||
if (is_nt) skip("Windows version is NT, we will skip thread tests\n");
|
||||
|
||||
/* Check if we have some return values
|
||||
*
|
||||
*
|
||||
* On windows there will be several processes running (Including the always present Idle and System)
|
||||
* On wine we only have one (if this test is the only wine process running)
|
||||
*/
|
||||
|
||||
|
||||
/* Loop through the processes */
|
||||
|
||||
for (;;)
|
||||
@@ -294,15 +296,15 @@ static void test_query_process(void)
|
||||
ok( spi->dwThreadCount > 0, "Expected some threads for this process, got 0\n");
|
||||
|
||||
/* Loop through the threads, skip NT4 for now */
|
||||
|
||||
|
||||
if (!is_nt)
|
||||
{
|
||||
DWORD j;
|
||||
for ( j = 0; j < spi->dwThreadCount; j++)
|
||||
for ( j = 0; j < spi->dwThreadCount; j++)
|
||||
{
|
||||
k++;
|
||||
ok ( spi->ti[j].dwOwningPID == spi->dwProcessID,
|
||||
"The owning pid of the thread (%ld) doesn't equal the pid (%ld) of the process\n",
|
||||
ok ( spi->ti[j].dwOwningPID == spi->dwProcessID,
|
||||
"The owning pid of the thread (%d) doesn't equal the pid (%d) of the process\n",
|
||||
spi->ti[j].dwOwningPID, spi->dwProcessID);
|
||||
}
|
||||
}
|
||||
@@ -336,25 +338,25 @@ static void test_query_procperf(void)
|
||||
sppi = HeapAlloc(GetProcessHeap(), 0, NeededLength);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
/* Try it for 1 processor */
|
||||
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi,
|
||||
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
|
||||
"Inconsistent length (%d) <-> (%ld)\n", sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), ReturnLength);
|
||||
|
||||
"Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Try it for all processors */
|
||||
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( NeededLength == ReturnLength, "Inconsistent length (%ld) <-> (%ld)\n", NeededLength, ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
|
||||
|
||||
/* A too large given buffer size */
|
||||
sppi = HeapReAlloc(GetProcessHeap(), 0, sppi , NeededLength + 2);
|
||||
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength + 2, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( NeededLength == ReturnLength, "Inconsistent length (%ld) <-> (%ld)\n", NeededLength, ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, sppi);
|
||||
}
|
||||
@@ -366,30 +368,28 @@ static void test_query_module(void)
|
||||
ULONG ModuleCount, i;
|
||||
|
||||
ULONG SystemInformationLength = sizeof(SYSTEM_MODULE_INFORMATION);
|
||||
SYSTEM_MODULE_INFORMATION* smi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
|
||||
SYSTEM_MODULE_INFORMATION* smi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
|
||||
SYSTEM_MODULE* sm;
|
||||
|
||||
/* Request the needed length */
|
||||
status = pNtQuerySystemInformation(SystemModuleInformation, smi, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( ReturnLength > 0, "Expected a ReturnLength to show the needed length\n");
|
||||
|
||||
SystemInformationLength = ReturnLength;
|
||||
smi = HeapReAlloc(GetProcessHeap(), 0, smi , SystemInformationLength);
|
||||
status = pNtQuerySystemInformation(SystemModuleInformation, smi, SystemInformationLength, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
ModuleCount = smi->ModulesCount;
|
||||
sm = &smi->Modules[0];
|
||||
todo_wine{
|
||||
/* our implementation is a stub for now */
|
||||
ok( ModuleCount > 0, "Expected some modules to be loaded\n");
|
||||
}
|
||||
/* our implementation is a stub for now */
|
||||
ok( ModuleCount > 0, "Expected some modules to be loaded\n");
|
||||
|
||||
/* Loop through all the modules/drivers, Wine doesn't get here (yet) */
|
||||
for (i = 0; i < ModuleCount ; i++)
|
||||
{
|
||||
ok( i == sm->Id, "Id (%d) should have matched %lu\n", sm->Id, i);
|
||||
ok( i == sm->Id, "Id (%d) should have matched %u\n", sm->Id, i);
|
||||
sm++;
|
||||
}
|
||||
|
||||
@@ -409,21 +409,21 @@ static void test_query_handle(void)
|
||||
/* The following check assumes more than one handle on any given system */
|
||||
todo_wine
|
||||
{
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
}
|
||||
ok( ReturnLength > 0, "Expected ReturnLength to be > 0, it was %ld\n", ReturnLength);
|
||||
ok( ReturnLength > 0, "Expected ReturnLength to be > 0, it was %d\n", ReturnLength);
|
||||
|
||||
SystemInformationLength = ReturnLength;
|
||||
shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
|
||||
status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("Number of Handles : %ld\n", shi->Count);
|
||||
trace("Number of Handles : %d\n", shi->Count);
|
||||
todo_wine
|
||||
{
|
||||
/* our implementation is a stub for now */
|
||||
ok( shi->Count > 1, "Expected more than 1 handles, got (%ld)\n", shi->Count);
|
||||
ok( shi->Count > 1, "Expected more than 1 handles, got (%d)\n", shi->Count);
|
||||
}
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, shi);
|
||||
@@ -436,15 +436,15 @@ static void test_query_cache(void)
|
||||
SYSTEM_CACHE_INFORMATION sci;
|
||||
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(sci), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci) + 2, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(sci), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
}
|
||||
|
||||
static void test_query_interrupt(void)
|
||||
@@ -462,11 +462,11 @@ static void test_query_interrupt(void)
|
||||
sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemInterruptInformation, sii, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
/* Try it for all processors */
|
||||
status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
/* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
|
||||
* No test added for this as it's highly unlikely that an app depends on this
|
||||
@@ -482,15 +482,15 @@ static void test_query_kerndebug(void)
|
||||
SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi;
|
||||
|
||||
status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(skdi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(skdi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi) + 2, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(skdi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(skdi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
}
|
||||
|
||||
static void test_query_regquota(void)
|
||||
@@ -500,15 +500,15 @@ static void test_query_regquota(void)
|
||||
SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
|
||||
|
||||
status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(srqi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(srqi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi) + 2, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(srqi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(srqi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
}
|
||||
|
||||
static void test_query_process_basic(void)
|
||||
@@ -534,48 +534,48 @@ static void test_query_process_basic(void)
|
||||
/* Use a nonexistent info class */
|
||||
trace("Check nonexistent info class\n");
|
||||
status = pNtQueryInformationProcess(NULL, -1, NULL, 0, NULL);
|
||||
ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status);
|
||||
ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08x\n", status);
|
||||
|
||||
/* Do not give a handle and buffer */
|
||||
trace("Check NULL handle and buffer and zero-length buffersize\n");
|
||||
status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, 0, NULL);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
/* Use a correct info class and buffer size, but still no handle and buffer */
|
||||
trace("Check NULL handle and buffer\n");
|
||||
status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, sizeof(pbi), NULL);
|
||||
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
|
||||
|
||||
/* Use a correct info class and buffer size, but still no handle */
|
||||
trace("Check NULL handle\n");
|
||||
status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
|
||||
|
||||
/* Use a greater buffer size */
|
||||
trace("Check NULL handle and too large buffersize\n");
|
||||
status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi) * 2, NULL);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
/* Use no ReturnLength */
|
||||
trace("Check NULL ReturnLength\n");
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
/* Finally some correct calls */
|
||||
trace("Check with correct parameters\n");
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(pbi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(pbi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Everything is correct except a too large buffersize */
|
||||
trace("Too large buffersize\n");
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi) * 2, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( sizeof(pbi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(pbi), ReturnLength);
|
||||
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("ProcessID : %ld\n", pbi.UniqueProcessId);
|
||||
trace("ProcessID : %d\n", pbi.UniqueProcessId);
|
||||
ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
|
||||
}
|
||||
|
||||
@@ -587,10 +587,10 @@ static void test_query_process_vm(void)
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
|
||||
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
|
||||
|
||||
/* Windows XP and W2K3 will report success for a size of 44 AND 48 !
|
||||
Windows W2K will only report success for 44.
|
||||
@@ -599,15 +599,15 @@ static void test_query_process_vm(void)
|
||||
*/
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 24, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(pvi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(pvi), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(pvi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 46, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( sizeof(pvi) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(pvi), ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( sizeof(pvi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
|
||||
@@ -627,30 +627,30 @@ static void test_query_process_io(void)
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
|
||||
if (status == STATUS_NOT_SUPPORTED)
|
||||
{
|
||||
trace("ProcessIoCounters information class not supported, skipping tests\n");
|
||||
skip("ProcessIoCounters information class is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessIoCounters, NULL, sizeof(pii), NULL);
|
||||
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessIoCounters, &pii, sizeof(pii), NULL);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, 24, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(pii) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(pii), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii) * 2, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( sizeof(pii) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(pii), ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("OtherOperationCount : %lld\n", pii.OtherOperationCount);
|
||||
trace("OtherOperationCount : 0x%x%08x\n", (DWORD)(pii.OtherOperationCount >> 32), (DWORD)pii.OtherOperationCount);
|
||||
todo_wine
|
||||
{
|
||||
ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
|
||||
@@ -667,27 +667,27 @@ static void test_query_process_times(void)
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessTimes, NULL, sizeof(spti), NULL);
|
||||
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessTimes, &spti, sizeof(spti), NULL);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, 24, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
|
||||
if (!process)
|
||||
{
|
||||
trace("Could not open process with ID : %ld, error : %08lx. Going to use current one.\n", one_before_last_pid, GetLastError());
|
||||
trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
|
||||
process = GetCurrentProcess();
|
||||
trace("ProcessTimes for current process\n");
|
||||
}
|
||||
else
|
||||
trace("ProcessTimes for process with ID : %ld\n", one_before_last_pid);
|
||||
trace("ProcessTimes for process with ID : %d\n", one_before_last_pid);
|
||||
|
||||
status = pNtQueryInformationProcess( process, ProcessTimes, &spti, sizeof(spti), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(spti) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(spti), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(spti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
CloseHandle(process);
|
||||
|
||||
FileTimeToSystemTime((const FILETIME *)&spti.CreateTime, &UTC);
|
||||
@@ -707,8 +707,8 @@ static void test_query_process_times(void)
|
||||
trace("UserTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, sizeof(spti) * 2, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( sizeof(spti) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(spti), ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( sizeof(spti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
}
|
||||
|
||||
static void test_query_process_handlecount(void)
|
||||
@@ -720,41 +720,132 @@ static void test_query_process_handlecount(void)
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessHandleCount, NULL, sizeof(handlecount), NULL);
|
||||
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessHandleCount, &handlecount, sizeof(handlecount), NULL);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, 2, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
|
||||
if (!process)
|
||||
{
|
||||
trace("Could not open process with ID : %ld, error : %08lx. Going to use current one.\n", one_before_last_pid, GetLastError());
|
||||
trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
|
||||
process = GetCurrentProcess();
|
||||
trace("ProcessHandleCount for current process\n");
|
||||
}
|
||||
else
|
||||
trace("ProcessHandleCount for process with ID : %ld\n", one_before_last_pid);
|
||||
trace("ProcessHandleCount for process with ID : %d\n", one_before_last_pid);
|
||||
|
||||
status = pNtQueryInformationProcess( process, ProcessHandleCount, &handlecount, sizeof(handlecount), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
|
||||
ok( sizeof(handlecount) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(handlecount), ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
CloseHandle(process);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, sizeof(handlecount) * 2, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
|
||||
ok( sizeof(handlecount) == ReturnLength, "Inconsistent length (%d) <-> (%ld)\n", sizeof(handlecount), ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("HandleCount : %ld\n", handlecount);
|
||||
trace("HandleCount : %d\n", handlecount);
|
||||
todo_wine
|
||||
{
|
||||
ok( handlecount > 0, "Expected some handles, got 0\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void test_query_process_image_file_name(void)
|
||||
{
|
||||
DWORD status;
|
||||
ULONG ReturnLength;
|
||||
UNICODE_STRING image_file_name;
|
||||
void *buffer;
|
||||
char *file_nameA;
|
||||
INT len;
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessImageFileName, &image_file_name, sizeof(image_file_name), NULL);
|
||||
if (status == STATUS_INVALID_INFO_CLASS)
|
||||
{
|
||||
skip("ProcessImageFileName is not supported\n");
|
||||
return;
|
||||
}
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, 2, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, sizeof(image_file_name), &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
|
||||
buffer = HeapAlloc(GetProcessHeap(), 0, ReturnLength);
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, buffer, ReturnLength, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
memcpy(&image_file_name, buffer, sizeof(image_file_name));
|
||||
len = WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), NULL, 0, NULL, NULL);
|
||||
file_nameA = HeapAlloc(GetProcessHeap(), 0, len + 1);
|
||||
WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), file_nameA, len, NULL, NULL);
|
||||
file_nameA[len] = '\0';
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
trace("process image file name: %s\n", file_nameA);
|
||||
HeapFree(GetProcessHeap(), 0, file_nameA);
|
||||
}
|
||||
|
||||
|
||||
static void test_readvirtualmemory(void)
|
||||
{
|
||||
HANDLE process;
|
||||
DWORD status;
|
||||
SIZE_T readcount;
|
||||
static const char teststring[] = "test string";
|
||||
char buffer[12];
|
||||
|
||||
process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
|
||||
ok(process != 0, "Expected to be able to open own process for reading memory\n");
|
||||
|
||||
/* normal operation */
|
||||
status = pNtReadVirtualMemory(process, teststring, buffer, 12, &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
|
||||
ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
|
||||
|
||||
/* no number of bytes */
|
||||
memset(buffer, 0, 12);
|
||||
status = pNtReadVirtualMemory(process, teststring, buffer, 12, NULL);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
|
||||
|
||||
/* illegal remote address */
|
||||
todo_wine{
|
||||
status = pNtReadVirtualMemory(process, (void *) 0x1234, buffer, 12, &readcount);
|
||||
ok( status == STATUS_PARTIAL_COPY, "Expected STATUS_PARTIAL_COPY, got %08x\n", status);
|
||||
ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
|
||||
}
|
||||
|
||||
/* 0 handle */
|
||||
status = pNtReadVirtualMemory(0, teststring, buffer, 12, &readcount);
|
||||
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
|
||||
ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
|
||||
|
||||
/* pseudo handle for current process*/
|
||||
memset(buffer, 0, 12);
|
||||
status = pNtReadVirtualMemory((HANDLE)-1, teststring, buffer, 12, &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
|
||||
ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
|
||||
|
||||
/* this test currently crashes wine with "wine client error:<process id>: read: Bad address"
|
||||
* because the reply from wine server is directly read into the buffer and that fails with EFAULT
|
||||
*/
|
||||
/* illegal local address */
|
||||
/*status = pNtReadVirtualMemory(process, teststring, (void *)0x1234, 12, &readcount);
|
||||
ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
|
||||
ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
|
||||
*/
|
||||
|
||||
CloseHandle(process);
|
||||
}
|
||||
|
||||
START_TEST(info)
|
||||
{
|
||||
if(!InitFunctionPtrs())
|
||||
@@ -832,5 +923,11 @@ START_TEST(info)
|
||||
trace("Starting test_query_process_handlecount()\n");
|
||||
test_query_process_handlecount();
|
||||
|
||||
FreeLibrary(hntdll);
|
||||
/* 27 ProcessImageFileName */
|
||||
trace("Starting test_query_process_image_file_name()\n");
|
||||
test_query_process_image_file_name();
|
||||
|
||||
/* belongs into it's own file */
|
||||
trace("Starting test_readvirtualmemory()\n");
|
||||
test_readvirtualmemory();
|
||||
}
|
||||
|
||||
@@ -113,8 +113,10 @@ static void test_RtlExtendedMagicDivide(void)
|
||||
for (i = 0; i < NB_MAGIC_DIVIDE; i++) {
|
||||
result = pRtlExtendedMagicDivide(magic_divide[i].a, magic_divide[i].b, magic_divide[i].shift);
|
||||
ok(result == magic_divide[i].result,
|
||||
"call failed: RtlExtendedMagicDivide(%lld, %llu, %d) has result %llx, expected %llx\n",
|
||||
magic_divide[i].a, magic_divide[i].b, magic_divide[i].shift, result, magic_divide[i].result);
|
||||
"call failed: RtlExtendedMagicDivide(0x%x%08x, 0x%x%08x, %d) has result 0x%x%08x, expected 0x%x%08x\n",
|
||||
(DWORD)(magic_divide[i].a >> 32), (DWORD)magic_divide[i].a, (DWORD)(magic_divide[i].b >> 32),
|
||||
(DWORD)magic_divide[i].b, magic_divide[i].shift, (DWORD)(result >> 32), (DWORD)result,
|
||||
(DWORD)(magic_divide[i].result >> 32), (DWORD)magic_divide[i].result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,23 +324,28 @@ static void one_RtlInt64ToUnicodeString_test(int test_num, const largeint2str_t
|
||||
} /* if */
|
||||
} else {
|
||||
ok(result == largeint2str->result,
|
||||
"(test %d): RtlInt64ToUnicodeString(%llu, %d, [out]) has result %lx, expected: %lx\n",
|
||||
test_num, largeint2str->value, largeint2str->base, result, largeint2str->result);
|
||||
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) has result %x, expected: %x\n",
|
||||
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value,
|
||||
largeint2str->base, result, largeint2str->result);
|
||||
if (result == STATUS_SUCCESS) {
|
||||
ok(unicode_string.Buffer[unicode_string.Length/sizeof(WCHAR)] == '\0',
|
||||
"(test %d): RtlInt64ToUnicodeString(%llu, %d, [out]) string \"%s\" is not NULL terminated\n",
|
||||
test_num, largeint2str->value, largeint2str->base, ansi_str.Buffer);
|
||||
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) string \"%s\" is not NULL terminated\n",
|
||||
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value,
|
||||
largeint2str->base, ansi_str.Buffer);
|
||||
} /* if */
|
||||
} /* if */
|
||||
ok(memcmp(unicode_string.Buffer, expected_unicode_string.Buffer, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
|
||||
"(test %d): RtlInt64ToUnicodeString(%llu, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, largeint2str->value, largeint2str->base, ansi_str.Buffer, expected_ansi_str.Buffer);
|
||||
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, (DWORD)(largeint2str->value >>32), (DWORD)largeint2str->value, largeint2str->base,
|
||||
ansi_str.Buffer, expected_ansi_str.Buffer);
|
||||
ok(unicode_string.Length == expected_unicode_string.Length,
|
||||
"(test %d): RtlInt64ToUnicodeString(%llu, %d, [out]) string has Length %d, expected: %d\n",
|
||||
test_num, largeint2str->value, largeint2str->base, unicode_string.Length, expected_unicode_string.Length);
|
||||
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) string has Length %d, expected: %d\n",
|
||||
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
|
||||
unicode_string.Length, expected_unicode_string.Length);
|
||||
ok(unicode_string.MaximumLength == expected_unicode_string.MaximumLength,
|
||||
"(test %d): RtlInt64ToUnicodeString(%llu, %d, [out]) string has MaximumLength %d, expected: %d\n",
|
||||
test_num, largeint2str->value, largeint2str->base, unicode_string.MaximumLength, expected_unicode_string.MaximumLength);
|
||||
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) string has MaximumLength %d, expected: %d\n",
|
||||
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
|
||||
unicode_string.MaximumLength, expected_unicode_string.MaximumLength);
|
||||
pRtlFreeAnsiString(&expected_ansi_str);
|
||||
pRtlFreeAnsiString(&ansi_str);
|
||||
}
|
||||
@@ -369,11 +376,13 @@ static void one_RtlLargeIntegerToChar_test(int test_num, const largeint2str_t *l
|
||||
result = pRtlLargeIntegerToChar(&value, largeint2str->base, largeint2str->MaximumLength, dest_str);
|
||||
} /* if */
|
||||
ok(result == largeint2str->result,
|
||||
"(test %d): RtlLargeIntegerToChar(%llu, %d, %d, [out]) has result %lx, expected: %lx\n",
|
||||
test_num, largeint2str->value, largeint2str->base, largeint2str->MaximumLength, result, largeint2str->result);
|
||||
"(test %d): RtlLargeIntegerToChar(0x%x%08x, %d, %d, [out]) has result %x, expected: %x\n",
|
||||
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
|
||||
largeint2str->MaximumLength, result, largeint2str->result);
|
||||
ok(memcmp(dest_str, largeint2str->Buffer, LARGE_STRI_BUFFER_LENGTH) == 0,
|
||||
"(test %d): RtlLargeIntegerToChar(%llu, %d, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, largeint2str->value, largeint2str->base, largeint2str->MaximumLength, dest_str, largeint2str->Buffer);
|
||||
"(test %d): RtlLargeIntegerToChar(0x%x%08x, %d, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
|
||||
largeint2str->MaximumLength, dest_str, largeint2str->Buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -390,23 +399,27 @@ static void test_RtlLargeIntegerToChar(void)
|
||||
value = largeint2str[0].value;
|
||||
result = pRtlLargeIntegerToChar(&value, 20, largeint2str[0].MaximumLength, NULL);
|
||||
ok(result == STATUS_INVALID_PARAMETER,
|
||||
"(test a): RtlLargeIntegerToChar(%llu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
largeint2str[0].value, 20, largeint2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
|
||||
"(test a): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value, 20,
|
||||
largeint2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
|
||||
|
||||
result = pRtlLargeIntegerToChar(&value, 20, 0, NULL);
|
||||
ok(result == STATUS_INVALID_PARAMETER,
|
||||
"(test b): RtlLargeIntegerToChar(%llu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
largeint2str[0].value, 20, largeint2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
|
||||
"(test b): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value, 20,
|
||||
largeint2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
|
||||
|
||||
result = pRtlLargeIntegerToChar(&value, largeint2str[0].base, 0, NULL);
|
||||
ok(result == STATUS_BUFFER_OVERFLOW,
|
||||
"(test c): RtlLargeIntegerToChar(%llu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
largeint2str[0].value, largeint2str[0].base, 0, result, STATUS_BUFFER_OVERFLOW);
|
||||
"(test c): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value,
|
||||
largeint2str[0].base, 0, result, STATUS_BUFFER_OVERFLOW);
|
||||
|
||||
result = pRtlLargeIntegerToChar(&value, largeint2str[0].base, largeint2str[0].MaximumLength, NULL);
|
||||
ok(result == STATUS_ACCESS_VIOLATION,
|
||||
"(test d): RtlLargeIntegerToChar(%llu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
largeint2str[0].value, largeint2str[0].base, largeint2str[0].MaximumLength, result, STATUS_ACCESS_VIOLATION);
|
||||
"(test d): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value,
|
||||
largeint2str[0].base, largeint2str[0].MaximumLength, result, STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="ntdll_winetest" type="win32cui" installbase="bin" installname="ntdll_winetest.exe" allowwarnings="true">
|
||||
<include base="ntdll_winetest">.</include>
|
||||
<define name="__USE_W32API" />
|
||||
<define name="_WIN32_WINNT">0x0600</define>
|
||||
<define name="WINVER">0x609</define>
|
||||
<library>kernel32</library>
|
||||
<library>ntdll</library>
|
||||
<file>atom.c</file>
|
||||
@@ -8,6 +13,7 @@
|
||||
<file>env.c</file>
|
||||
<file>error.c</file>
|
||||
<file>exception.c</file>
|
||||
<file>file.c</file>
|
||||
<file>info.c</file>
|
||||
<file>large_int.c</file>
|
||||
<file>om.c</file>
|
||||
@@ -21,3 +27,4 @@
|
||||
<file>time.c</file>
|
||||
<file>testlist.c</file>
|
||||
</module>
|
||||
</group>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
+100
-85
@@ -25,6 +25,7 @@
|
||||
#include "winnt.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*, BOOL, LPCSTR);
|
||||
static NTSTATUS (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
|
||||
static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
|
||||
static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
|
||||
@@ -45,7 +46,7 @@ static NTSTATUS (WINAPI *pNtOpenSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJEC
|
||||
static NTSTATUS (WINAPI *pNtCreateSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PUNICODE_STRING);
|
||||
|
||||
|
||||
void test_case_sensitive (void)
|
||||
static void test_case_sensitive (void)
|
||||
{
|
||||
static const WCHAR buffer1[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','t','e','s','t',0};
|
||||
static const WCHAR buffer2[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','T','e','s','t',0};
|
||||
@@ -59,22 +60,22 @@ void test_case_sensitive (void)
|
||||
pRtlInitUnicodeString(&str, buffer1);
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
|
||||
|
||||
status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
|
||||
ok(status == STATUS_OBJECT_NAME_COLLISION,
|
||||
"NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08lx)\n", status);
|
||||
"NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
|
||||
|
||||
pRtlInitUnicodeString(&str, buffer2);
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Event(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Event(%08x)\n", status);
|
||||
|
||||
pRtlInitUnicodeString(&str, buffer3);
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
status = pNtOpenMutant(&h, GENERIC_ALL, &attr);
|
||||
ok(status == STATUS_OBJECT_TYPE_MISMATCH,
|
||||
"NtOpenMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08lx)\n", status);
|
||||
"NtOpenMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
|
||||
|
||||
pNtClose(Mutant);
|
||||
|
||||
@@ -82,21 +83,21 @@ void test_case_sensitive (void)
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_NAME_COLLISION,
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION got(%08lx)\n", status);
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
|
||||
|
||||
status = pNtCreateEvent(&h, GENERIC_ALL, &attr, FALSE, FALSE);
|
||||
ok(status == STATUS_OBJECT_NAME_COLLISION,
|
||||
"NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08lx)\n", status);
|
||||
"NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
|
||||
|
||||
attr.Attributes = 0;
|
||||
status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08lx)\n", status);
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
|
||||
|
||||
pNtClose(Event);
|
||||
}
|
||||
|
||||
void test_namespace_pipe(void)
|
||||
static void test_namespace_pipe(void)
|
||||
{
|
||||
static const WCHAR buffer1[] = {'\\','?','?','\\','P','I','P','E','\\','t','e','s','t','\\','p','i','p','e',0};
|
||||
static const WCHAR buffer2[] = {'\\','?','?','\\','P','I','P','E','\\','T','E','S','T','\\','P','I','P','E',0};
|
||||
@@ -115,36 +116,36 @@ void test_namespace_pipe(void)
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create NamedPipe(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create NamedPipe(%08x)\n", status);
|
||||
|
||||
status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
|
||||
ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
|
||||
"NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08lx)\n", status);
|
||||
"NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
|
||||
|
||||
pRtlInitUnicodeString(&str, buffer2);
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
|
||||
ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
|
||||
"NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08lx)\n", status);
|
||||
"NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08x)\n", status);
|
||||
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
|
||||
ok(status == STATUS_SUCCESS, "Failed to open NamedPipe(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to open NamedPipe(%08x)\n", status);
|
||||
pNtClose(h);
|
||||
|
||||
pRtlInitUnicodeString(&str, buffer3);
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
|
||||
ok(status == STATUS_OBJECT_PATH_NOT_FOUND || status == STATUS_PIPE_NOT_AVAILABLE,
|
||||
"pNtOpenFile should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08lx)\n", status);
|
||||
"NtOpenFile should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
|
||||
|
||||
pRtlInitUnicodeString(&str, buffer4);
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
|
||||
ok(status == STATUS_OBJECT_NAME_NOT_FOUND,
|
||||
"pNtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08lx)\n", status);
|
||||
"NtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08x)\n", status);
|
||||
|
||||
pNtClose(pipe);
|
||||
}
|
||||
@@ -154,10 +155,10 @@ void test_namespace_pipe(void)
|
||||
|
||||
#define DIR_TEST_CREATE_FAILURE(h,e) \
|
||||
status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr);\
|
||||
ok(status == e,"NtCreateDirectoryObject should have failed with %s got(%08lx)\n", #e, status);
|
||||
ok(status == e,"NtCreateDirectoryObject should have failed with %s got(%08x)\n", #e, status);
|
||||
#define DIR_TEST_OPEN_FAILURE(h,e) \
|
||||
status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr);\
|
||||
ok(status == e,"NtOpenDirectoryObject should have failed with %s got(%08lx)\n", #e, status);
|
||||
ok(status == e,"NtOpenDirectoryObject should have failed with %s got(%08x)\n", #e, status);
|
||||
#define DIR_TEST_CREATE_OPEN_FAILURE(h,n,e) \
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, n);\
|
||||
DIR_TEST_CREATE_FAILURE(h,e) DIR_TEST_OPEN_FAILURE(h,e)\
|
||||
@@ -165,13 +166,13 @@ void test_namespace_pipe(void)
|
||||
|
||||
#define DIR_TEST_CREATE_SUCCESS(h) \
|
||||
status = pNtCreateDirectoryObject(h, DIRECTORY_QUERY, &attr); \
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Directory(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Directory(%08x)\n", status);
|
||||
#define DIR_TEST_OPEN_SUCCESS(h) \
|
||||
status = pNtOpenDirectoryObject(h, DIRECTORY_QUERY, &attr); \
|
||||
ok(status == STATUS_SUCCESS, "Failed to open Directory(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to open Directory(%08x)\n", status);
|
||||
#define DIR_TEST_CREATE_OPEN_SUCCESS(h,n) \
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, n);\
|
||||
DIR_TEST_CREATE_SUCCESS(h) pNtClose(h); DIR_TEST_OPEN_SUCCESS(h) pNtClose(h); \
|
||||
DIR_TEST_CREATE_SUCCESS(&h) pNtClose(h); DIR_TEST_OPEN_SUCCESS(&h) pNtClose(h); \
|
||||
pRtlFreeUnicodeString(&str);
|
||||
|
||||
static void test_name_collisions(void)
|
||||
@@ -192,13 +193,13 @@ static void test_name_collisions(void)
|
||||
pNtClose(h);
|
||||
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_TYPE_MISMATCH,
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08lx)\n", status);
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "\\??\\PIPE\\om.c-mutant");
|
||||
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08lx)\n", status);
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
|
||||
|
||||
@@ -206,70 +207,70 @@ static void test_name_collisions(void)
|
||||
DIR_TEST_OPEN_SUCCESS(&dir)
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-test");
|
||||
InitializeObjectAttributes(&attr, &str, OBJ_OPENIF, dir, NULL);
|
||||
|
||||
|
||||
h = CreateMutexA(NULL, FALSE, "om.c-test");
|
||||
ok(h != 0, "CreateMutexA failed got ret=%p (%ld)\n", h, GetLastError());
|
||||
ok(h != 0, "CreateMutexA failed got ret=%p (%d)\n", h, GetLastError());
|
||||
status = pNtCreateMutant(&h1, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
|
||||
"NtCreateMutant should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08lx)\n", status);
|
||||
"NtCreateMutant should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
|
||||
h2 = CreateMutexA(NULL, FALSE, "om.c-test");
|
||||
winerr = GetLastError();
|
||||
ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
|
||||
"CreateMutexA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%ld)\n", h2, winerr);
|
||||
"CreateMutexA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
|
||||
pNtClose(h);
|
||||
pNtClose(h1);
|
||||
pNtClose(h2);
|
||||
|
||||
h = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
|
||||
ok(h != 0, "CreateEventA failed got ret=%p (%ld)\n", h, GetLastError());
|
||||
ok(h != 0, "CreateEventA failed got ret=%p (%d)\n", h, GetLastError());
|
||||
status = pNtCreateEvent(&h1, GENERIC_ALL, &attr, FALSE, FALSE);
|
||||
ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
|
||||
"NtCreateEvent should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08lx)\n", status);
|
||||
"NtCreateEvent should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
|
||||
h2 = CreateEventA(NULL, FALSE, FALSE, "om.c-test");
|
||||
winerr = GetLastError();
|
||||
ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
|
||||
"CreateEventA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%ld)\n", h2, winerr);
|
||||
"CreateEventA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
|
||||
pNtClose(h);
|
||||
pNtClose(h1);
|
||||
pNtClose(h2);
|
||||
|
||||
h = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
|
||||
ok(h != 0, "CreateSemaphoreA failed got ret=%p (%ld)\n", h, GetLastError());
|
||||
ok(h != 0, "CreateSemaphoreA failed got ret=%p (%d)\n", h, GetLastError());
|
||||
status = pNtCreateSemaphore(&h1, GENERIC_ALL, &attr, 1, 2);
|
||||
ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
|
||||
"NtCreateSemaphore should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08lx)\n", status);
|
||||
"NtCreateSemaphore should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
|
||||
h2 = CreateSemaphoreA(NULL, 1, 2, "om.c-test");
|
||||
winerr = GetLastError();
|
||||
ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
|
||||
"CreateSemaphoreA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%ld)\n", h2, winerr);
|
||||
"CreateSemaphoreA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
|
||||
pNtClose(h);
|
||||
pNtClose(h1);
|
||||
pNtClose(h2);
|
||||
|
||||
h = CreateWaitableTimerA(NULL, TRUE, "om.c-test");
|
||||
ok(h != 0, "CreateWaitableTimerA failed got ret=%p (%ld)\n", h, GetLastError());
|
||||
|
||||
h = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
|
||||
ok(h != 0, "CreateWaitableTimerA failed got ret=%p (%d)\n", h, GetLastError());
|
||||
status = pNtCreateTimer(&h1, GENERIC_ALL, &attr, NotificationTimer);
|
||||
ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
|
||||
"NtCreateTimer should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08lx)\n", status);
|
||||
h2 = CreateWaitableTimerA(NULL, TRUE, "om.c-test");
|
||||
"NtCreateTimer should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
|
||||
h2 = pCreateWaitableTimerA(NULL, TRUE, "om.c-test");
|
||||
winerr = GetLastError();
|
||||
ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
|
||||
"CreateWaitableTimerA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%ld)\n", h2, winerr);
|
||||
"CreateWaitableTimerA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
|
||||
pNtClose(h);
|
||||
pNtClose(h1);
|
||||
pNtClose(h2);
|
||||
|
||||
h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
|
||||
ok(h != 0, "CreateFileMappingA failed got ret=%p (%ld)\n", h, GetLastError());
|
||||
ok(h != 0, "CreateFileMappingA failed got ret=%p (%d)\n", h, GetLastError());
|
||||
size.u.LowPart = 256;
|
||||
size.u.HighPart = 0;
|
||||
status = pNtCreateSection(&h1, SECTION_MAP_WRITE, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0);
|
||||
ok(status == STATUS_OBJECT_NAME_EXISTS && h1 != NULL,
|
||||
"NtCreateSection should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08lx)\n", status);
|
||||
"NtCreateSection should have succeeded with STATUS_OBJECT_NAME_EXISTS got(%08x)\n", status);
|
||||
h2 = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, "om.c-test");
|
||||
winerr = GetLastError();
|
||||
ok(h2 != 0 && winerr == ERROR_ALREADY_EXISTS,
|
||||
"CreateFileMappingA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%ld)\n", h2, winerr);
|
||||
"CreateFileMappingA should have succeeded with ERROR_ALREADY_EXISTS got ret=%p (%d)\n", h2, winerr);
|
||||
pNtClose(h);
|
||||
pNtClose(h1);
|
||||
pNtClose(h2);
|
||||
@@ -278,7 +279,7 @@ static void test_name_collisions(void)
|
||||
pNtClose(dir);
|
||||
}
|
||||
|
||||
void test_directory(void)
|
||||
static void test_directory(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING str;
|
||||
@@ -288,17 +289,17 @@ void test_directory(void)
|
||||
/* No name and/or no attributes */
|
||||
status = pNtCreateDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
|
||||
ok(status == STATUS_ACCESS_VIOLATION,
|
||||
"NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08lx)\n", status);
|
||||
"NtCreateDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
|
||||
status = pNtOpenDirectoryObject(NULL, DIRECTORY_QUERY, &attr);
|
||||
ok(status == STATUS_ACCESS_VIOLATION,
|
||||
"NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08lx)\n", status);
|
||||
"NtOpenDirectoryObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
|
||||
|
||||
status = pNtCreateDirectoryObject(&h, DIRECTORY_QUERY, NULL);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Directory without attributes(%08x)\n", status);
|
||||
pNtClose(h);
|
||||
status = pNtOpenDirectoryObject(&h, DIRECTORY_QUERY, NULL);
|
||||
ok(status == STATUS_INVALID_PARAMETER,
|
||||
"NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08lx)\n", status);
|
||||
"NtOpenDirectoryObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
|
||||
|
||||
InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
|
||||
DIR_TEST_CREATE_SUCCESS(&dir)
|
||||
@@ -333,8 +334,8 @@ void test_directory(void)
|
||||
/* Can't use symlinks as a directory */
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "\\BaseNamedObjects\\Local");
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
status = pNtOpenSymbolicLinkObject(&dir, SYMBOLIC_LINK_QUERY, &attr);\
|
||||
ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08lx)\n", status);
|
||||
status = pNtOpenSymbolicLinkObject(&dir, SYMBOLIC_LINK_QUERY, &attr);
|
||||
ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "one more level");
|
||||
@@ -352,7 +353,7 @@ void test_directory(void)
|
||||
DIR_TEST_OPEN_FAILURE(&h, STATUS_OBJECT_NAME_INVALID)
|
||||
|
||||
InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
|
||||
DIR_TEST_CREATE_OPEN_SUCCESS(&h, "")
|
||||
DIR_TEST_CREATE_OPEN_SUCCESS(h, "")
|
||||
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
|
||||
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test", STATUS_OBJECT_PATH_SYNTAX_BAD)
|
||||
DIR_TEST_CREATE_OPEN_FAILURE(&h, "\\om.c-test\\", STATUS_OBJECT_PATH_SYNTAX_BAD)
|
||||
@@ -417,27 +418,27 @@ void test_directory(void)
|
||||
pRtlFreeUnicodeString(&str);
|
||||
InitializeObjectAttributes(&attr, &str, 0, dir, NULL);
|
||||
|
||||
/* Test inavalid paths */
|
||||
/* Test invalid paths */
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant");
|
||||
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08lx)\n", status);
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant\\");
|
||||
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08lx)\n", status);
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "om.c\\-mutant");
|
||||
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08lx)\n", status);
|
||||
"NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "om.c-mutant");
|
||||
status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
pNtClose(h);
|
||||
|
||||
@@ -446,10 +447,10 @@ void test_directory(void)
|
||||
|
||||
#define SYMLNK_TEST_CREATE_FAILURE(h,e) \
|
||||
status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target);\
|
||||
ok(status == e,"NtCreateSymbolicLinkObject should have failed with %s got(%08lx)\n", #e, status);
|
||||
ok(status == e,"NtCreateSymbolicLinkObject should have failed with %s got(%08x)\n", #e, status);
|
||||
#define SYMLNK_TEST_OPEN_FAILURE(h,e) \
|
||||
status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr);\
|
||||
ok(status == e,"NtOpenSymbolicLinkObject should have failed with %s got(%08lx)\n", #e, status);
|
||||
ok(status == e,"NtOpenSymbolicLinkObject should have failed with %s got(%08x)\n", #e, status);
|
||||
#define SYMLNK_TEST_CREATE_OPEN_FAILURE(h,n,t,e) \
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, n);\
|
||||
pRtlCreateUnicodeStringFromAsciiz(&target, t);\
|
||||
@@ -460,12 +461,12 @@ void test_directory(void)
|
||||
|
||||
#define SYMLNK_TEST_CREATE_SUCCESS(h) \
|
||||
status = pNtCreateSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr, &target); \
|
||||
ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to create SymbolicLink(%08x)\n", status);
|
||||
#define SYMLNK_TEST_OPEN_SUCCESS(h) \
|
||||
status = pNtOpenSymbolicLinkObject(h, SYMBOLIC_LINK_QUERY, &attr); \
|
||||
ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08lx)\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Failed to open SymbolicLink(%08x)\n", status);
|
||||
|
||||
void test_symboliclink(void)
|
||||
static void test_symboliclink(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING str, target;
|
||||
@@ -478,10 +479,17 @@ void test_symboliclink(void)
|
||||
|
||||
status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, NULL);
|
||||
ok(status == STATUS_ACCESS_VIOLATION,
|
||||
"NtCreateSymbolicLinkObject should have failed with STATUS_ACCESS_VIOLATION got(%08lx)\n", status);
|
||||
"NtCreateSymbolicLinkObject should have failed with STATUS_ACCESS_VIOLATION got(%08x)\n", status);
|
||||
status = pNtOpenSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL);
|
||||
ok(status == STATUS_INVALID_PARAMETER,
|
||||
"NtOpenSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08lx)\n", status);
|
||||
"NtOpenSymbolicLinkObject should have failed with STATUS_INVALID_PARAMETER got(%08x)\n", status);
|
||||
|
||||
/* No attributes */
|
||||
pRtlCreateUnicodeStringFromAsciiz(&target, "\\DosDevices");
|
||||
status = pNtCreateSymbolicLinkObject(&h, SYMBOLIC_LINK_QUERY, NULL, &target);
|
||||
ok(status == STATUS_SUCCESS, "NtCreateSymbolicLinkObject failed(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&target);
|
||||
pNtClose(h);
|
||||
|
||||
InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
|
||||
SYMLNK_TEST_CREATE_FAILURE(&link, STATUS_INVALID_PARAMETER)
|
||||
@@ -523,7 +531,7 @@ void test_symboliclink(void)
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&str, "Local\\test-link\\PIPE");
|
||||
status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
|
||||
todo_wine ok(status == STATUS_SUCCESS, "Failed to open NamedPipe(%08lx)\n", status);
|
||||
todo_wine ok(status == STATUS_SUCCESS, "Failed to open NamedPipe(%08x)\n", status);
|
||||
pRtlFreeUnicodeString(&str);
|
||||
|
||||
pNtClose(h);
|
||||
@@ -534,29 +542,36 @@ void test_symboliclink(void)
|
||||
START_TEST(om)
|
||||
{
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||
if (hntdll)
|
||||
{
|
||||
pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
|
||||
pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
|
||||
pNtCreateEvent = (void *)GetProcAddress(hntdll, "NtCreateEvent");
|
||||
pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant");
|
||||
pNtOpenMutant = (void *)GetProcAddress(hntdll, "NtOpenMutant");
|
||||
pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
|
||||
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
|
||||
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
|
||||
pNtCreateNamedPipeFile = (void *)GetProcAddress(hntdll, "NtCreateNamedPipeFile");
|
||||
pNtOpenDirectoryObject = (void *)GetProcAddress(hntdll, "NtOpenDirectoryObject");
|
||||
pNtCreateDirectoryObject= (void *)GetProcAddress(hntdll, "NtCreateDirectoryObject");
|
||||
pNtOpenSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtOpenSymbolicLinkObject");
|
||||
pNtCreateSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtCreateSymbolicLinkObject");
|
||||
pNtCreateSemaphore = (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
|
||||
pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer");
|
||||
pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
|
||||
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
|
||||
|
||||
test_case_sensitive();
|
||||
test_namespace_pipe();
|
||||
test_name_collisions();
|
||||
test_directory();
|
||||
test_symboliclink();
|
||||
if (!hntdll)
|
||||
{
|
||||
skip("not running on NT, skipping test\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pCreateWaitableTimerA = (void *)GetProcAddress(hkernel32, "CreateWaitableTimerA");
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
|
||||
pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
|
||||
pNtCreateEvent = (void *)GetProcAddress(hntdll, "NtCreateEvent");
|
||||
pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant");
|
||||
pNtOpenMutant = (void *)GetProcAddress(hntdll, "NtOpenMutant");
|
||||
pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
|
||||
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
|
||||
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
|
||||
pNtCreateNamedPipeFile = (void *)GetProcAddress(hntdll, "NtCreateNamedPipeFile");
|
||||
pNtOpenDirectoryObject = (void *)GetProcAddress(hntdll, "NtOpenDirectoryObject");
|
||||
pNtCreateDirectoryObject= (void *)GetProcAddress(hntdll, "NtCreateDirectoryObject");
|
||||
pNtOpenSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtOpenSymbolicLinkObject");
|
||||
pNtCreateSymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtCreateSymbolicLinkObject");
|
||||
pNtCreateSemaphore = (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
|
||||
pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer");
|
||||
pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
|
||||
|
||||
test_case_sensitive();
|
||||
test_namespace_pipe();
|
||||
test_name_collisions();
|
||||
test_directory();
|
||||
test_symboliclink();
|
||||
}
|
||||
|
||||
@@ -101,23 +101,22 @@ static void test_RtlIsDosDeviceName(void)
|
||||
{ "", 0, 0 },
|
||||
{ "\\\\foo\\nul", 0, 0 },
|
||||
{ "c:\\nul:", 6, 6 },
|
||||
{ "c:\\nul::", 0, 0 },
|
||||
{ "c:\\nul::", 6, 6 },
|
||||
{ "c:\\nul::::::", 6, 6 },
|
||||
{ "c:prn ", 4, 6 },
|
||||
{ "c:prn.......", 4, 6 },
|
||||
{ "c:prn... ...", 4, 6 },
|
||||
{ "c:NUL .... ", 0, 0 },
|
||||
{ "c:NUL .... ", 4, 6 },
|
||||
{ "c: . . .", 0, 0 },
|
||||
{ "c:", 0, 0 },
|
||||
{ " . . . :", 0, 0 },
|
||||
{ ":", 0, 0 },
|
||||
{ "c:nul. . . :", 4, 6 },
|
||||
{ "c:nul . . :", 0, 0 },
|
||||
{ "c:nul . . :", 4, 6 },
|
||||
{ "c:nul0", 0, 0 },
|
||||
{ "c:prn:aaa", 0, 0 },
|
||||
{ "c:PRN:.txt", 4, 6 },
|
||||
{ "c:aux:.txt...", 4, 6 },
|
||||
{ "c:prn:.txt:", 4, 6 },
|
||||
{ "c:nul:aaa", 0, 0 },
|
||||
{ "con:", 0, 6 },
|
||||
{ "lpt1:", 0, 8 },
|
||||
{ "c:com5:", 4, 8 },
|
||||
@@ -146,6 +145,18 @@ static void test_RtlIsDosDeviceName(void)
|
||||
"Wrong result (%d,%d)/(%d,%d) for %s\n",
|
||||
HIWORD(ret), LOWORD(ret), test->pos, test->len, test->path );
|
||||
}
|
||||
|
||||
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, "c:prn:aaa", strlen("c:prn:aaa")+1 );
|
||||
ret = pRtlIsDosDeviceName_U( buffer );
|
||||
ok( ret == MAKELONG( 6, 4 ) || /* NT */
|
||||
ret == MAKELONG( 0, 0), /* win9x */
|
||||
"Wrong result (%d,%d)/(4,6) or (0,0) for c:prn:aaa\n", HIWORD(ret), LOWORD(ret) );
|
||||
|
||||
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, "c:nul:aaa", strlen("c:nul:aaa")+1 );
|
||||
ret = pRtlIsDosDeviceName_U( buffer );
|
||||
ok( ret == MAKELONG( 6, 4 ) || /* NT */
|
||||
ret == MAKELONG( 0, 0), /* win9x */
|
||||
"Wrong result (%d,%d)/(4,6) or (0,0) for c:nul:aaa\n", HIWORD(ret), LOWORD(ret) );
|
||||
}
|
||||
|
||||
static void test_RtlIsNameLegalDOS8Dot3(void)
|
||||
@@ -213,7 +224,7 @@ static void test_RtlIsNameLegalDOS8Dot3(void)
|
||||
strcpy( str, test->path );
|
||||
for (i = 0; str[i]; i++) str[i] = toupper(str[i]);
|
||||
ok( oem_ret.Length == strlen(test->path), "Wrong length %d/%d for '%s'\n",
|
||||
oem_ret.Length, strlen(test->path), test->path );
|
||||
oem_ret.Length, lstrlenA(test->path), test->path );
|
||||
ok( !memcmp( oem_ret.Buffer, str, oem_ret.Length ),
|
||||
"Wrong string '%.*s'/'%s'\n", oem_ret.Length, oem_ret.Buffer, str );
|
||||
}
|
||||
@@ -265,7 +276,7 @@ static void test_RtlGetFullPathName_U(void)
|
||||
len= strlen(test->rname) * sizeof(WCHAR);
|
||||
pRtlMultiByteToUnicodeN(pathbufW , sizeof(pathbufW), NULL, test->path, strlen(test->path)+1 );
|
||||
ret = pRtlGetFullPathName_U( pathbufW,MAX_PATH, rbufferW, &file_part);
|
||||
ok( ret == len, "Wrong result %ld/%d for \"%s\"\n", ret, len, test->path );
|
||||
ok( ret == len, "Wrong result %d/%d for \"%s\"\n", ret, len, test->path );
|
||||
ok(pRtlUnicodeToMultiByteN(rbufferA,MAX_PATH,&reslen,rbufferW,(lstrlenW(rbufferW) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
|
||||
"RtlUnicodeToMultiByteN failed\n");
|
||||
ok(lstrcmpiA(rbufferA,test->rname) == 0, "Got \"%s\" expected \"%s\"\n",rbufferA,test->rname);
|
||||
|
||||
@@ -20,8 +20,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ntdll_test.h"
|
||||
#include "windows.h"
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "winreg.h"
|
||||
#include "winnls.h"
|
||||
#include "wine/test.h"
|
||||
#include "winternl.h"
|
||||
|
||||
#ifndef __WINE_WINTERNL_H
|
||||
|
||||
@@ -146,10 +153,10 @@ static void ProcessConnectionRequest(PLPC_MESSAGE LpcMessage, PHANDLE pAcceptPor
|
||||
ok(!*LpcMessage->Data, "Expected empty string!\n");
|
||||
|
||||
status = pNtAcceptConnectPort(pAcceptPortHandle, 0, LpcMessage, 1, 0, NULL);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
|
||||
status = pNtCompleteConnectPort(*pAcceptPortHandle);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
}
|
||||
|
||||
static void ProcessLpcRequest(HANDLE PortHandle, PLPC_MESSAGE LpcMessage)
|
||||
@@ -164,7 +171,7 @@ static void ProcessLpcRequest(HANDLE PortHandle, PLPC_MESSAGE LpcMessage)
|
||||
lstrcpy((LPSTR)LpcMessage->Data, REPLY);
|
||||
|
||||
status = pNtReplyPort(PortHandle, LpcMessage);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
ok(LpcMessage->MessageType == LPC_REQUEST,
|
||||
"Expected LPC_REQUEST, got %d\n", LpcMessage->MessageType);
|
||||
ok(!lstrcmp((LPSTR)LpcMessage->Data, REPLY),
|
||||
@@ -185,22 +192,22 @@ static DWORD WINAPI test_ports_client(LPVOID arg)
|
||||
sqos.EffectiveOnly = TRUE;
|
||||
|
||||
status = pNtConnectPort(&PortHandle, &port, &sqos, 0, 0, &len, NULL, NULL);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
todo_wine ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
if (status != STATUS_SUCCESS) return 1;
|
||||
|
||||
status = pNtRegisterThreadTerminatePort(PortHandle);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
|
||||
size = FIELD_OFFSET(LPC_MESSAGE, Data) + MAX_MESSAGE_LEN;
|
||||
LpcMessage = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
out = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
|
||||
memset(LpcMessage, 0, size);
|
||||
LpcMessage->DataSize = lstrlen(REQUEST1) + 1;
|
||||
LpcMessage->MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data) + LpcMessage->DataSize;
|
||||
lstrcpy((LPSTR)LpcMessage->Data, REQUEST1);
|
||||
|
||||
status = pNtRequestPort(PortHandle, LpcMessage);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
ok(LpcMessage->MessageType == 0, "Expected 0, got %d\n", LpcMessage->MessageType);
|
||||
ok(!lstrcmp((LPSTR)LpcMessage->Data, REQUEST1),
|
||||
"Expected %s, got %s\n", REQUEST1, LpcMessage->Data);
|
||||
@@ -213,7 +220,7 @@ static DWORD WINAPI test_ports_client(LPVOID arg)
|
||||
|
||||
/* Send the message and wait for the reply */
|
||||
status = pNtRequestWaitReplyPort(PortHandle, LpcMessage, out);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
ok(!lstrcmp((LPSTR)out->Data, REPLY), "Expected %s, got %s\n", REPLY, out->Data);
|
||||
ok(out->MessageType == LPC_REPLY, "Expected LPC_REPLY, got %d\n", out->MessageType);
|
||||
|
||||
@@ -239,19 +246,19 @@ static void test_ports_server(void)
|
||||
status = pNtCreatePort(&PortHandle, &obj, 100, 100, 0);
|
||||
todo_wine
|
||||
{
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld\n", status);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
|
||||
}
|
||||
if (status != STATUS_SUCCESS) return;
|
||||
|
||||
size = FIELD_OFFSET(LPC_MESSAGE, Data) + MAX_MESSAGE_LEN;
|
||||
LpcMessage = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
memset(LpcMessage, 0, size);
|
||||
LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
status = pNtReplyWaitReceivePort(PortHandle, NULL, NULL, LpcMessage);
|
||||
todo_wine
|
||||
{
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %ld(%lx)\n", status, status);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d(%x)\n", status, status);
|
||||
}
|
||||
/* STATUS_INVALID_HANDLE: win2k without admin rights will perform an
|
||||
* endless loop here
|
||||
|
||||
+225
-62
@@ -2,7 +2,6 @@
|
||||
*
|
||||
* Copyright 2003 Thomas Mertes
|
||||
* Copyright 2005 Brad DeMorrow
|
||||
* Copyright 2006 Dmitry Philippov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -68,6 +67,37 @@ typedef struct _RTL_QUERY_REGISTRY_TABLE {
|
||||
ULONG DefaultLength;
|
||||
} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
|
||||
|
||||
typedef struct _KEY_VALUE_BASIC_INFORMATION {
|
||||
ULONG TitleIndex;
|
||||
ULONG Type;
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1];
|
||||
} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
|
||||
ULONG TitleIndex;
|
||||
ULONG Type;
|
||||
ULONG DataLength;
|
||||
UCHAR Data[1];
|
||||
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
|
||||
|
||||
typedef struct _KEY_VALUE_FULL_INFORMATION {
|
||||
ULONG TitleIndex;
|
||||
ULONG Type;
|
||||
ULONG DataOffset;
|
||||
ULONG DataLength;
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1];
|
||||
} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
|
||||
|
||||
typedef enum _KEY_VALUE_INFORMATION_CLASS {
|
||||
KeyValueBasicInformation,
|
||||
KeyValueFullInformation,
|
||||
KeyValuePartialInformation,
|
||||
KeyValueFullInformationAlign64,
|
||||
KeyValuePartialInformationAlign64
|
||||
} KEY_VALUE_INFORMATION_CLASS;
|
||||
|
||||
#define InitializeObjectAttributes(p,n,a,r,s) \
|
||||
do { \
|
||||
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
|
||||
@@ -85,18 +115,18 @@ static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
|
||||
static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
|
||||
static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID);
|
||||
static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
|
||||
static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHANDLE);
|
||||
static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHKEY);
|
||||
static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
|
||||
static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
|
||||
static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
|
||||
static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE);
|
||||
static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
|
||||
static NTSTATUS (WINAPI * pNtFlushKey)(HKEY);
|
||||
static NTSTATUS (WINAPI * pNtDeleteKey)(HKEY);
|
||||
static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
|
||||
ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
|
||||
PULONG dispos );
|
||||
static NTSTATUS (WINAPI * pNtSetValueKey)( HANDLE, const PUNICODE_STRING, ULONG,
|
||||
static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *);
|
||||
static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG,
|
||||
ULONG, const PVOID, ULONG );
|
||||
static NTSTATUS (WINAPI * pNtQueryValueKey)( HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,
|
||||
void *,DWORD,DWORD * );
|
||||
static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
|
||||
static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
|
||||
static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
|
||||
@@ -105,6 +135,7 @@ static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRIN
|
||||
static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
|
||||
static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
|
||||
static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
|
||||
static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*);
|
||||
|
||||
static HMODULE hntdll = 0;
|
||||
static int CurrentTest = 0;
|
||||
@@ -137,9 +168,10 @@ static BOOL InitFunctionPtrs(void)
|
||||
NTDLL_GET_PROC(NtClose)
|
||||
NTDLL_GET_PROC(NtDeleteValueKey)
|
||||
NTDLL_GET_PROC(NtCreateKey)
|
||||
NTDLL_GET_PROC(NtFlushKey)
|
||||
NTDLL_GET_PROC(NtDeleteKey)
|
||||
NTDLL_GET_PROC(NtSetValueKey)
|
||||
NTDLL_GET_PROC(NtQueryValueKey)
|
||||
NTDLL_GET_PROC(NtSetValueKey)
|
||||
NTDLL_GET_PROC(NtOpenKey)
|
||||
NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
|
||||
NTDLL_GET_PROC(RtlReAllocateHeap)
|
||||
@@ -148,6 +180,7 @@ static BOOL InitFunctionPtrs(void)
|
||||
NTDLL_GET_PROC(RtlFreeHeap)
|
||||
NTDLL_GET_PROC(RtlAllocateHeap)
|
||||
NTDLL_GET_PROC(RtlZeroMemory)
|
||||
NTDLL_GET_PROC(RtlpNtQueryValueKey)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -157,9 +190,8 @@ static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN
|
||||
IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
|
||||
{
|
||||
NTSTATUS ret = STATUS_SUCCESS;
|
||||
LPSTR ValName = 0;
|
||||
LPSTR ValData = 0;
|
||||
int ValueNameLength = 0;
|
||||
LPSTR ValName = 0;
|
||||
trace("**Test %d**\n", CurrentTest);
|
||||
|
||||
if(ValueName)
|
||||
@@ -167,6 +199,7 @@ static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN
|
||||
ValueNameLength = lstrlenW(ValueName);
|
||||
|
||||
ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
|
||||
|
||||
WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
|
||||
|
||||
trace("ValueName: %s\n", ValName);
|
||||
@@ -174,14 +207,6 @@ static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN
|
||||
else
|
||||
trace("ValueName: (null)\n");
|
||||
|
||||
if( ValueType == REG_SZ ||
|
||||
ValueType == REG_MULTI_SZ ||
|
||||
ValueType == REG_EXPAND_SZ )
|
||||
{
|
||||
ValData = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueLength);
|
||||
WideCharToMultiByte(0, 0, ValueData, ValueLength, ValData, ValueLength, 0, 0);
|
||||
}
|
||||
|
||||
switch(ValueType)
|
||||
{
|
||||
case REG_NONE:
|
||||
@@ -196,17 +221,17 @@ static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN
|
||||
|
||||
case REG_SZ:
|
||||
trace("ValueType: REG_SZ\n");
|
||||
trace("ValueData: %s\n", ValData);
|
||||
trace("ValueData: %s\n", (char*)ValueData);
|
||||
break;
|
||||
|
||||
case REG_MULTI_SZ:
|
||||
trace("ValueType: REG_MULTI_SZ\n");
|
||||
trace("ValueData: %s", (char*)ValData);
|
||||
trace("ValueData: %s\n", (char*)ValueData);
|
||||
break;
|
||||
|
||||
case REG_EXPAND_SZ:
|
||||
trace("ValueType: REG_EXPAND_SZ\n");
|
||||
trace("ValueData: %s\n", (char*)ValData);
|
||||
trace("ValueData: %s\n", (char*)ValueData);
|
||||
break;
|
||||
|
||||
case REG_DWORD:
|
||||
@@ -226,9 +251,6 @@ static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN
|
||||
if(ValName)
|
||||
pRtlFreeHeap(GetProcessHeap(), 0, ValName);
|
||||
|
||||
if(ValData)
|
||||
pRtlFreeHeap(GetProcessHeap(), 0, ValData);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -261,7 +283,7 @@ static void test_RtlQueryRegistryValues(void)
|
||||
8)DefaultLength Test Default Length with DefaultType = REG_SZ
|
||||
9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
|
||||
10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
|
||||
11)DefaultData Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
|
||||
11)DefaultData Test whether DefaultData is used while DefaultType = REG_NONE(shouldn't be)
|
||||
12)Delete Try to delete value key
|
||||
|
||||
*/
|
||||
@@ -284,14 +306,14 @@ static void test_RtlQueryRegistryValues(void)
|
||||
QueryTable[0].DefaultLength = 100;
|
||||
|
||||
QueryTable[1].QueryRoutine = QueryRoutine;
|
||||
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DELETE;
|
||||
QueryTable[1].Name = L"multisztest";
|
||||
QueryTable[1].Flags = 0;
|
||||
QueryTable[1].Name = NULL;
|
||||
QueryTable[1].EntryContext = 0;
|
||||
QueryTable[1].DefaultType = REG_NONE;
|
||||
QueryTable[1].DefaultData = NULL;
|
||||
QueryTable[1].DefaultLength = 0;
|
||||
|
||||
QueryTable[2].QueryRoutine = QueryRoutine;
|
||||
QueryTable[2].QueryRoutine = NULL;
|
||||
QueryTable[2].Flags = 0;
|
||||
QueryTable[2].Name = NULL;
|
||||
QueryTable[2].EntryContext = 0;
|
||||
@@ -300,22 +322,84 @@ static void test_RtlQueryRegistryValues(void)
|
||||
QueryTable[2].DefaultLength = 0;
|
||||
|
||||
status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
|
||||
ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08x\n", status);
|
||||
|
||||
pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
|
||||
}
|
||||
|
||||
static void test_NtOpenKey(void)
|
||||
{
|
||||
HANDLE key;
|
||||
NTSTATUS status;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
ACCESS_MASK am = KEY_READ;
|
||||
|
||||
if (0)
|
||||
{
|
||||
/* Crashes Wine */
|
||||
/* All NULL */
|
||||
status = pNtOpenKey(NULL, 0, NULL);
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
|
||||
|
||||
/* NULL attributes */
|
||||
status = pNtOpenKey(&key, 0, NULL);
|
||||
ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
|
||||
|
||||
/* NULL key */
|
||||
status = pNtOpenKey(NULL, 0, &attr);
|
||||
todo_wine
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
|
||||
|
||||
/* Length > sizeof(OBJECT_ATTRIBUTES) */
|
||||
attr.Length *= 2;
|
||||
status = pNtOpenKey(&key, am, &attr);
|
||||
todo_wine
|
||||
ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
|
||||
}
|
||||
|
||||
static void test_NtCreateKey(void)
|
||||
{
|
||||
/*Create WineTest*/
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
HANDLE key;
|
||||
HKEY key;
|
||||
ACCESS_MASK am = GENERIC_ALL;
|
||||
NTSTATUS status;
|
||||
|
||||
/* All NULL */
|
||||
status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
|
||||
|
||||
/* Only the key */
|
||||
status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
|
||||
ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
|
||||
|
||||
/* Only accessmask */
|
||||
status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
|
||||
|
||||
/* Key and accessmask */
|
||||
status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
|
||||
ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
|
||||
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
|
||||
|
||||
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
|
||||
|
||||
/* Only attributes */
|
||||
status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
|
||||
|
||||
status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
|
||||
ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status);
|
||||
|
||||
/* Length > sizeof(OBJECT_ATTRIBUTES) */
|
||||
attr.Length *= 2;
|
||||
status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
|
||||
ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
|
||||
|
||||
pNtClose(key);
|
||||
}
|
||||
@@ -327,39 +411,27 @@ static void test_NtSetValueKey(void)
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
ACCESS_MASK am = KEY_WRITE;
|
||||
UNICODE_STRING ValName;
|
||||
UNICODE_STRING ValNameMultiSz;
|
||||
DWORD data = 711;
|
||||
static const WCHAR DataMultiSz[] = {'T','e','s','t','V','a','l','u','e','1',0,
|
||||
'T','e','s','t','V','a','l','u','e','2',0,
|
||||
'T','e','s','t','V','a','l','u','e','3',0,0,
|
||||
'T','e','s','t','V','a','l','u','e','5',0,0,0};
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
|
||||
|
||||
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
|
||||
status = pNtOpenKey(&key, am, &attr);
|
||||
ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
|
||||
|
||||
status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
|
||||
ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
|
||||
|
||||
pRtlFreeUnicodeString(&ValName);
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&ValNameMultiSz, "multisztest");
|
||||
|
||||
status = pNtSetValueKey(key, &ValNameMultiSz, 0, REG_MULTI_SZ, (PVOID)DataMultiSz, sizeof(DataMultiSz));
|
||||
ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status);
|
||||
|
||||
pRtlFreeUnicodeString(&ValNameMultiSz);
|
||||
|
||||
pNtClose(key);
|
||||
}
|
||||
|
||||
static void test_RtlOpenCurrentUser(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE handle;
|
||||
HKEY handle;
|
||||
status=pRtlOpenCurrentUser(KEY_READ, &handle);
|
||||
ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
|
||||
pNtClose(handle);
|
||||
}
|
||||
|
||||
@@ -368,32 +440,111 @@ static void test_RtlCheckRegistryKey(void)
|
||||
NTSTATUS status;
|
||||
|
||||
status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
|
||||
ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
|
||||
|
||||
status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
|
||||
ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
|
||||
}
|
||||
|
||||
static void test_RtlQueryRegistryDelete(void)
|
||||
static void test_NtFlushKey(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE hkey;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
ACCESS_MASK am = KEY_ALL_ACCESS;
|
||||
|
||||
status = pNtFlushKey(NULL);
|
||||
ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
|
||||
|
||||
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
|
||||
pNtOpenKey(&hkey, am, &attr);
|
||||
|
||||
status = pNtFlushKey(hkey);
|
||||
ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
|
||||
|
||||
pNtClose(hkey);
|
||||
}
|
||||
|
||||
static void test_NtQueryValueKey(void)
|
||||
{
|
||||
HANDLE key;
|
||||
NTSTATUS status;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING ValNameMultiSz;
|
||||
WCHAR sBuf[255];
|
||||
DWORD ValueSize;
|
||||
UNICODE_STRING ValName;
|
||||
KEY_VALUE_BASIC_INFORMATION *basic_info;
|
||||
KEY_VALUE_PARTIAL_INFORMATION *partial_info;
|
||||
KEY_VALUE_FULL_INFORMATION *full_info;
|
||||
DWORD len;
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
|
||||
|
||||
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
|
||||
status = pNtOpenKey(&key, KEY_READ, &attr);
|
||||
ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&ValNameMultiSz, "multisztest");
|
||||
len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
|
||||
basic_info = HeapAlloc(GetProcessHeap(), 0, len);
|
||||
status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
|
||||
ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
|
||||
ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->Type);
|
||||
ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
|
||||
ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
|
||||
ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
|
||||
|
||||
status = pNtQueryValueKey(key, &ValNameMultiSz, 0, (void*)sBuf, sizeof(sBuf), &ValueSize);
|
||||
ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey returns: 0x%08lx instead of STATUS_OBJECT_NAME_NOT_FOUND\n", status);
|
||||
basic_info = HeapReAlloc(GetProcessHeap(), 0, basic_info, len);
|
||||
status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
|
||||
ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
|
||||
ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->Type);
|
||||
ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
|
||||
ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
|
||||
ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
|
||||
ok(!memcmp(basic_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
|
||||
HeapFree(GetProcessHeap(), 0, basic_info);
|
||||
|
||||
pRtlFreeUnicodeString(&ValNameMultiSz);
|
||||
len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
|
||||
partial_info = HeapAlloc(GetProcessHeap(), 0, len);
|
||||
status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
|
||||
ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
|
||||
ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->Type);
|
||||
ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
|
||||
ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
|
||||
ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
|
||||
|
||||
partial_info = HeapReAlloc(GetProcessHeap(), 0, partial_info, len);
|
||||
status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
|
||||
ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
|
||||
ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->Type);
|
||||
ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
|
||||
ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
|
||||
ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
|
||||
ok(*(DWORD *)partial_info->Data == 711, "incorrect Data returned: 0x%x\n", *(DWORD *)partial_info->Data);
|
||||
HeapFree(GetProcessHeap(), 0, partial_info);
|
||||
|
||||
len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
|
||||
full_info = HeapAlloc(GetProcessHeap(), 0, len);
|
||||
status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
|
||||
ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
|
||||
ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->Type);
|
||||
ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
|
||||
ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
|
||||
ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
|
||||
ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength,
|
||||
"NtQueryValueKey returned wrong len %d\n", len);
|
||||
len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength;
|
||||
|
||||
full_info = HeapReAlloc(GetProcessHeap(), 0, full_info, len);
|
||||
status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
|
||||
ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
|
||||
ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->Type);
|
||||
ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
|
||||
ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
|
||||
ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
|
||||
ok(!memcmp(full_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
|
||||
ok(*(DWORD *)((char *)full_info + full_info->DataOffset) == 711, "incorrect Data returned: 0x%x\n",
|
||||
*(DWORD *)((char *)full_info + full_info->DataOffset));
|
||||
HeapFree(GetProcessHeap(), 0, full_info);
|
||||
|
||||
pRtlFreeUnicodeString(&ValName);
|
||||
pNtClose(key);
|
||||
}
|
||||
|
||||
@@ -404,13 +555,22 @@ static void test_NtDeleteKey(void)
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
ACCESS_MASK am = KEY_ALL_ACCESS;
|
||||
|
||||
status = pNtDeleteKey(NULL);
|
||||
ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
|
||||
|
||||
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
|
||||
status = pNtOpenKey(&hkey, am, &attr);
|
||||
|
||||
status = pNtDeleteKey(hkey);
|
||||
ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
|
||||
}
|
||||
|
||||
pNtClose(hkey);
|
||||
static void test_RtlpNtQueryValueKey(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL);
|
||||
ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
|
||||
}
|
||||
|
||||
START_TEST(reg)
|
||||
@@ -425,12 +585,15 @@ START_TEST(reg)
|
||||
|
||||
pRtlAppendUnicodeToString(&winetestpath, winetest);
|
||||
|
||||
test_NtOpenKey();
|
||||
test_NtCreateKey();
|
||||
test_NtSetValueKey();
|
||||
test_RtlCheckRegistryKey();
|
||||
test_RtlOpenCurrentUser();
|
||||
test_RtlQueryRegistryValues();
|
||||
test_RtlQueryRegistryDelete();
|
||||
test_RtlpNtQueryValueKey();
|
||||
test_NtFlushKey();
|
||||
test_NtQueryValueKey();
|
||||
test_NtDeleteKey();
|
||||
|
||||
pRtlFreeUnicodeString(&winetestpath);
|
||||
|
||||
@@ -130,39 +130,39 @@ static void test_RtlCompareMemoryUlong(void)
|
||||
a[2]= 0x89ab;
|
||||
a[3]= 0xcdef;
|
||||
result = pRtlCompareMemoryUlong(a, 0, 0x0123);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 0, 0x0123) returns %lu, expected 0\n", a, result);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 0, 0x0123) returns %u, expected 0\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 3, 0x0123);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %lu, expected 0\n", a, result);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %u, expected 0\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 4, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 5, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 7, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 8, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 9, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 4, 0x0127);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x0127) returns %lu, expected 0\n", a, result);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x0127) returns %u, expected 0\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 4, 0x7123);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x7123) returns %lu, expected 0\n", a, result);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x7123) returns %u, expected 0\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 16, 0x4567);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 16, 0x4567) returns %lu, expected 0\n", a, result);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 16, 0x4567) returns %u, expected 0\n", a, result);
|
||||
|
||||
a[1]= 0x0123;
|
||||
result = pRtlCompareMemoryUlong(a, 3, 0x0123);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %lu, expected 0\n", a, result);
|
||||
ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %u, expected 0\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 4, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 5, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 7, 0x0123);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %lu, expected 4\n", a, result);
|
||||
ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %u, expected 4\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 8, 0x0123);
|
||||
ok(result == 8, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %lu, expected 8\n", a, result);
|
||||
ok(result == 8, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %u, expected 8\n", a, result);
|
||||
result = pRtlCompareMemoryUlong(a, 9, 0x0123);
|
||||
ok(result == 8, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %lu, expected 8\n", a, result);
|
||||
ok(result == 8, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %u, expected 8\n", a, result);
|
||||
}
|
||||
|
||||
#define COPY(len) memset(dest,0,sizeof(dest_aligned_block)); pRtlMoveMemory(dest, src, len)
|
||||
@@ -266,8 +266,8 @@ static void test_RtlUlonglongByteSwap(void)
|
||||
|
||||
result = pRtlUlonglongByteSwap( ((ULONGLONG)0x76543210 << 32) | 0x87654321 );
|
||||
ok( (((ULONGLONG)0x21436587 << 32) | 0x10325476) == result,
|
||||
"RtlUlonglongByteSwap(0x7654321087654321) returns 0x%llx, expected 0x2143658710325476\n",
|
||||
result);
|
||||
"RtlUlonglongByteSwap(0x7654321087654321) returns 0x%x%08x, expected 0x2143658710325476\n",
|
||||
(DWORD)(result >> 32), (DWORD)result);
|
||||
}
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ static void test_RtlUniform(void)
|
||||
expected = 0x7fffffc3;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 0)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 0)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
/*
|
||||
* The algorithm is now:
|
||||
@@ -322,7 +322,7 @@ static void test_RtlUniform(void)
|
||||
expected = seed * 0xffffffed + 0x7fffffc3 + 1;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 1)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 1)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
/*
|
||||
* For seed = 2 the const_2 is 0x7fffffc3:
|
||||
@@ -330,9 +330,21 @@ static void test_RtlUniform(void)
|
||||
seed = 2;
|
||||
expected = seed * 0xffffffed + 0x7fffffc3;
|
||||
result = pRtlUniform(&seed);
|
||||
|
||||
/*
|
||||
* Windows Vista uses different algorithms, so skip the rest of the tests
|
||||
* until that is figured out. Trace output for the failures is about 10.5 MB!
|
||||
*/
|
||||
|
||||
if (result == 0x7fffff9f) {
|
||||
skip("Most likely running on Windows Vista which uses a different algorithm\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 2)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 2)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
|
||||
/*
|
||||
* More tests show that if seed is odd the result must be incremented by 1:
|
||||
*/
|
||||
@@ -340,21 +352,21 @@ static void test_RtlUniform(void)
|
||||
expected = seed * 0xffffffed + 0x7fffffc3 + (seed & 1);
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 2)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 3)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
|
||||
seed = 0x6bca1aa;
|
||||
expected = seed * 0xffffffed + 0x7fffffc3;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 0x6bca1aa)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 0x6bca1aa)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
|
||||
seed = 0x6bca1ab;
|
||||
expected = seed * 0xffffffed + 0x7fffffc3 + 1;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 0x6bca1ab)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 0x6bca1ab)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
/*
|
||||
* When seed is 0x6bca1ac there is an exception:
|
||||
@@ -363,7 +375,7 @@ static void test_RtlUniform(void)
|
||||
expected = seed * 0xffffffed + 0x7fffffc3 + 2;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 0x6bca1ac)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 0x6bca1ac)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
/*
|
||||
* Note that up to here const_3 is not used
|
||||
@@ -375,14 +387,14 @@ static void test_RtlUniform(void)
|
||||
expected = (seed * 0xffffffed + 0x7fffffc3) & MAXLONG;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 0x6bca1ad)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 0x6bca1ad)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
|
||||
seed = 0x6bca1ae;
|
||||
expected = (seed * 0xffffffed + 0x7fffffc3 + 1) & MAXLONG;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"RtlUniform(&seed (seed == 0x6bca1ae)) returns %lx, expected %lx\n",
|
||||
"RtlUniform(&seed (seed == 0x6bca1ae)) returns %x, expected %x\n",
|
||||
result, expected);
|
||||
/*
|
||||
* There are several ranges where for odd or even seed the result must be
|
||||
@@ -410,7 +422,7 @@ static void test_RtlUniform(void)
|
||||
expected = (expected + (~seed & 1)) & MAXLONG;
|
||||
} else if (seed < 0x1435e50b) {
|
||||
expected = expected + (seed & 1);
|
||||
} else if (seed < 0x1af286ba) {
|
||||
} else if (seed < 0x1af286ba) {
|
||||
expected = (expected + (~seed & 1)) & MAXLONG;
|
||||
} else if (seed < 0x21af2869) {
|
||||
expected = expected + (seed & 1);
|
||||
@@ -490,11 +502,11 @@ static void test_RtlUniform(void)
|
||||
seed_bak = seed;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"test: %llu RtlUniform(&seed (seed == %lx)) returns %lx, expected %lx\n",
|
||||
num, seed_bak, result, expected);
|
||||
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
|
||||
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
|
||||
ok(seed == expected,
|
||||
"test: %llu RtlUniform(&seed (seed == %lx)) sets seed to %lx, expected %lx\n",
|
||||
num, seed_bak, seed, expected);
|
||||
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
|
||||
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
|
||||
} /* for */
|
||||
/*
|
||||
* Further investigation shows: In the different regions the highest bit
|
||||
@@ -537,11 +549,11 @@ static void test_RtlUniform(void)
|
||||
seed_bak = seed;
|
||||
result = pRtlUniform(&seed);
|
||||
ok(result == expected,
|
||||
"test: %llu RtlUniform(&seed (seed == %lx)) returns %lx, expected %lx\n",
|
||||
num, seed_bak, result, expected);
|
||||
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
|
||||
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
|
||||
ok(seed == expected,
|
||||
"test: %llu RtlUniform(&seed (seed == %lx)) sets seed to %lx, expected %lx\n",
|
||||
num, seed_bak, seed, expected);
|
||||
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
|
||||
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
|
||||
} /* for */
|
||||
/*
|
||||
* More tests show that RtlUniform does not return 0x7ffffffd for seed values
|
||||
@@ -616,42 +628,53 @@ static void test_RtlRandom(void)
|
||||
result_expected = 0x320a1743;
|
||||
seed_expected =0x44b;
|
||||
result = pRtlRandom(&seed);
|
||||
|
||||
/*
|
||||
* Windows Vista uses different algorithms, so skip the rest of the tests
|
||||
* until that is figured out. Trace output for the failures is about 10.5 MB!
|
||||
*/
|
||||
|
||||
if (seed == 0x3fc) {
|
||||
skip("Most likely running on Windows Vista which uses a different algorithm\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ok(result == result_expected,
|
||||
"pRtlRandom(&seed (seed == 0)) returns %lx, expected %lx\n",
|
||||
"pRtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
|
||||
result, result_expected);
|
||||
ok(seed == seed_expected,
|
||||
"pRtlRandom(&seed (seed == 0)) sets seed to %lx, expected %lx\n",
|
||||
"pRtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
|
||||
seed, seed_expected);
|
||||
/*
|
||||
* Seed is not equal to result as with RtlUniform. To see more we
|
||||
* call RtlRandom aggain with seed set to 0:
|
||||
* call RtlRandom again with seed set to 0:
|
||||
*/
|
||||
seed = 0;
|
||||
result_expected = 0x7fffffc3;
|
||||
seed_expected =0x44b;
|
||||
result = pRtlRandom(&seed);
|
||||
ok(result == result_expected,
|
||||
"RtlRandom(&seed (seed == 0)) returns %lx, expected %lx\n",
|
||||
"RtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
|
||||
result, result_expected);
|
||||
ok(seed == seed_expected,
|
||||
"RtlRandom(&seed (seed == 0)) sets seed to %lx, expected %lx\n",
|
||||
"RtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
|
||||
seed, seed_expected);
|
||||
/*
|
||||
* Seed is set to the same value as before but the result is different.
|
||||
* To see more we call RtlRandom aggain with seed set to 0:
|
||||
* To see more we call RtlRandom again with seed set to 0:
|
||||
*/
|
||||
seed = 0;
|
||||
result_expected = 0x7fffffc3;
|
||||
seed_expected =0x44b;
|
||||
result = pRtlRandom(&seed);
|
||||
ok(result == result_expected,
|
||||
"RtlRandom(&seed (seed == 0)) returns %lx, expected %lx\n",
|
||||
"RtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
|
||||
result, result_expected);
|
||||
ok(seed == seed_expected,
|
||||
"RtlRandom(&seed (seed == 0)) sets seed to %lx, expected %lx\n",
|
||||
"RtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
|
||||
seed, seed_expected);
|
||||
/*
|
||||
* Seed is aggain set to the same value as before. This time we also
|
||||
* Seed is again set to the same value as before. This time we also
|
||||
* have the same result as before. Interestingly the value of the
|
||||
* result is 0x7fffffc3 which is the same value used in RtlUniform
|
||||
* as const_2. If we do
|
||||
@@ -678,7 +701,7 @@ static void test_RtlRandom(void)
|
||||
* RtlRandom(&seed);
|
||||
*
|
||||
* assigns to seed. Putting these two findings together leads to
|
||||
* the concluson that RtlRandom saves the value in some variable,
|
||||
* the conclusion that RtlRandom saves the value in some variable,
|
||||
* like in the following algorithm:
|
||||
*
|
||||
* result = saved_value;
|
||||
@@ -693,10 +716,10 @@ static void test_RtlRandom(void)
|
||||
seed_expected =0x5a1;
|
||||
result = pRtlRandom(&seed);
|
||||
ok(result == result_expected,
|
||||
"RtlRandom(&seed (seed == 1)) returns %lx, expected %lx\n",
|
||||
"RtlRandom(&seed (seed == 1)) returns %x, expected %x\n",
|
||||
result, result_expected);
|
||||
ok(seed == seed_expected,
|
||||
"RtlRandom(&seed (seed == 1)) sets seed to %lx, expected %lx\n",
|
||||
"RtlRandom(&seed (seed == 1)) sets seed to %x, expected %x\n",
|
||||
seed, seed_expected);
|
||||
/*
|
||||
* If there is just one saved_value the result now would be
|
||||
@@ -725,7 +748,7 @@ static void test_RtlRandom(void)
|
||||
*
|
||||
* What remains to be determined is: The size of the saved_value array,
|
||||
* the initial values of the saved_value array and the function
|
||||
* position(seed). These tests are not shown here.
|
||||
* position(seed). These tests are not shown here.
|
||||
* The result of these tests is: The size of the saved_value array
|
||||
* is 128, the initial values can be seen in the my_RtlRandom
|
||||
* function and the position(seed) function is (seed & 0x7f).
|
||||
@@ -754,11 +777,11 @@ static void test_RtlRandom(void)
|
||||
} /* if */
|
||||
result = pRtlRandom(&seed);
|
||||
ok(result == result_expected,
|
||||
"test: %llu RtlUniform(&seed (seed == %lx)) returns %lx, expected %lx\n",
|
||||
num, seed_bak, result, result_expected);
|
||||
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
|
||||
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, result_expected);
|
||||
ok(seed == seed_expected,
|
||||
"test: %llu RtlUniform(&seed (seed == %lx)) sets seed to %lx, expected %lx\n",
|
||||
num, seed_bak, seed, seed_expected);
|
||||
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
|
||||
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, seed_expected);
|
||||
} /* for */
|
||||
}
|
||||
|
||||
@@ -786,14 +809,14 @@ static const all_accesses_t all_accesses[] = {
|
||||
|
||||
static void test_RtlAreAllAccessesGranted(void)
|
||||
{
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
BOOLEAN result;
|
||||
|
||||
for (test_num = 0; test_num < NB_ALL_ACCESSES; test_num++) {
|
||||
result = pRtlAreAllAccessesGranted(all_accesses[test_num].GrantedAccess,
|
||||
all_accesses[test_num].DesiredAccess);
|
||||
ok(all_accesses[test_num].result == result,
|
||||
"(test %d): RtlAreAllAccessesGranted(%08lx, %08lx) returns %d, expected %d\n",
|
||||
"(test %d): RtlAreAllAccessesGranted(%08x, %08x) returns %d, expected %d\n",
|
||||
test_num, all_accesses[test_num].GrantedAccess,
|
||||
all_accesses[test_num].DesiredAccess,
|
||||
result, all_accesses[test_num].result);
|
||||
@@ -823,14 +846,14 @@ static const any_accesses_t any_accesses[] = {
|
||||
|
||||
static void test_RtlAreAnyAccessesGranted(void)
|
||||
{
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
BOOLEAN result;
|
||||
|
||||
for (test_num = 0; test_num < NB_ANY_ACCESSES; test_num++) {
|
||||
result = pRtlAreAnyAccessesGranted(any_accesses[test_num].GrantedAccess,
|
||||
any_accesses[test_num].DesiredAccess);
|
||||
ok(any_accesses[test_num].result == result,
|
||||
"(test %d): RtlAreAnyAccessesGranted(%08lx, %08lx) returns %d, expected %d\n",
|
||||
"(test %d): RtlAreAnyAccessesGranted(%08x, %08x) returns %d, expected %d\n",
|
||||
test_num, any_accesses[test_num].GrantedAccess,
|
||||
any_accesses[test_num].DesiredAccess,
|
||||
result, any_accesses[test_num].result);
|
||||
@@ -844,8 +867,8 @@ static void test_RtlComputeCrc32(void)
|
||||
if (!pRtlComputeCrc32)
|
||||
return;
|
||||
|
||||
crc = pRtlComputeCrc32(crc, (LPBYTE)src, LEN);
|
||||
ok(crc == 0x40861dc2,"Expected 0x40861dc2, got %8lx\n", crc);
|
||||
crc = pRtlComputeCrc32(crc, (const BYTE *)src, LEN);
|
||||
ok(crc == 0x40861dc2,"Expected 0x40861dc2, got %8x\n", crc);
|
||||
}
|
||||
|
||||
|
||||
@@ -879,7 +902,7 @@ static void test_HandleTables(void)
|
||||
result = pRtlFreeHandle(&HandleTable, &MyHandle->RtlHandle);
|
||||
ok(result, "Couldn't free handle %p\n", MyHandle);
|
||||
status = pRtlDestroyHandleTable(&HandleTable);
|
||||
ok(status == STATUS_SUCCESS, "RtlDestroyHandleTable failed with error 0x%08lx\n", status);
|
||||
ok(status == STATUS_SUCCESS, "RtlDestroyHandleTable failed with error 0x%08x\n", status);
|
||||
}
|
||||
|
||||
static void test_RtlAllocateAndInitializeSid(void)
|
||||
@@ -889,16 +912,16 @@ static void test_RtlAllocateAndInitializeSid(void)
|
||||
PSID psid;
|
||||
|
||||
ret = pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
|
||||
ok(!ret, "RtlAllocateAndInitializeSid error %08lx\n", ret);
|
||||
ok(!ret, "RtlAllocateAndInitializeSid error %08x\n", ret);
|
||||
ret = pRtlFreeSid(psid);
|
||||
ok(!ret, "RtlFreeSid error %08lx\n", ret);
|
||||
ok(!ret, "RtlFreeSid error %08x\n", ret);
|
||||
|
||||
/* these tests crash on XP
|
||||
ret = pRtlAllocateAndInitializeSid(NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
|
||||
ret = pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, NULL);*/
|
||||
|
||||
ret = pRtlAllocateAndInitializeSid(&sia, 9, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
|
||||
ok(ret == STATUS_INVALID_SID, "wrong error %08lx\n", ret);
|
||||
ok(ret == STATUS_INVALID_SID, "wrong error %08x\n", ret);
|
||||
}
|
||||
|
||||
START_TEST(rtl)
|
||||
|
||||
@@ -425,13 +425,15 @@ static void test_RtlFindMostSignificantBit(void)
|
||||
ulLong <<= i;
|
||||
|
||||
cPos = pRtlFindMostSignificantBit(ulLong);
|
||||
ok (cPos == i, "didn't find MSB %llx %d %d\n", ulLong, i, cPos);
|
||||
ok (cPos == i, "didn't find MSB 0x%x%08x %d %d\n",
|
||||
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
|
||||
|
||||
/* Set all bits lower than bit i */
|
||||
ulLong = ((ulLong - 1) << 1) | 1;
|
||||
|
||||
cPos = pRtlFindMostSignificantBit(ulLong);
|
||||
ok (cPos == i, "didn't find MSB %llx %d %d\n", ulLong, i, cPos);
|
||||
ok (cPos == i, "didn't find MSB 0x%x%08x %d %d\n",
|
||||
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
|
||||
}
|
||||
cPos = pRtlFindMostSignificantBit(0);
|
||||
ok (cPos == -1, "found bit when not set\n");
|
||||
@@ -451,12 +453,14 @@ static void test_RtlFindLeastSignificantBit(void)
|
||||
ulLong = (ULONGLONG)1 << i;
|
||||
|
||||
cPos = pRtlFindLeastSignificantBit(ulLong);
|
||||
ok (cPos == i, "didn't find LSB %llx %d %d\n", ulLong, i, cPos);
|
||||
ok (cPos == i, "didn't find LSB 0x%x%08x %d %d\n",
|
||||
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
|
||||
|
||||
ulLong = ~((ULONGLONG)0) << i;
|
||||
|
||||
cPos = pRtlFindLeastSignificantBit(ulLong);
|
||||
ok (cPos == i, "didn't find LSB %llx %d %d\n", ulLong, i, cPos);
|
||||
ok (cPos == i, "didn't find LSB 0x%x%08x %d %d\n",
|
||||
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
|
||||
}
|
||||
cPos = pRtlFindLeastSignificantBit(0);
|
||||
ok (cPos == -1, "found bit when not set\n");
|
||||
@@ -528,7 +532,7 @@ static void test_RtlFindSetRuns(void)
|
||||
ULONG ulStart = 0;
|
||||
|
||||
ulCount = pRtlFindLongestRunSet(&bm, &ulStart);
|
||||
ok(ulCount == 33 && ulStart == 1877,"didn't find longest %ld %ld\n",ulCount,ulStart);
|
||||
ok(ulCount == 33 && ulStart == 1877,"didn't find longest %d %d\n",ulCount,ulStart);
|
||||
|
||||
memset(buff, 0, sizeof(buff));
|
||||
ulCount = pRtlFindLongestRunSet(&bm, &ulStart);
|
||||
|
||||
@@ -62,6 +62,7 @@ static NTSTATUS (WINAPI *pRtlUpperString)(STRING *, const STRING *);
|
||||
static NTSTATUS (WINAPI *pRtlValidateUnicodeString)(long, UNICODE_STRING *);
|
||||
static NTSTATUS (WINAPI *pRtlGUIDFromString)(const UNICODE_STRING*,GUID*);
|
||||
static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
|
||||
static BOOLEAN (WINAPI *pRtlIsTextUnicode)(LPVOID, INT, INT *);
|
||||
|
||||
/*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/
|
||||
/*static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);*/
|
||||
@@ -82,7 +83,6 @@ static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
|
||||
/*static NTSTATUS (WINAPI *pRtlUpcaseUnicodeToOemN)(LPSTR, DWORD, LPDWORD, LPCWSTR, DWORD);*/
|
||||
/*static UINT (WINAPI *pRtlOemToUnicodeSize)(const STRING *);*/
|
||||
/*static DWORD (WINAPI *pRtlAnsiStringToUnicodeSize)(const STRING *);*/
|
||||
/*static DWORD (WINAPI *pRtlIsTextUnicode)(LPVOID, DWORD, DWORD *);*/
|
||||
|
||||
|
||||
static WCHAR* AtoW( const char* p )
|
||||
@@ -130,6 +130,7 @@ static void InitFunctionPtrs(void)
|
||||
pRtlValidateUnicodeString = (void *)GetProcAddress(hntdll, "RtlValidateUnicodeString");
|
||||
pRtlGUIDFromString = (void *)GetProcAddress(hntdll, "RtlGUIDFromString");
|
||||
pRtlStringFromGUID = (void *)GetProcAddress(hntdll, "RtlStringFromGUID");
|
||||
pRtlIsTextUnicode = (void *)GetProcAddress(hntdll, "RtlIsTextUnicode");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +200,7 @@ static void test_RtlInitUnicodeStringEx(void)
|
||||
uni.Buffer = (void *) 0xdeadbeef;
|
||||
result = pRtlInitUnicodeStringEx(&uni, teststring);
|
||||
ok(result == STATUS_SUCCESS,
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) returns %lx, expected 0\n",
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) returns %x, expected 0\n",
|
||||
result);
|
||||
ok(uni.Length == 32,
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) sets Length to %u, expected %u\n",
|
||||
@@ -230,7 +231,7 @@ static void test_RtlInitUnicodeStringEx(void)
|
||||
uni.Buffer = (void *) 0xdeadbeef;
|
||||
result = pRtlInitUnicodeStringEx(&uni, teststring2);
|
||||
ok(result == STATUS_NAME_TOO_LONG,
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) returns %lx, expected %lx\n",
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) returns %x, expected %x\n",
|
||||
result, STATUS_NAME_TOO_LONG);
|
||||
ok(uni.Length == 12345,
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) sets Length to %u, expected %u\n",
|
||||
@@ -246,12 +247,12 @@ static void test_RtlInitUnicodeStringEx(void)
|
||||
uni.MaximumLength = 12345;
|
||||
uni.Buffer = (void *) 0xdeadbeef;
|
||||
pRtlInitUnicodeString(&uni, teststring2);
|
||||
ok(uni.Length == 33920,
|
||||
ok(uni.Length == 33920 /* <= Win2000 */ || uni.Length == 65532 /* >= Win XP */,
|
||||
"pRtlInitUnicodeString(&uni, 0) sets Length to %u, expected %u\n",
|
||||
uni.Length, 33920);
|
||||
ok(uni.MaximumLength == 33922,
|
||||
uni.Length, 65532);
|
||||
ok(uni.MaximumLength == 33922 /* <= Win2000 */ || uni.MaximumLength == 65534 /* >= Win XP */,
|
||||
"pRtlInitUnicodeString(&uni, 0) sets MaximumLength to %u, expected %u\n",
|
||||
uni.MaximumLength, 33922);
|
||||
uni.MaximumLength, 65534);
|
||||
ok(uni.Buffer == teststring2,
|
||||
"pRtlInitUnicodeString(&uni, 0) sets Buffer to %p, expected %p\n",
|
||||
uni.Buffer, teststring2);
|
||||
@@ -263,7 +264,7 @@ static void test_RtlInitUnicodeStringEx(void)
|
||||
uni.Buffer = (void *) 0xdeadbeef;
|
||||
result = pRtlInitUnicodeStringEx(&uni, 0);
|
||||
ok(result == STATUS_SUCCESS,
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) returns %lx, expected 0\n",
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) returns %x, expected 0\n",
|
||||
result);
|
||||
ok(uni.Length == 0,
|
||||
"pRtlInitUnicodeStringEx(&uni, 0) sets Length to %u, expected %u\n",
|
||||
@@ -288,6 +289,8 @@ static void test_RtlInitUnicodeStringEx(void)
|
||||
ok(uni.Buffer == NULL,
|
||||
"pRtlInitUnicodeString(&uni, 0) sets Buffer to %p, expected %p\n",
|
||||
uni.Buffer, NULL);
|
||||
|
||||
free(teststring2);
|
||||
}
|
||||
|
||||
|
||||
@@ -397,7 +400,7 @@ static void test_RtlDuplicateUnicodeString(void)
|
||||
CHAR dest_ansi_buf[257];
|
||||
STRING dest_ansi_str;
|
||||
NTSTATUS result;
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
|
||||
for (test_num = 0; test_num < NB_DUPL_USTR; test_num++) {
|
||||
source_str.Length = dupl_ustr[test_num].source_Length;
|
||||
@@ -439,7 +442,7 @@ static void test_RtlDuplicateUnicodeString(void)
|
||||
dest_ansi_buf[dest_ansi_str.Length] = '\0';
|
||||
dest_ansi_str.Buffer = dest_ansi_buf;
|
||||
ok(result == dupl_ustr[test_num].result,
|
||||
"(test %d): RtlDuplicateUnicodeString(%d, source, dest) has result %lx, expected %lx\n",
|
||||
"(test %d): RtlDuplicateUnicodeString(%d, source, dest) has result %x, expected %x\n",
|
||||
test_num, dupl_ustr[test_num].add_nul, result, dupl_ustr[test_num].result);
|
||||
ok(dest_str.Length == dupl_ustr[test_num].res_Length,
|
||||
"(test %d): RtlDuplicateUnicodeString(%d, source, dest) destination has Length %d, expected %d\n",
|
||||
@@ -637,7 +640,7 @@ static void test_RtlDowncaseUnicodeString(void)
|
||||
UNICODE_STRING result_str;
|
||||
UNICODE_STRING lower_str;
|
||||
|
||||
for (i = 0; i <= 1024; i++) {
|
||||
for (i = 0; i < 1024; i++) {
|
||||
ch = (WCHAR) i;
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
lower_ch = ch - 'A' + 'a';
|
||||
@@ -678,7 +681,6 @@ static void test_RtlDowncaseUnicodeString(void)
|
||||
case 0x38c: lower_ch = 0x3cc; break;
|
||||
case 0x38e: lower_ch = 0x3cd; break;
|
||||
case 0x38f: lower_ch = 0x3ce; break;
|
||||
case 0x400: lower_ch = 0x0; break;
|
||||
default: lower_ch = ch; break;
|
||||
} /* switch */
|
||||
}
|
||||
@@ -754,7 +756,7 @@ static void test_RtlUnicodeStringToAnsiString(void)
|
||||
STRING ansi_str;
|
||||
UNICODE_STRING uni_str;
|
||||
NTSTATUS result;
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
|
||||
for (test_num = 0; test_num < NB_USTR2ASTR; test_num++) {
|
||||
ansi_str.Length = ustr2astr[test_num].ansi_Length;
|
||||
@@ -778,7 +780,7 @@ static void test_RtlUnicodeStringToAnsiString(void)
|
||||
}
|
||||
result = pRtlUnicodeStringToAnsiString(&ansi_str, &uni_str, ustr2astr[test_num].doalloc);
|
||||
ok(result == ustr2astr[test_num].result,
|
||||
"(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) has result %lx, expected %lx\n",
|
||||
"(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) has result %x, expected %x\n",
|
||||
test_num, ustr2astr[test_num].doalloc, result, ustr2astr[test_num].result);
|
||||
ok(ansi_str.Length == ustr2astr[test_num].res_Length,
|
||||
"(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) ansi has Length %d, expected %d\n",
|
||||
@@ -825,7 +827,7 @@ static void test_RtlAppendAsciizToString(void)
|
||||
CHAR dest_buf[257];
|
||||
STRING dest_str;
|
||||
NTSTATUS result;
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
|
||||
for (test_num = 0; test_num < NB_APP_ASC2STR; test_num++) {
|
||||
dest_str.Length = app_asc2str[test_num].dest_Length;
|
||||
@@ -839,7 +841,7 @@ static void test_RtlAppendAsciizToString(void)
|
||||
}
|
||||
result = pRtlAppendAsciizToString(&dest_str, app_asc2str[test_num].src);
|
||||
ok(result == app_asc2str[test_num].result,
|
||||
"(test %d): RtlAppendAsciizToString(dest, src) has result %lx, expected %lx\n",
|
||||
"(test %d): RtlAppendAsciizToString(dest, src) has result %x, expected %x\n",
|
||||
test_num, result, app_asc2str[test_num].result);
|
||||
ok(dest_str.Length == app_asc2str[test_num].res_Length,
|
||||
"(test %d): RtlAppendAsciizToString(dest, src) dest has Length %d, expected %d\n",
|
||||
@@ -897,7 +899,7 @@ static void test_RtlAppendStringToString(void)
|
||||
STRING dest_str;
|
||||
STRING src_str;
|
||||
NTSTATUS result;
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
|
||||
for (test_num = 0; test_num < NB_APP_STR2STR; test_num++) {
|
||||
dest_str.Length = app_str2str[test_num].dest_Length;
|
||||
@@ -920,7 +922,7 @@ static void test_RtlAppendStringToString(void)
|
||||
}
|
||||
result = pRtlAppendStringToString(&dest_str, &src_str);
|
||||
ok(result == app_str2str[test_num].result,
|
||||
"(test %d): RtlAppendStringToString(dest, src) has result %lx, expected %lx\n",
|
||||
"(test %d): RtlAppendStringToString(dest, src) has result %x, expected %x\n",
|
||||
test_num, result, app_str2str[test_num].result);
|
||||
ok(dest_str.Length == app_str2str[test_num].res_Length,
|
||||
"(test %d): RtlAppendStringToString(dest, src) dest has Length %d, expected %d\n",
|
||||
@@ -978,7 +980,7 @@ static void test_RtlAppendUnicodeToString(void)
|
||||
WCHAR dest_buf[257];
|
||||
UNICODE_STRING dest_str;
|
||||
NTSTATUS result;
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
|
||||
for (test_num = 0; test_num < NB_APP_UNI2STR; test_num++) {
|
||||
dest_str.Length = app_uni2str[test_num].dest_Length;
|
||||
@@ -992,7 +994,7 @@ static void test_RtlAppendUnicodeToString(void)
|
||||
}
|
||||
result = pRtlAppendUnicodeToString(&dest_str, (LPCWSTR) app_uni2str[test_num].src);
|
||||
ok(result == app_uni2str[test_num].result,
|
||||
"(test %d): RtlAppendUnicodeToString(dest, src) has result %lx, expected %lx\n",
|
||||
"(test %d): RtlAppendUnicodeToString(dest, src) has result %x, expected %x\n",
|
||||
test_num, result, app_uni2str[test_num].result);
|
||||
ok(dest_str.Length == app_uni2str[test_num].res_Length,
|
||||
"(test %d): RtlAppendUnicodeToString(dest, src) dest has Length %d, expected %d\n",
|
||||
@@ -1033,7 +1035,7 @@ static const app_ustr2str_t app_ustr2str[] = {
|
||||
{ 4, 12, 14, "Fake0123abcdef", 4, 6, 8, "UstrZYXW", 8, 12, 14, "FakeUstr\0\0cdef", STATUS_SUCCESS},
|
||||
{ 4, 11, 14, "Fake0123abcdef", 4, 6, 8, "UstrZYXW", 8, 11, 14, "FakeUstr\0\0cdef", STATUS_SUCCESS},
|
||||
{ 4, 10, 14, "Fake0123abcdef", 4, 6, 8, "UstrZYXW", 8, 10, 14, "FakeUstr\0\0cdef", STATUS_SUCCESS},
|
||||
/* In the following test the native function writes beyond MaximumLength
|
||||
/* In the following test the native function writes beyond MaximumLength
|
||||
* { 4, 9, 14, "Fake0123abcdef", 4, 6, 8, "UstrZYXW", 8, 9, 14, "FakeUstrabcdef", STATUS_SUCCESS},
|
||||
*/
|
||||
{ 4, 8, 14, "Fake0123abcdef", 4, 6, 8, "UstrZYXW", 8, 8, 14, "FakeUstrabcdef", STATUS_SUCCESS},
|
||||
@@ -1054,7 +1056,7 @@ static void test_RtlAppendUnicodeStringToString(void)
|
||||
UNICODE_STRING dest_str;
|
||||
UNICODE_STRING src_str;
|
||||
NTSTATUS result;
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
|
||||
for (test_num = 0; test_num < NB_APP_USTR2STR; test_num++) {
|
||||
dest_str.Length = app_ustr2str[test_num].dest_Length;
|
||||
@@ -1077,7 +1079,7 @@ static void test_RtlAppendUnicodeStringToString(void)
|
||||
}
|
||||
result = pRtlAppendUnicodeStringToString(&dest_str, &src_str);
|
||||
ok(result == app_ustr2str[test_num].result,
|
||||
"(test %d): RtlAppendStringToString(dest, src) has result %lx, expected %lx\n",
|
||||
"(test %d): RtlAppendStringToString(dest, src) has result %x, expected %x\n",
|
||||
test_num, result, app_ustr2str[test_num].result);
|
||||
ok(dest_str.Length == app_ustr2str[test_num].res_Length,
|
||||
"(test %d): RtlAppendStringToString(dest, src) dest has Length %d, expected %d\n",
|
||||
@@ -1165,8 +1167,8 @@ static void test_RtlFindCharInUnicodeString(void)
|
||||
UNICODE_STRING search_chars;
|
||||
USHORT pos;
|
||||
NTSTATUS result;
|
||||
size_t idx;
|
||||
size_t test_num;
|
||||
unsigned int idx;
|
||||
unsigned int test_num;
|
||||
|
||||
for (test_num = 0; test_num < NB_FIND_CH_IN_USTR; test_num++) {
|
||||
if (find_ch_in_ustr[test_num].main_str != NULL) {
|
||||
@@ -1196,7 +1198,7 @@ static void test_RtlFindCharInUnicodeString(void)
|
||||
pos = 12345;
|
||||
result = pRtlFindCharInUnicodeString(find_ch_in_ustr[test_num].flags, &main_str, &search_chars, &pos);
|
||||
ok(result == find_ch_in_ustr[test_num].result,
|
||||
"(test %d): RtlFindCharInUnicodeString(%d, %s, %s, [out]) has result %lx, expected %lx\n",
|
||||
"(test %d): RtlFindCharInUnicodeString(%d, %s, %s, [out]) has result %x, expected %x\n",
|
||||
test_num, find_ch_in_ustr[test_num].flags,
|
||||
find_ch_in_ustr[test_num].main_str, find_ch_in_ustr[test_num].search_chars,
|
||||
result, find_ch_in_ustr[test_num].result);
|
||||
@@ -1280,7 +1282,7 @@ static const str2int_t str2int[] = {
|
||||
{ 0, "0o7", 7, STATUS_SUCCESS}, /* one digit octal */
|
||||
{ 0, "0o8", 0, STATUS_SUCCESS}, /* empty octal */
|
||||
{ 0, "0o", 0, STATUS_SUCCESS}, /* empty octal */
|
||||
{ 0, "0d1011101100", 0, STATUS_SUCCESS}, /* explizit decimal with 0d */
|
||||
{ 0, "0d1011101100", 0, STATUS_SUCCESS}, /* explicit decimal with 0d */
|
||||
{ 0, "x89abcdef", 0, STATUS_SUCCESS}, /* Hex with lower case digits a-f (x-notation) */
|
||||
{ 0, "xFEDCBA00", 0, STATUS_SUCCESS}, /* Hex with upper case digits A-F (x-notation) */
|
||||
{ 0, "-xFEDCBA00", 0, STATUS_SUCCESS}, /* Negative Hexadecimal (x-notation) */
|
||||
@@ -1335,7 +1337,7 @@ static const str2int_t str2int[] = {
|
||||
|
||||
static void test_RtlUnicodeStringToInteger(void)
|
||||
{
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
int value;
|
||||
NTSTATUS result;
|
||||
WCHAR *wstr;
|
||||
@@ -1347,7 +1349,7 @@ static void test_RtlUnicodeStringToInteger(void)
|
||||
pRtlInitUnicodeString(&uni, wstr);
|
||||
result = pRtlUnicodeStringToInteger(&uni, str2int[test_num].base, &value);
|
||||
ok(result == str2int[test_num].result,
|
||||
"(test %d): RtlUnicodeStringToInteger(\"%s\", %d, [out]) has result %lx, expected: %lx\n",
|
||||
"(test %d): RtlUnicodeStringToInteger(\"%s\", %d, [out]) has result %x, expected: %x\n",
|
||||
test_num, str2int[test_num].str, str2int[test_num].base, result, str2int[test_num].result);
|
||||
ok(value == str2int[test_num].value,
|
||||
"(test %d): RtlUnicodeStringToInteger(\"%s\", %d, [out]) assigns value %d, expected: %d\n",
|
||||
@@ -1359,17 +1361,17 @@ static void test_RtlUnicodeStringToInteger(void)
|
||||
pRtlInitUnicodeString(&uni, wstr);
|
||||
result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, NULL);
|
||||
ok(result == STATUS_ACCESS_VIOLATION,
|
||||
"call failed: RtlUnicodeStringToInteger(\"%s\", %d, NULL) has result %lx\n",
|
||||
"call failed: RtlUnicodeStringToInteger(\"%s\", %d, NULL) has result %x\n",
|
||||
str2int[1].str, str2int[1].base, result);
|
||||
result = pRtlUnicodeStringToInteger(&uni, 20, NULL);
|
||||
ok(result == STATUS_INVALID_PARAMETER,
|
||||
"call failed: RtlUnicodeStringToInteger(\"%s\", 20, NULL) has result %lx\n",
|
||||
"call failed: RtlUnicodeStringToInteger(\"%s\", 20, NULL) has result %x\n",
|
||||
str2int[1].str, result);
|
||||
|
||||
uni.Length = 10; /* Make Length shorter (5 WCHARS instead of 7) */
|
||||
result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, &value);
|
||||
ok(result == STATUS_SUCCESS,
|
||||
"call failed: RtlUnicodeStringToInteger(\"12345\", %d, [out]) has result %lx\n",
|
||||
"call failed: RtlUnicodeStringToInteger(\"12345\", %d, [out]) has result %x\n",
|
||||
str2int[1].base, result);
|
||||
ok(value == 12345,
|
||||
"didn't return expected value (test a): expected: %d, got: %d\n",
|
||||
@@ -1378,7 +1380,7 @@ static void test_RtlUnicodeStringToInteger(void)
|
||||
uni.Length = 5; /* Use odd Length (2.5 WCHARS) */
|
||||
result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, &value);
|
||||
ok(result == STATUS_SUCCESS,
|
||||
"call failed: RtlUnicodeStringToInteger(\"12\", %d, [out]) has result %lx\n",
|
||||
"call failed: RtlUnicodeStringToInteger(\"12\", %d, [out]) has result %x\n",
|
||||
str2int[1].base, result);
|
||||
ok(value == 12,
|
||||
"didn't return expected value (test b): expected: %d, got: %d\n",
|
||||
@@ -1387,7 +1389,7 @@ static void test_RtlUnicodeStringToInteger(void)
|
||||
uni.Length = 2;
|
||||
result = pRtlUnicodeStringToInteger(&uni, str2int[1].base, &value);
|
||||
ok(result == STATUS_SUCCESS,
|
||||
"call failed: RtlUnicodeStringToInteger(\"1\", %d, [out]) has result %lx\n",
|
||||
"call failed: RtlUnicodeStringToInteger(\"1\", %d, [out]) has result %x\n",
|
||||
str2int[1].base, result);
|
||||
ok(value == 1,
|
||||
"didn't return expected value (test c): expected: %d, got: %d\n",
|
||||
@@ -1399,7 +1401,7 @@ static void test_RtlUnicodeStringToInteger(void)
|
||||
|
||||
static void test_RtlCharToInteger(void)
|
||||
{
|
||||
size_t test_num;
|
||||
unsigned int test_num;
|
||||
int value;
|
||||
NTSTATUS result;
|
||||
|
||||
@@ -1409,7 +1411,7 @@ static void test_RtlCharToInteger(void)
|
||||
value = 0xdeadbeef;
|
||||
result = pRtlCharToInteger(str2int[test_num].str, str2int[test_num].base, &value);
|
||||
ok(result == str2int[test_num].result,
|
||||
"(test %d): call failed: RtlCharToInteger(\"%s\", %d, [out]) has result %lx, expected: %lx\n",
|
||||
"(test %d): call failed: RtlCharToInteger(\"%s\", %d, [out]) has result %x, expected: %x\n",
|
||||
test_num, str2int[test_num].str, str2int[test_num].base, result, str2int[test_num].result);
|
||||
ok(value == str2int[test_num].value,
|
||||
"(test %d): call failed: RtlCharToInteger(\"%s\", %d, [out]) assigns value %d, expected: %d\n",
|
||||
@@ -1419,12 +1421,12 @@ static void test_RtlCharToInteger(void)
|
||||
|
||||
result = pRtlCharToInteger(str2int[1].str, str2int[1].base, NULL);
|
||||
ok(result == STATUS_ACCESS_VIOLATION,
|
||||
"call failed: RtlCharToInteger(\"%s\", %d, NULL) has result %lx\n",
|
||||
"call failed: RtlCharToInteger(\"%s\", %d, NULL) has result %x\n",
|
||||
str2int[1].str, str2int[1].base, result);
|
||||
|
||||
result = pRtlCharToInteger(str2int[1].str, 20, NULL);
|
||||
ok(result == STATUS_INVALID_PARAMETER,
|
||||
"call failed: RtlCharToInteger(\"%s\", 20, NULL) has result %lx\n",
|
||||
"call failed: RtlCharToInteger(\"%s\", 20, NULL) has result %x\n",
|
||||
str2int[1].str, result);
|
||||
}
|
||||
|
||||
@@ -1592,22 +1594,22 @@ static void one_RtlIntegerToUnicodeString_test(int test_num, const int2str_t *in
|
||||
}
|
||||
} else {
|
||||
ok(result == int2str->result,
|
||||
"(test %d): RtlIntegerToUnicodeString(%lu, %d, [out]) has result %lx, expected: %lx\n",
|
||||
"(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) has result %x, expected: %x\n",
|
||||
test_num, int2str->value, int2str->base, result, int2str->result);
|
||||
if (result == STATUS_SUCCESS) {
|
||||
ok(unicode_string.Buffer[unicode_string.Length/sizeof(WCHAR)] == '\0',
|
||||
"(test %d): RtlIntegerToUnicodeString(%lu, %d, [out]) string \"%s\" is not NULL terminated\n",
|
||||
"(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) string \"%s\" is not NULL terminated\n",
|
||||
test_num, int2str->value, int2str->base, ansi_str.Buffer);
|
||||
}
|
||||
}
|
||||
ok(memcmp(unicode_string.Buffer, expected_unicode_string.Buffer, STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
|
||||
"(test %d): RtlIntegerToUnicodeString(%lu, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
"(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, int2str->value, int2str->base, ansi_str.Buffer, expected_ansi_str.Buffer);
|
||||
ok(unicode_string.Length == expected_unicode_string.Length,
|
||||
"(test %d): RtlIntegerToUnicodeString(%lu, %d, [out]) string has Length %d, expected: %d\n",
|
||||
"(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) string has Length %d, expected: %d\n",
|
||||
test_num, int2str->value, int2str->base, unicode_string.Length, expected_unicode_string.Length);
|
||||
ok(unicode_string.MaximumLength == expected_unicode_string.MaximumLength,
|
||||
"(test %d): RtlIntegerToUnicodeString(%lu, %d, [out]) string has MaximumLength %d, expected: %d\n",
|
||||
"(test %d): RtlIntegerToUnicodeString(%u, %d, [out]) string has MaximumLength %d, expected: %d\n",
|
||||
test_num, int2str->value, int2str->base, unicode_string.MaximumLength, expected_unicode_string.MaximumLength);
|
||||
pRtlFreeAnsiString(&expected_ansi_str);
|
||||
pRtlFreeAnsiString(&ansi_str);
|
||||
@@ -1632,10 +1634,10 @@ static void one_RtlIntegerToChar_test(int test_num, const int2str_t *int2str)
|
||||
dest_str[STRI_BUFFER_LENGTH] = '\0';
|
||||
result = pRtlIntegerToChar(int2str->value, int2str->base, int2str->MaximumLength, dest_str);
|
||||
ok(result == int2str->result,
|
||||
"(test %d): RtlIntegerToChar(%lu, %d, %d, [out]) has result %lx, expected: %lx\n",
|
||||
"(test %d): RtlIntegerToChar(%u, %d, %d, [out]) has result %x, expected: %x\n",
|
||||
test_num, int2str->value, int2str->base, int2str->MaximumLength, result, int2str->result);
|
||||
ok(memcmp(dest_str, int2str->Buffer, STRI_BUFFER_LENGTH) == 0,
|
||||
"(test %d): RtlIntegerToChar(%lu, %d, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
"(test %d): RtlIntegerToChar(%u, %d, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, int2str->value, int2str->base, int2str->MaximumLength, dest_str, int2str->Buffer);
|
||||
}
|
||||
|
||||
@@ -1650,25 +1652,75 @@ static void test_RtlIntegerToChar(void)
|
||||
|
||||
result = pRtlIntegerToChar(int2str[0].value, 20, int2str[0].MaximumLength, NULL);
|
||||
ok(result == STATUS_INVALID_PARAMETER,
|
||||
"(test a): RtlIntegerToChar(%lu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
"(test a): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
int2str[0].value, 20, int2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
|
||||
|
||||
result = pRtlIntegerToChar(int2str[0].value, 20, 0, NULL);
|
||||
ok(result == STATUS_INVALID_PARAMETER,
|
||||
"(test b): RtlIntegerToChar(%lu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
"(test b): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
int2str[0].value, 20, 0, result, STATUS_INVALID_PARAMETER);
|
||||
|
||||
result = pRtlIntegerToChar(int2str[0].value, int2str[0].base, 0, NULL);
|
||||
ok(result == STATUS_BUFFER_OVERFLOW,
|
||||
"(test c): RtlIntegerToChar(%lu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
"(test c): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
int2str[0].value, int2str[0].base, 0, result, STATUS_BUFFER_OVERFLOW);
|
||||
|
||||
result = pRtlIntegerToChar(int2str[0].value, int2str[0].base, int2str[0].MaximumLength, NULL);
|
||||
ok(result == STATUS_ACCESS_VIOLATION,
|
||||
"(test d): RtlIntegerToChar(%lu, %d, %d, NULL) has result %lx, expected: %lx\n",
|
||||
"(test d): RtlIntegerToChar(%u, %d, %d, NULL) has result %x, expected: %x\n",
|
||||
int2str[0].value, int2str[0].base, int2str[0].MaximumLength, result, STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
|
||||
static void test_RtlIsTextUnicode(void)
|
||||
{
|
||||
char ascii[] = "A simple string";
|
||||
WCHAR unicode[] = {'A',' ','U','n','i','c','o','d','e',' ','s','t','r','i','n','g',0};
|
||||
WCHAR *be_unicode;
|
||||
int flags;
|
||||
int i;
|
||||
|
||||
ok(!pRtlIsTextUnicode(ascii, sizeof(ascii), NULL), "ASCII text detected as Unicode\n");
|
||||
|
||||
ok(pRtlIsTextUnicode(unicode, sizeof(unicode), NULL), "Text should be Unicode\n");
|
||||
ok(!pRtlIsTextUnicode(unicode, sizeof(unicode) - 1, NULL), "Text should be Unicode\n");
|
||||
|
||||
flags = IS_TEXT_UNICODE_UNICODE_MASK;
|
||||
ok(pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Text should not pass a Unicode\n");
|
||||
todo_wine
|
||||
ok(flags == (IS_TEXT_UNICODE_STATISTICS | IS_TEXT_UNICODE_CONTROLS),
|
||||
"Expected flags 0x6, obtained %x\n", flags);
|
||||
|
||||
flags = IS_TEXT_UNICODE_REVERSE_MASK;
|
||||
ok(!pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Text should not pass reverse Unicode tests\n");
|
||||
ok(flags == 0, "Expected flags 0, obtained %x\n", flags);
|
||||
|
||||
flags = IS_TEXT_UNICODE_ODD_LENGTH;
|
||||
ok(!pRtlIsTextUnicode(unicode, sizeof(unicode) - 1, &flags), "Odd length test should have passed\n");
|
||||
ok(flags == IS_TEXT_UNICODE_ODD_LENGTH, "Expected flags 0x200, obtained %x\n", flags);
|
||||
|
||||
be_unicode = HeapAlloc(GetProcessHeap(), 0, sizeof(unicode) + sizeof(WCHAR));
|
||||
be_unicode[0] = 0xfffe;
|
||||
for (i = 0; i < sizeof(unicode)/sizeof(unicode[0]); i++)
|
||||
{
|
||||
be_unicode[i + 1] = (unicode[i] >> 8) | ((unicode[i] & 0xff) << 8);
|
||||
}
|
||||
ok(!pRtlIsTextUnicode(be_unicode, sizeof(unicode) + 2, NULL), "Reverse endian should not be Unicode\n");
|
||||
todo_wine ok(!pRtlIsTextUnicode(&be_unicode[1], sizeof(unicode), NULL), "Reverse endian should not be Unicode\n");
|
||||
|
||||
flags = IS_TEXT_UNICODE_REVERSE_MASK;
|
||||
ok(!pRtlIsTextUnicode(&be_unicode[1], sizeof(unicode), &flags), "Reverse endian should be Unicode\n");
|
||||
todo_wine
|
||||
ok(flags == (IS_TEXT_UNICODE_REVERSE_ASCII16 | IS_TEXT_UNICODE_REVERSE_STATISTICS | IS_TEXT_UNICODE_REVERSE_CONTROLS),
|
||||
"Expected flags 0x70, obtained %x\n", flags);
|
||||
|
||||
flags = IS_TEXT_UNICODE_REVERSE_MASK;
|
||||
ok(!pRtlIsTextUnicode(be_unicode, sizeof(unicode) + 2, &flags), "Reverse endian should be Unicode\n");
|
||||
todo_wine
|
||||
ok(flags == (IS_TEXT_UNICODE_REVERSE_CONTROLS | IS_TEXT_UNICODE_REVERSE_SIGNATURE),
|
||||
"Expected flags 0xc0, obtained %x\n", flags);
|
||||
HeapFree(GetProcessHeap(), 0, be_unicode);
|
||||
}
|
||||
|
||||
static const WCHAR szGuid[] = { '{','0','1','0','2','0','3','0','4','-',
|
||||
'0','5','0','6','-' ,'0','7','0','8','-','0','9','0','A','-',
|
||||
'0','B','0','C','0','D','0','E','0','F','0','A','}','\0' };
|
||||
@@ -1684,14 +1736,14 @@ static void test_RtlGUIDFromString(void)
|
||||
UNICODE_STRING str;
|
||||
NTSTATUS ret;
|
||||
|
||||
str.Length = str.MaximumLength = (sizeof(szGuid) - 1) / sizeof(WCHAR);
|
||||
str.Length = str.MaximumLength = sizeof(szGuid) - sizeof(WCHAR);
|
||||
str.Buffer = (LPWSTR)szGuid;
|
||||
|
||||
ret = pRtlGUIDFromString(&str, &guid);
|
||||
ok(ret == 0, "expected ret=0, got 0x%0lx\n", ret);
|
||||
ok(ret == 0, "expected ret=0, got 0x%0x\n", ret);
|
||||
ok(memcmp(&guid, &IID_Endianess, sizeof(guid)) == 0, "Endianess broken\n");
|
||||
|
||||
str.Length = str.MaximumLength = (sizeof(szGuid2) - 1) / sizeof(WCHAR);
|
||||
str.Length = str.MaximumLength = sizeof(szGuid2) - sizeof(WCHAR);
|
||||
str.Buffer = (LPWSTR)szGuid2;
|
||||
|
||||
ret = pRtlGUIDFromString(&str, &guid);
|
||||
@@ -1707,8 +1759,8 @@ static void test_RtlStringFromGUID(void)
|
||||
str.Buffer = NULL;
|
||||
|
||||
ret = pRtlStringFromGUID(&IID_Endianess, &str);
|
||||
ok(ret == 0, "expected ret=0, got 0x%0lx\n", ret);
|
||||
ok(str.Buffer && !lstrcmpW(str.Buffer, szGuid), "Endianess broken\n");
|
||||
ok(ret == 0, "expected ret=0, got 0x%0x\n", ret);
|
||||
ok(str.Buffer && !lstrcmpiW(str.Buffer, szGuid), "Endianess broken\n");
|
||||
}
|
||||
|
||||
START_TEST(rtlstr)
|
||||
@@ -1741,6 +1793,8 @@ START_TEST(rtlstr)
|
||||
test_RtlGUIDFromString();
|
||||
if (pRtlStringFromGUID)
|
||||
test_RtlStringFromGUID();
|
||||
if (pRtlIsTextUnicode)
|
||||
test_RtlIsTextUnicode();
|
||||
if(0)
|
||||
{
|
||||
test_RtlUpcaseUnicodeChar();
|
||||
|
||||
@@ -391,8 +391,6 @@ static void one_ultow_test(int test_num, const ulong2str_t *ulong2str)
|
||||
static void test_ulongtow(void)
|
||||
{
|
||||
int test_num;
|
||||
int pos;
|
||||
WCHAR expected_wstr[LARGE_STRI_BUFFER_LENGTH + 1];
|
||||
LPWSTR result;
|
||||
|
||||
for (test_num = 0; test_num < NB_ULONG2STR; test_num++) {
|
||||
@@ -407,32 +405,29 @@ static void test_ulongtow(void)
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
|
||||
expected_wstr[pos] = ulong2str[0].Buffer[pos];
|
||||
} /* for */
|
||||
expected_wstr[LARGE_STRI_BUFFER_LENGTH] = '\0';
|
||||
result = p_itow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test a): _itow(%ld, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulong2str[0].value, result);
|
||||
if (0) {
|
||||
/* Crashes on XP and W2K3 */
|
||||
result = p_itow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test a): _itow(%d, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulong2str[0].value, result);
|
||||
}
|
||||
|
||||
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
|
||||
expected_wstr[pos] = ulong2str[0].Buffer[pos];
|
||||
} /* for */
|
||||
expected_wstr[LARGE_STRI_BUFFER_LENGTH] = '\0';
|
||||
result = p_ltow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test b): _ltow(%ld, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulong2str[0].value, result);
|
||||
if (0) {
|
||||
/* Crashes on XP and W2K3 */
|
||||
result = p_ltow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test b): _ltow(%d, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulong2str[0].value, result);
|
||||
}
|
||||
|
||||
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
|
||||
expected_wstr[pos] = ulong2str[0].Buffer[pos];
|
||||
} /* for */
|
||||
expected_wstr[LARGE_STRI_BUFFER_LENGTH] = '\0';
|
||||
result = p_ultow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test c): _ultow(%ld, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulong2str[0].value, result);
|
||||
if (0) {
|
||||
/* Crashes on XP and W2K3 */
|
||||
result = p_ultow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test c): _ultow(%d, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulong2str[0].value, result);
|
||||
}
|
||||
}
|
||||
|
||||
#define ULL(a,b) (((ULONGLONG)(a) << 32) | (b))
|
||||
@@ -673,8 +668,9 @@ static void one_i64tow_test(int test_num, const ulonglong2str_t *ulonglong2str)
|
||||
result = p_i64tow(ulonglong2str->value, dest_wstr, ulonglong2str->base);
|
||||
pRtlUnicodeStringToAnsiString(&ansi_str, &unicode_string, 1);
|
||||
ok(result == dest_wstr,
|
||||
"(test %d): _i64tow(%llu, [out], %d) has result %p, expected: %p\n",
|
||||
test_num, ulonglong2str->value, ulonglong2str->base, result, dest_wstr);
|
||||
"(test %d): _i64tow(0x%x%08x, [out], %d) has result %p, expected: %p\n",
|
||||
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
|
||||
ulonglong2str->base, result, dest_wstr);
|
||||
if (ulonglong2str->mask & 0x04) {
|
||||
if (memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) != 0) {
|
||||
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
|
||||
@@ -683,14 +679,16 @@ static void one_i64tow_test(int test_num, const ulonglong2str_t *ulonglong2str)
|
||||
expected_wstr[LARGE_STRI_BUFFER_LENGTH] = '\0';
|
||||
if (memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) != 0) {
|
||||
ok(memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
|
||||
"(test %d): _i64tow(%llu, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, ulonglong2str->value, ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
|
||||
"(test %d): _i64tow(0x%x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
|
||||
ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} else {
|
||||
ok(memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
|
||||
"(test %d): _i64tow(%llu, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, ulonglong2str->value, ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
|
||||
"(test %d): _i64tow(0x%x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
|
||||
ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
|
||||
} /* if */
|
||||
pRtlFreeAnsiString(&ansi_str);
|
||||
}
|
||||
@@ -721,11 +719,13 @@ static void one_ui64tow_test(int test_num, const ulonglong2str_t *ulonglong2str)
|
||||
result = p_ui64tow(ulonglong2str->value, dest_wstr, ulonglong2str->base);
|
||||
pRtlUnicodeStringToAnsiString(&ansi_str, &unicode_string, 1);
|
||||
ok(result == dest_wstr,
|
||||
"(test %d): _ui64tow(%llu, [out], %d) has result %p, expected: %p\n",
|
||||
test_num, ulonglong2str->value, ulonglong2str->base, result, dest_wstr);
|
||||
"(test %d): _ui64tow(0x%x%08x, [out], %d) has result %p, expected: %p\n",
|
||||
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
|
||||
ulonglong2str->base, result, dest_wstr);
|
||||
ok(memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
|
||||
"(test %d): _ui64tow(%llu, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, ulonglong2str->value, ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
|
||||
"(test %d): _ui64tow(0x%x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
|
||||
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
|
||||
ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
|
||||
pRtlFreeAnsiString(&ansi_str);
|
||||
}
|
||||
|
||||
@@ -733,8 +733,6 @@ static void one_ui64tow_test(int test_num, const ulonglong2str_t *ulonglong2str)
|
||||
static void test_ulonglongtow(void)
|
||||
{
|
||||
int test_num;
|
||||
int pos;
|
||||
WCHAR expected_wstr[LARGE_STRI_BUFFER_LENGTH + 1];
|
||||
LPWSTR result;
|
||||
|
||||
for (test_num = 0; test_num < NB_ULONGLONG2STR; test_num++) {
|
||||
@@ -748,24 +746,22 @@ static void test_ulonglongtow(void)
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
|
||||
expected_wstr[pos] = ulong2str[0].Buffer[pos];
|
||||
} /* for */
|
||||
expected_wstr[LARGE_STRI_BUFFER_LENGTH] = '\0';
|
||||
result = p_i64tow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test d): _i64tow(%llu, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulonglong2str[0].value, result);
|
||||
if (0) {
|
||||
/* Crashes on XP and W2K3 */
|
||||
result = p_i64tow(ulonglong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test d): _i64tow(0x%x%08x, NULL, 10) has result %p, expected: NULL\n",
|
||||
(DWORD)(ulonglong2str[0].value >> 32), (DWORD)ulonglong2str[0].value, result);
|
||||
}
|
||||
|
||||
if (p_ui64tow) {
|
||||
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
|
||||
expected_wstr[pos] = ulong2str[0].Buffer[pos];
|
||||
} /* for */
|
||||
expected_wstr[LARGE_STRI_BUFFER_LENGTH] = '\0';
|
||||
result = p_ui64tow(ulong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test e): _ui64tow(%llu, NULL, 10) has result %p, expected: NULL\n",
|
||||
ulonglong2str[0].value, result);
|
||||
if (0) {
|
||||
/* Crashes on XP and W2K3 */
|
||||
result = p_ui64tow(ulonglong2str[0].value, NULL, 10);
|
||||
ok(result == NULL,
|
||||
"(test e): _ui64tow(0x%x%08x, NULL, 10) has result %p, expected: NULL\n",
|
||||
(DWORD)(ulonglong2str[0].value >> 32), (DWORD)ulonglong2str[0].value, result);
|
||||
}
|
||||
} /* if */
|
||||
}
|
||||
|
||||
@@ -863,7 +859,7 @@ static const str2long_t str2long[] = {
|
||||
{ "0o7", 0 }, /* one digit octal */
|
||||
{ "0o8", 0 }, /* empty octal */
|
||||
{ "0o", 0 }, /* empty octal */
|
||||
{ "0d1011101100", 0 }, /* explizit decimal with 0d */
|
||||
{ "0d1011101100", 0 }, /* explicit decimal with 0d */
|
||||
{ "x89abcdef", 0 }, /* Hex with lower case digits a-f (x-notation) */
|
||||
{ "xFEDCBA00", 0 }, /* Hex with upper case digits A-F (x-notation) */
|
||||
{ "-xFEDCBA00", 0 }, /* Negative Hexadecimal (x-notation) */
|
||||
@@ -891,7 +887,7 @@ static void test_wtoi(void)
|
||||
pRtlCreateUnicodeStringFromAsciiz(&uni, str2long[test_num].str);
|
||||
result = p_wtoi(uni.Buffer);
|
||||
ok(result == str2long[test_num].value,
|
||||
"(test %d): call failed: _wtoi(\"%s\") has result %d, expected: %ld\n",
|
||||
"(test %d): call failed: _wtoi(\"%s\") has result %d, expected: %d\n",
|
||||
test_num, str2long[test_num].str, result, str2long[test_num].value);
|
||||
pRtlFreeUnicodeString(&uni);
|
||||
} /* for */
|
||||
@@ -908,7 +904,7 @@ static void test_wtol(void)
|
||||
pRtlCreateUnicodeStringFromAsciiz(&uni, str2long[test_num].str);
|
||||
result = p_wtol(uni.Buffer);
|
||||
ok(result == str2long[test_num].value,
|
||||
"(test %d): call failed: _wtol(\"%s\") has result %ld, expected: %ld\n",
|
||||
"(test %d): call failed: _wtol(\"%s\") has result %d, expected: %d\n",
|
||||
test_num, str2long[test_num].str, result, str2long[test_num].value);
|
||||
pRtlFreeUnicodeString(&uni);
|
||||
} /* for */
|
||||
@@ -1020,7 +1016,7 @@ static const str2longlong_t str2longlong[] = {
|
||||
{ "0o7", 0 }, /* one digit octal */
|
||||
{ "0o8", 0 }, /* empty octal */
|
||||
{ "0o", 0 }, /* empty octal */
|
||||
{ "0d1011101100", 0 }, /* explizit decimal with 0d */
|
||||
{ "0d1011101100", 0 }, /* explicit decimal with 0d */
|
||||
{ "x89abcdef", 0 }, /* Hex with lower case digits a-f (x-notation) */
|
||||
{ "xFEDCBA00", 0 }, /* Hex with upper case digits A-F (x-notation) */
|
||||
{ "-xFEDCBA00", 0 }, /* Negative Hexadecimal (x-notation) */
|
||||
@@ -1046,8 +1042,9 @@ static void test_atoi64(void)
|
||||
for (test_num = 0; test_num < NB_STR2LONGLONG; test_num++) {
|
||||
result = p_atoi64(str2longlong[test_num].str);
|
||||
ok(result == str2longlong[test_num].value,
|
||||
"(test %d): call failed: _atoi64(\"%s\") has result %lld, expected: %lld\n",
|
||||
test_num, str2longlong[test_num].str, result, str2longlong[test_num].value);
|
||||
"(test %d): call failed: _atoi64(\"%s\") has result 0x%x%08x, expected: 0x%x%08x\n",
|
||||
test_num, str2longlong[test_num].str, (DWORD)(result >> 32), (DWORD)result,
|
||||
(DWORD)(str2longlong[test_num].value >> 32), (DWORD)str2longlong[test_num].value);
|
||||
} /* for */
|
||||
}
|
||||
|
||||
@@ -1062,14 +1059,15 @@ static void test_wtoi64(void)
|
||||
pRtlCreateUnicodeStringFromAsciiz(&uni, str2longlong[test_num].str);
|
||||
result = p_wtoi64(uni.Buffer);
|
||||
ok(result == str2longlong[test_num].value,
|
||||
"(test %d): call failed: _wtoi64(\"%s\") has result %lld, expected: %lld\n",
|
||||
test_num, str2longlong[test_num].str, result, str2longlong[test_num].value);
|
||||
"(test %d): call failed: _wtoi64(\"%s\") has result 0x%x%08x, expected: 0x%x%08x\n",
|
||||
test_num, str2longlong[test_num].str, (DWORD)(result >> 32), (DWORD)result,
|
||||
(DWORD)(str2longlong[test_num].value >> 32), (DWORD)str2longlong[test_num].value);
|
||||
pRtlFreeUnicodeString(&uni);
|
||||
} /* for */
|
||||
}
|
||||
|
||||
static void test_wcsfuncs(void)
|
||||
{
|
||||
{
|
||||
static const WCHAR testing[] = {'T','e','s','t','i','n','g',0};
|
||||
ok (p_wcschr(testing,0)!=NULL, "wcschr Not finding terminating character\n");
|
||||
ok (p_wcsrchr(testing,0)!=NULL, "wcsrchr Not finding terminating character\n");
|
||||
|
||||
@@ -11,6 +11,7 @@ extern void func_change(void);
|
||||
extern void func_env(void);
|
||||
extern void func_error(void);
|
||||
extern void func_exception(void);
|
||||
extern void func_file(void);
|
||||
extern void func_generated(void);
|
||||
extern void func_info(void);
|
||||
extern void func_large_int(void);
|
||||
@@ -31,7 +32,8 @@ const struct test winetest_testlist[] =
|
||||
{ "env", func_env },
|
||||
{ "error", func_error },
|
||||
{ "exception", func_exception },
|
||||
// { "generated", func_generated },
|
||||
{ "file", func_file },
|
||||
//{ "generated", func_generated },
|
||||
{ "info", func_info },
|
||||
{ "large_int", func_large_int },
|
||||
{ "om", func_om },
|
||||
|
||||
@@ -53,7 +53,7 @@ static void test_pRtlTimeToTimeFields(void)
|
||||
/* test at the last second of the month */
|
||||
pRtlTimeToTimeFields( &litime, &tfresult);
|
||||
ok( tfresult.Year == tftest.Year && tfresult.Month == tftest.Month &&
|
||||
tfresult.Day == tftest.Day && tfresult.Hour == tftest.Hour &&
|
||||
tfresult.Day == tftest.Day && tfresult.Hour == tftest.Hour &&
|
||||
tfresult.Minute == tftest.Minute && tfresult.Second == tftest.Second,
|
||||
"#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
|
||||
tftest.Year, tftest.Month, tftest.Day,
|
||||
@@ -71,7 +71,7 @@ static void test_pRtlTimeToTimeFields(void)
|
||||
pRtlTimeToTimeFields( &litime, &tfresult);
|
||||
ok( tfresult.Year == tftest.Year + (tftest.Month ==12) &&
|
||||
tfresult.Month == tftest.Month % 12 + 1 &&
|
||||
tfresult.Day == 1 && tfresult.Hour == 0 &&
|
||||
tfresult.Day == 1 && tfresult.Hour == 0 &&
|
||||
tfresult.Minute == 0 && tfresult.Second == 0,
|
||||
"#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
|
||||
tftest.Year + (tftest.Month ==12),
|
||||
@@ -89,7 +89,7 @@ static void test_pRtlTimeToTimeFields(void)
|
||||
if( tftest.Month == 12) {
|
||||
tftest.Month = 1;
|
||||
tftest.Year += 1;
|
||||
} else
|
||||
} else
|
||||
tftest.Month += 1;
|
||||
tftest.Day = MonthLengths[IsLeapYear(tftest.Year)][tftest.Month - 1];
|
||||
litime.QuadPart += (LONGLONG) tftest.Day * TICKSPERSEC * SECSPERDAY;
|
||||
|
||||
@@ -58,7 +58,7 @@ static void test_SQLInstallerError(void)
|
||||
sql_ret = SQLInstallerError(0, NULL, NULL, 0, NULL);
|
||||
ok(sql_ret == SQL_ERROR, "SQLInstallerError(0...) failed with %d instead of SQL_ERROR\n", sql_ret);
|
||||
/* However numbers greater than 8 do not return SQL_ERROR.
|
||||
* I am currenly unsure as to whether it should return SQL_NO_DATA or "the same as for error 8";
|
||||
* I am currently unsure as to whether it should return SQL_NO_DATA or "the same as for error 8";
|
||||
* I have never been able to generate 8 errors to test it
|
||||
*/
|
||||
sql_ret = SQLInstallerError(65535, NULL, NULL, 0, NULL);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="odbccp32_winetest" type="win32cui" installbase="bin" installname="odbccp32_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="odbccp32_winetest" type="win32cui" installbase="bin" installname="odbccp32_winetest.exe" allowwarnings="true">
|
||||
<include base="odbccp32_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -57,6 +57,9 @@ typedef struct EnumFormatImpl {
|
||||
UINT cur;
|
||||
} EnumFormatImpl;
|
||||
|
||||
static BOOL expect_DataObjectImpl_QueryGetData = TRUE;
|
||||
static ULONG DataObjectImpl_GetData_calls = 0;
|
||||
|
||||
static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT size, LPENUMFORMATETC *lplpformatetc);
|
||||
|
||||
static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFIID riid, LPVOID *ppvObj)
|
||||
@@ -194,6 +197,8 @@ static HRESULT WINAPI DataObjectImpl_GetData(IDataObject* iface, FORMATETC *pfor
|
||||
{
|
||||
DataObjectImpl *This = (DataObjectImpl*)iface;
|
||||
|
||||
DataObjectImpl_GetData_calls++;
|
||||
|
||||
if(pformatetc->lindex != -1)
|
||||
return DV_E_LINDEX;
|
||||
|
||||
@@ -223,6 +228,9 @@ static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject* iface, FORMATETC
|
||||
UINT i;
|
||||
BOOL foundFormat = FALSE;
|
||||
|
||||
if (!expect_DataObjectImpl_QueryGetData)
|
||||
ok(0, "unexpected call to DataObjectImpl_QueryGetData\n");
|
||||
|
||||
if(pformatetc->lindex != -1)
|
||||
return DV_E_LINDEX;
|
||||
|
||||
@@ -316,6 +324,97 @@ static HRESULT DataObjectImpl_CreateText(LPCSTR text, LPDATAOBJECT *lplpdataobj)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void test_get_clipboard(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDataObject *data_obj;
|
||||
FORMATETC fmtetc;
|
||||
STGMEDIUM stgmedium;
|
||||
|
||||
hr = OleGetClipboard(NULL);
|
||||
ok(hr == E_INVALIDARG, "OleGetClipboard(NULL) should return E_INVALIDARG instead of 0x%08x\n", hr);
|
||||
|
||||
hr = OleGetClipboard(&data_obj);
|
||||
ok(hr == S_OK, "OleGetClipboard failed with error 0x%08x\n", hr);
|
||||
|
||||
/* test IDataObject_QueryGetData */
|
||||
|
||||
/* clipboard's IDataObject_QueryGetData shouldn't defer to our IDataObject_QueryGetData */
|
||||
expect_DataObjectImpl_QueryGetData = FALSE;
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
hr = IDataObject_QueryGetData(data_obj, &fmtetc);
|
||||
ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.dwAspect = 0xdeadbeef;
|
||||
hr = IDataObject_QueryGetData(data_obj, &fmtetc);
|
||||
ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.dwAspect = DVASPECT_THUMBNAIL;
|
||||
hr = IDataObject_QueryGetData(data_obj, &fmtetc);
|
||||
ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.lindex = 256;
|
||||
hr = IDataObject_QueryGetData(data_obj, &fmtetc);
|
||||
ok(hr == DV_E_FORMATETC, "IDataObject_QueryGetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.cfFormat = CF_RIFF;
|
||||
hr = IDataObject_QueryGetData(data_obj, &fmtetc);
|
||||
ok(hr == DV_E_CLIPFORMAT, "IDataObject_QueryGetData should have failed with DV_E_CLIPFORMAT instead of 0x%08x\n", hr);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.tymed = TYMED_FILE;
|
||||
hr = IDataObject_QueryGetData(data_obj, &fmtetc);
|
||||
ok(hr == S_OK, "IDataObject_QueryGetData failed with error 0x%08x\n", hr);
|
||||
|
||||
expect_DataObjectImpl_QueryGetData = TRUE;
|
||||
|
||||
/* test IDataObject_GetData */
|
||||
|
||||
DataObjectImpl_GetData_calls = 0;
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
|
||||
ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
|
||||
ReleaseStgMedium(&stgmedium);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.dwAspect = 0xdeadbeef;
|
||||
hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
|
||||
ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
|
||||
ReleaseStgMedium(&stgmedium);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.dwAspect = DVASPECT_THUMBNAIL;
|
||||
hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
|
||||
ok(hr == S_OK, "IDataObject_GetData failed with error 0x%08x\n", hr);
|
||||
ReleaseStgMedium(&stgmedium);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.lindex = 256;
|
||||
hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
|
||||
todo_wine
|
||||
ok(hr == DV_E_FORMATETC, "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.cfFormat = CF_RIFF;
|
||||
hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
|
||||
ok(hr == DV_E_FORMATETC, "IDataObject_GetData should have failed with DV_E_FORMATETC instead of 0x%08x\n", hr);
|
||||
|
||||
InitFormatEtc(fmtetc, CF_TEXT, TYMED_HGLOBAL);
|
||||
fmtetc.tymed = TYMED_FILE;
|
||||
hr = IDataObject_GetData(data_obj, &fmtetc, &stgmedium);
|
||||
ok(hr == DV_E_TYMED, "IDataObject_GetData should have failed with DV_E_TYMED instead of 0x%08x\n", hr);
|
||||
|
||||
ok(DataObjectImpl_GetData_calls == 6, "DataObjectImpl_GetData should have been called 6 times instead of %d times\n", DataObjectImpl_GetData_calls);
|
||||
|
||||
IDataObject_Release(data_obj);
|
||||
}
|
||||
|
||||
static void test_set_clipboard(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
@@ -350,6 +449,8 @@ static void test_set_clipboard(void)
|
||||
hr = OleIsCurrentClipboard(data2);
|
||||
ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
|
||||
|
||||
test_get_clipboard();
|
||||
|
||||
hr = OleSetClipboard(data2);
|
||||
ok(hr == S_OK, "failed to set clipboard to data2, hr = 0x%08x\n", hr);
|
||||
hr = OleIsCurrentClipboard(data1);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "winbase.h"
|
||||
#include "objbase.h"
|
||||
#include "shlguid.h"
|
||||
#include "shobjidl.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
@@ -1076,6 +1077,99 @@ static void test_tableweak_marshal_releasedata2(void)
|
||||
end_host_object(tid, thread);
|
||||
}
|
||||
|
||||
struct weak_and_normal_marshal_data
|
||||
{
|
||||
IStream *pStreamWeak;
|
||||
IStream *pStreamNormal;
|
||||
HANDLE hReadyEvent;
|
||||
HANDLE hQuitEvent;
|
||||
};
|
||||
|
||||
static DWORD CALLBACK weak_and_normal_marshal_thread_proc(void *p)
|
||||
{
|
||||
HRESULT hr;
|
||||
struct weak_and_normal_marshal_data *data = p;
|
||||
HANDLE hQuitEvent = data->hQuitEvent;
|
||||
MSG msg;
|
||||
|
||||
pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
|
||||
hr = CoMarshalInterface(data->pStreamWeak, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
|
||||
ok_ole_success(hr, "CoMarshalInterface");
|
||||
|
||||
hr = CoMarshalInterface(data->pStreamNormal, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
|
||||
ok_ole_success(hr, "CoMarshalInterface");
|
||||
|
||||
/* force the message queue to be created before signaling parent thread */
|
||||
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
||||
|
||||
SetEvent(data->hReadyEvent);
|
||||
|
||||
while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, INFINITE, QS_ALLINPUT))
|
||||
{
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
CloseHandle(hQuitEvent);
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* tests interaction between table-weak and normal marshalling of an object */
|
||||
static void test_tableweak_and_normal_marshal_and_unmarshal(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
IUnknown *pProxyWeak = NULL;
|
||||
IUnknown *pProxyNormal = NULL;
|
||||
DWORD tid;
|
||||
HANDLE thread;
|
||||
struct weak_and_normal_marshal_data data;
|
||||
|
||||
cLocks = 0;
|
||||
|
||||
data.hReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
data.hQuitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStreamWeak);
|
||||
ok_ole_success(hr, CreateStreamOnHGlobal);
|
||||
hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStreamNormal);
|
||||
ok_ole_success(hr, CreateStreamOnHGlobal);
|
||||
|
||||
thread = CreateThread(NULL, 0, weak_and_normal_marshal_thread_proc, &data, 0, &tid);
|
||||
WaitForSingleObject(data.hReadyEvent, INFINITE);
|
||||
CloseHandle(data.hReadyEvent);
|
||||
|
||||
ok_more_than_one_lock();
|
||||
|
||||
IStream_Seek(data.pStreamWeak, ullZero, STREAM_SEEK_SET, NULL);
|
||||
hr = CoUnmarshalInterface(data.pStreamWeak, &IID_IClassFactory, (void **)&pProxyWeak);
|
||||
ok_ole_success(hr, CoUnmarshalInterface);
|
||||
|
||||
ok_more_than_one_lock();
|
||||
|
||||
IStream_Seek(data.pStreamNormal, ullZero, STREAM_SEEK_SET, NULL);
|
||||
hr = CoUnmarshalInterface(data.pStreamNormal, &IID_IClassFactory, (void **)&pProxyNormal);
|
||||
ok_ole_success(hr, CoUnmarshalInterface);
|
||||
|
||||
ok_more_than_one_lock();
|
||||
|
||||
IUnknown_Release(pProxyNormal);
|
||||
|
||||
ok_more_than_one_lock();
|
||||
|
||||
IUnknown_Release(pProxyWeak);
|
||||
|
||||
ok_no_locks();
|
||||
|
||||
IStream_Release(data.pStreamWeak);
|
||||
IStream_Release(data.pStreamNormal);
|
||||
|
||||
SetEvent(data.hQuitEvent);
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
}
|
||||
|
||||
/* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
|
||||
static void test_tablestrong_marshal_and_unmarshal_twice(void)
|
||||
{
|
||||
@@ -2549,8 +2643,9 @@ static void test_local_server(void)
|
||||
hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
|
||||
&IID_IClassFactory, (LPVOID*)&cf);
|
||||
ok(hr == CO_E_SERVER_STOPPING || /* NT */
|
||||
hr == REGDB_E_CLASSNOTREG || /* win2k */
|
||||
hr == S_OK /* Win9x */,
|
||||
"CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr);
|
||||
"CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
|
||||
|
||||
hr = CoRevokeClassObject(cookie);
|
||||
ok_ole_success(hr, CoRevokeClassObject);
|
||||
@@ -2593,8 +2688,9 @@ static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
|
||||
IClassFactory *cf;
|
||||
|
||||
hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
|
||||
ok(hr == CO_E_NOTINITIALIZED,
|
||||
"IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
|
||||
ok(hr == CO_E_NOTINITIALIZED ||
|
||||
hr == E_UNEXPECTED, /* win2k */
|
||||
"IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
|
||||
hr);
|
||||
|
||||
CoInitialize(NULL);
|
||||
@@ -2922,6 +3018,7 @@ START_TEST(marshal)
|
||||
test_tableweak_marshal_and_unmarshal_twice();
|
||||
test_tableweak_marshal_releasedata1();
|
||||
test_tableweak_marshal_releasedata2();
|
||||
test_tableweak_and_normal_marshal_and_unmarshal();
|
||||
test_tablestrong_marshal_and_unmarshal_twice();
|
||||
test_lock_object_external();
|
||||
test_disconnect_stub();
|
||||
|
||||
@@ -657,6 +657,7 @@ static void test_ROT(void)
|
||||
todo_wine {
|
||||
ok(hr == CO_E_WRONG_SERVER_IDENTITY, "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
|
||||
}
|
||||
if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie);
|
||||
|
||||
hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
|
||||
(IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
|
||||
@@ -667,6 +668,49 @@ static void test_ROT(void)
|
||||
IRunningObjectTable_Release(pROT);
|
||||
}
|
||||
|
||||
static void test_ROT_multiple_entries(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
IMoniker *pMoniker = NULL;
|
||||
IRunningObjectTable *pROT = NULL;
|
||||
DWORD dwCookie1, dwCookie2;
|
||||
IUnknown *pObject = NULL;
|
||||
static const WCHAR moniker_path[] =
|
||||
{'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
|
||||
|
||||
hr = GetRunningObjectTable(0, &pROT);
|
||||
ok_ole_success(hr, GetRunningObjectTable);
|
||||
|
||||
hr = CreateFileMoniker(moniker_path, &pMoniker);
|
||||
ok_ole_success(hr, CreateFileMoniker);
|
||||
|
||||
hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
|
||||
ok_ole_success(hr, IRunningObjectTable_Register);
|
||||
|
||||
hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
|
||||
ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
|
||||
|
||||
ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
|
||||
|
||||
hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
|
||||
ok_ole_success(hr, IRunningObjectTable_GetObject);
|
||||
IUnknown_Release(pObject);
|
||||
|
||||
hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
|
||||
ok_ole_success(hr, IRunningObjectTable_Revoke);
|
||||
|
||||
hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
|
||||
ok_ole_success(hr, IRunningObjectTable_GetObject);
|
||||
IUnknown_Release(pObject);
|
||||
|
||||
hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
|
||||
ok_ole_success(hr, IRunningObjectTable_Revoke);
|
||||
|
||||
IMoniker_Release(pMoniker);
|
||||
|
||||
IRunningObjectTable_Release(pROT);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
@@ -1801,6 +1845,7 @@ START_TEST(moniker)
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
|
||||
test_ROT();
|
||||
test_ROT_multiple_entries();
|
||||
test_MkParseDisplayName();
|
||||
test_class_moniker();
|
||||
test_file_monikers();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="ole32_winetest" type="win32cui" installbase="bin" installname="ole32_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="ole32_winetest" type="win32cui" installbase="bin" installname="ole32_winetest.exe" allowwarnings="true">
|
||||
<include base="ole32_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="psapi_winetest" type="win32cui" installbase="bin" installname="psapi_winetest.exe" allowwarnings="true">
|
||||
<include base="psapi_winetest">.</include>
|
||||
<define name="__USE_W32API" />
|
||||
@@ -7,3 +10,4 @@
|
||||
<file>testlist.c</file>
|
||||
<file>psapi_main.c</file>
|
||||
</module>
|
||||
</group>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
return FALSE; \
|
||||
}
|
||||
|
||||
/* All PSAPI functions return non-zero and call SetLastError()
|
||||
/* All PSAPI functions return non-zero and call SetLastError()
|
||||
* on failure so we can use some macros for convenience */
|
||||
|
||||
#define w32_suc(x) \
|
||||
@@ -42,7 +42,7 @@
|
||||
? (ok(1, "succeeded\n"), 1) \
|
||||
: GetLastError() == 0xdeadbeef \
|
||||
? (ok(0, "failed without error code\n"), 0) \
|
||||
: (ok(0, "failed with %ld\n", GetLastError()), 0))
|
||||
: (ok(0, "failed with %d\n", GetLastError()), 0))
|
||||
|
||||
#define w32_err(x, e) \
|
||||
(SetLastError(0xdeadbeef), \
|
||||
@@ -52,7 +52,7 @@
|
||||
? (ok(1, "failed with %d\n", e), 1) \
|
||||
: GetLastError() == 0xdeadbeef \
|
||||
? (ok(0, "failed without error code\n"), 0) \
|
||||
: (ok(0, "expected error=%d but failed with %ld\n", \
|
||||
: (ok(0, "expected error=%d but failed with %d\n", \
|
||||
e, GetLastError()), 0))
|
||||
|
||||
static BOOL (WINAPI *pEmptyWorkingSet)(HANDLE);
|
||||
@@ -67,7 +67,7 @@ static BOOL (WINAPI *pGetProcessMemoryInfo)(HANDLE, PPROCESS_MEMORY_COUNTERS, D
|
||||
static BOOL (WINAPI *pGetWsChanges)(HANDLE, PPSAPI_WS_WATCH_INFORMATION, DWORD);
|
||||
static BOOL (WINAPI *pInitializeProcessForWsWatch)(HANDLE);
|
||||
static BOOL (WINAPI *pQueryWorkingSet)(HANDLE, PVOID, DWORD);
|
||||
|
||||
|
||||
static BOOL InitFunctionPtrs(HMODULE hpsapi)
|
||||
{
|
||||
PSAPI_GET_PROC(EmptyWorkingSet);
|
||||
@@ -95,9 +95,9 @@ static void test_EnumProcesses(void)
|
||||
DWORD pid, cbUsed = 0xdeadbeef;
|
||||
|
||||
if(w32_suc(pEnumProcesses(NULL, 0, &cbUsed)))
|
||||
ok(cbUsed == 0, "cbUsed=%ld\n", cbUsed);
|
||||
ok(cbUsed == 0, "cbUsed=%d\n", cbUsed);
|
||||
if(w32_suc(pEnumProcesses(&pid, 4, &cbUsed)))
|
||||
ok(cbUsed == 4, "cbUsed=%ld\n", cbUsed);
|
||||
ok(cbUsed == 4, "cbUsed=%d\n", cbUsed);
|
||||
}
|
||||
|
||||
static void test_EnumProcessModules(void)
|
||||
@@ -111,7 +111,7 @@ static void test_EnumProcessModules(void)
|
||||
if(!w32_suc(pEnumProcessModules(hpQV, &hMod, sizeof(HMODULE), &cbNeeded)))
|
||||
return;
|
||||
ok(cbNeeded / sizeof(HMODULE) >= 3 && cbNeeded / sizeof(HMODULE) <= 5 * sizeof(HMODULE),
|
||||
"cbNeeded=%ld\n", cbNeeded);
|
||||
"cbNeeded=%d\n", cbNeeded);
|
||||
ok(hMod == GetModuleHandle(NULL),
|
||||
"hMod=%p GetModuleHandle(NULL)=%p\n", hMod, GetModuleHandle(NULL));
|
||||
}
|
||||
@@ -120,7 +120,7 @@ static void test_GetModuleInformation(void)
|
||||
{
|
||||
HMODULE hMod = GetModuleHandle(NULL);
|
||||
MODULEINFO info;
|
||||
|
||||
|
||||
w32_err(pGetModuleInformation(NULL, hMod, &info, sizeof(info)), ERROR_INVALID_HANDLE);
|
||||
w32_err(pGetModuleInformation(hpQI, hMod, &info, sizeof(info)), ERROR_ACCESS_DENIED);
|
||||
w32_err(pGetModuleInformation(hpQV, hBad, &info, sizeof(info)), ERROR_INVALID_HANDLE);
|
||||
@@ -144,12 +144,12 @@ static void test_GetMappedFileName(void)
|
||||
HMODULE hMod = GetModuleHandle(NULL);
|
||||
char szMapPath[MAX_PATH], szModPath[MAX_PATH], *szMapBaseName;
|
||||
DWORD ret;
|
||||
|
||||
|
||||
w32_err(pGetMappedFileNameA(NULL, hMod, szMapPath, sizeof(szMapPath)), ERROR_INVALID_HANDLE);
|
||||
w32_err(pGetMappedFileNameA(hpSR, hMod, szMapPath, sizeof(szMapPath)), ERROR_ACCESS_DENIED);
|
||||
if(!w32_suc(ret = pGetMappedFileNameA(hpQI, hMod, szMapPath, sizeof(szMapPath))))
|
||||
return;
|
||||
ok(ret == strlen(szMapPath), "szMapPath=\"%s\" ret=%ld\n", szMapPath, ret);
|
||||
ok(ret == strlen(szMapPath), "szMapPath=\"%s\" ret=%d\n", szMapPath, ret);
|
||||
ok(szMapPath[0] == '\\', "szMapPath=\"%s\"\n", szMapPath);
|
||||
szMapBaseName = strrchr(szMapPath, '\\'); /* That's close enough for us */
|
||||
if(!szMapBaseName || !*szMapBaseName)
|
||||
@@ -180,11 +180,11 @@ static void test_GetProcessImageFileName(void)
|
||||
else if(GetLastError() == 0xdeadbeef)
|
||||
ok(0, "failed without error code\n");
|
||||
else
|
||||
ok(0, "failed with %ld\n", GetLastError());
|
||||
ok(0, "failed with %d\n", GetLastError());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
w32_err(pGetProcessImageFileNameA(NULL, szImgPath, sizeof(szImgPath)), ERROR_INVALID_HANDLE);
|
||||
w32_err(pGetProcessImageFileNameA(hpSR, szImgPath, sizeof(szImgPath)), ERROR_ACCESS_DENIED);
|
||||
w32_err(pGetProcessImageFileNameA(hpQI, szImgPath, 0), ERROR_INSUFFICIENT_BUFFER);
|
||||
@@ -192,9 +192,9 @@ static void test_GetProcessImageFileName(void)
|
||||
!w32_suc(pGetMappedFileNameA(hpQV, hMod, szMapPath, sizeof(szMapPath))))
|
||||
return;
|
||||
/* Windows returns 2*strlen-1 */
|
||||
ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%ld\n", szImgPath, ret);
|
||||
ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%d\n", szImgPath, ret);
|
||||
ok(!strcmp(szImgPath, szMapPath),
|
||||
"szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
|
||||
"szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
|
||||
}
|
||||
|
||||
static void test_GetModuleFileNameEx(void)
|
||||
@@ -202,15 +202,15 @@ static void test_GetModuleFileNameEx(void)
|
||||
HMODULE hMod = GetModuleHandle(NULL);
|
||||
char szModExPath[MAX_PATH+1], szModPath[MAX_PATH+1];
|
||||
DWORD ret;
|
||||
|
||||
|
||||
w32_err(pGetModuleFileNameExA(NULL, hMod, szModExPath, sizeof(szModExPath)), ERROR_INVALID_HANDLE);
|
||||
w32_err(pGetModuleFileNameExA(hpQI, hMod, szModExPath, sizeof(szModExPath)), ERROR_ACCESS_DENIED);
|
||||
w32_err(pGetModuleFileNameExA(hpQV, hBad, szModExPath, sizeof(szModExPath)), ERROR_INVALID_HANDLE);
|
||||
if(!w32_suc(ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, sizeof(szModExPath))))
|
||||
return;
|
||||
ok(ret == strlen(szModExPath), "szModExPath=\"%s\" ret=%ld\n", szModExPath, ret);
|
||||
ok(ret == strlen(szModExPath), "szModExPath=\"%s\" ret=%d\n", szModExPath, ret);
|
||||
GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
|
||||
ok(!strncmp(szModExPath, szModPath, MAX_PATH),
|
||||
ok(!strncmp(szModExPath, szModPath, MAX_PATH),
|
||||
"szModExPath=\"%s\" szModPath=\"%s\"\n", szModExPath, szModPath);
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ static void test_GetModuleBaseName(void)
|
||||
w32_err(pGetModuleBaseNameA(hpQV, hBad, szModBaseName, sizeof(szModBaseName)), ERROR_INVALID_HANDLE);
|
||||
if(!w32_suc(ret = pGetModuleBaseNameA(hpQV, NULL, szModBaseName, sizeof(szModBaseName))))
|
||||
return;
|
||||
ok(ret == strlen(szModBaseName), "szModBaseName=\"%s\" ret=%ld\n", szModBaseName, ret);
|
||||
ok(ret == strlen(szModBaseName), "szModBaseName=\"%s\" ret=%d\n", szModBaseName, ret);
|
||||
GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
|
||||
ok(!strcmp(strrchr(szModPath, '\\') + 1, szModBaseName),
|
||||
"szModPath=\"%s\" szModBaseName=\"%s\"\n", szModPath, szModBaseName);
|
||||
@@ -236,24 +236,24 @@ static void test_ws_functions(void)
|
||||
PSAPI_WS_WATCH_INFORMATION wswi[4096];
|
||||
ULONG_PTR pages[4096];
|
||||
char *addr;
|
||||
int i;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
todo_wine w32_err(pEmptyWorkingSet(NULL), ERROR_INVALID_HANDLE);
|
||||
todo_wine w32_err(pEmptyWorkingSet(hpSR), ERROR_ACCESS_DENIED);
|
||||
w32_suc(pEmptyWorkingSet(hpAA));
|
||||
|
||||
|
||||
todo_wine w32_err(pInitializeProcessForWsWatch(NULL), ERROR_INVALID_HANDLE);
|
||||
w32_suc(pInitializeProcessForWsWatch(hpAA));
|
||||
|
||||
|
||||
if(!w32_suc(addr = VirtualAlloc(NULL, 1, MEM_COMMIT, PAGE_READWRITE)))
|
||||
return;
|
||||
|
||||
if(!VirtualLock(addr, 1))
|
||||
{
|
||||
trace("locking failed (error=%ld) - skipping test\n", GetLastError());
|
||||
trace("locking failed (error=%d) - skipping test\n", GetLastError());
|
||||
goto free_page;
|
||||
}
|
||||
|
||||
|
||||
todo_wine if(w32_suc(pQueryWorkingSet(hpQI, pages, 4096 * sizeof(ULONG_PTR))))
|
||||
{
|
||||
for(i = 0; i < pages[0]; i++)
|
||||
@@ -262,7 +262,7 @@ static void test_ws_functions(void)
|
||||
ok(1, "QueryWorkingSet found our page\n");
|
||||
goto test_gwsc;
|
||||
}
|
||||
|
||||
|
||||
ok(0, "QueryWorkingSet didn't find our page\n");
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ test_gwsc:
|
||||
|
||||
ok(0, "GetWsChanges didn't find our page\n");
|
||||
}
|
||||
|
||||
|
||||
free_page:
|
||||
VirtualFree(addr, 0, MEM_RELEASE);
|
||||
}
|
||||
@@ -286,7 +286,7 @@ free_page:
|
||||
START_TEST(psapi_main)
|
||||
{
|
||||
HMODULE hpsapi = LoadLibraryA("psapi.dll");
|
||||
|
||||
|
||||
if(!hpsapi)
|
||||
{
|
||||
trace("Could not load psapi.dll\n");
|
||||
@@ -320,6 +320,6 @@ START_TEST(psapi_main)
|
||||
CloseHandle(hpQV);
|
||||
CloseHandle(hpAA);
|
||||
}
|
||||
|
||||
|
||||
FreeLibrary(hpsapi);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,9 @@ struct find_s find_tests2[] = {
|
||||
/* The backwards case of bug 4479; bounds look right
|
||||
* Fails because backward find is wrong */
|
||||
{19, 20, "WINE", FR_MATCHCASE, 0, 0},
|
||||
{0, 20, "WINE", FR_MATCHCASE, -1, 0}
|
||||
{0, 20, "WINE", FR_MATCHCASE, -1, 0},
|
||||
|
||||
{0, -1, "wineWine wine", 0, -1, 0},
|
||||
};
|
||||
|
||||
static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id) {
|
||||
@@ -261,6 +263,40 @@ static void test_EM_GETLINE(void)
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_LINELENGTH(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
const char * text =
|
||||
"richedit1\r"
|
||||
"richedit1\n"
|
||||
"richedit1\r\n"
|
||||
"richedit1";
|
||||
int offset_test[10][2] = {
|
||||
{0, 9},
|
||||
{5, 9},
|
||||
{10, 9},
|
||||
{15, 9},
|
||||
{20, 9},
|
||||
{25, 9},
|
||||
{30, 9},
|
||||
{35, 9},
|
||||
{40, 0},
|
||||
{45, 0},
|
||||
};
|
||||
int i;
|
||||
LRESULT result;
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
result = SendMessage(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
|
||||
ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
|
||||
offset_test[i][0], result, offset_test[i][1]);
|
||||
}
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static int get_scroll_pos_y(HWND hwnd)
|
||||
{
|
||||
POINT p = {-1, -1};
|
||||
@@ -404,6 +440,57 @@ static void test_EM_SETCHARFORMAT(void)
|
||||
(LPARAM) &cf2);
|
||||
ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
|
||||
|
||||
cf2.cbSize = sizeof(CHARFORMAT2);
|
||||
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT,
|
||||
(LPARAM) &cf2);
|
||||
|
||||
/* Test state of modify flag before and after valid EM_SETCHARFORMAT */
|
||||
cf2.cbSize = sizeof(CHARFORMAT2);
|
||||
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT,
|
||||
(LPARAM) &cf2);
|
||||
cf2.dwMask = CFM_ITALIC | cf2.dwMask;
|
||||
cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
|
||||
|
||||
/* wParam==0 is default char format, does not set modify */
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, 0, (LPARAM) &cf2);
|
||||
ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
|
||||
/* wParam==SCF_SELECTION sets modify if nonempty selection */
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf2);
|
||||
ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf2);
|
||||
ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
SendMessage(hwndRichEdit, EM_SETSEL, 0, 2);
|
||||
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf2);
|
||||
ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == -1, "Text not marked as modified, expected modified! (%d)\n", rc);
|
||||
|
||||
/* wParam==SCF_ALL sets modify regardless of whether text is present */
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2);
|
||||
ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == -1, "Text not marked as modified, expected modified! (%d)\n", rc);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
@@ -438,10 +525,17 @@ static void test_EM_SETTEXTMODE(void)
|
||||
cf2.dwMask = CFM_ITALIC | cf2.dwMask;
|
||||
cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
|
||||
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == 0, "Text marked as modified, expected not modified!\n");
|
||||
|
||||
/*EM_SETCHARFORMAT is not yet fully implemented for all WPARAMs in wine;
|
||||
however, SCF_ALL has been implemented*/
|
||||
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2);
|
||||
ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
|
||||
|
||||
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
|
||||
ok(rc == -1, "Text not marked as modified, expected modified! (%d)\n", rc);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine");
|
||||
|
||||
/*Select the string "wine"*/
|
||||
@@ -680,9 +774,12 @@ static void test_WM_GETTEXT(void)
|
||||
/* Test for behavior in overflow case */
|
||||
memset(buffer, 0, 1024);
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, strlen(text), (LPARAM)buffer);
|
||||
ok(result == 0,
|
||||
"WM_GETTEXT returned %d, expected 0\n", result);
|
||||
ok(result == 0 ||
|
||||
result == lstrlenA(text) - 1, /* XP, win2k3 */
|
||||
"WM_GETTEXT returned %d, expected 0 or %d\n", result, lstrlenA(text) - 1);
|
||||
result = strcmp(buffer,text);
|
||||
if (result)
|
||||
result = strncmp(buffer, text, lstrlenA(text) - 1); /* XP, win2k3 */
|
||||
ok(result == 0,
|
||||
"WM_GETTEXT: settext and gettext differ. strcmp: %d\n", result);
|
||||
|
||||
@@ -704,15 +801,75 @@ static void test_WM_GETTEXT(void)
|
||||
/* Test for behavior of CRLF conversion in case of overflow */
|
||||
memset(buffer, 0, 1024);
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, strlen(text2), (LPARAM)buffer);
|
||||
ok(result == 0,
|
||||
"WM_GETTEXT returned %d, expected 0\n", result);
|
||||
ok(result == 0 ||
|
||||
result == lstrlenA(text2) - 1, /* XP, win2k3 */
|
||||
"WM_GETTEXT returned %d, expected 0 or %d\n", result, lstrlenA(text2) - 1);
|
||||
result = strcmp(buffer,text2);
|
||||
if (result)
|
||||
result = strncmp(buffer, text2, lstrlenA(text2) - 1); /* XP, win2k3 */
|
||||
ok(result == 0,
|
||||
"WM_GETTEXT: settext and gettext differ. strcmp: %d\n", result);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_GETTEXTRANGE(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
const char * text1 = "foo bar\r\nfoo bar";
|
||||
const char * text2 = "foo bar\rfoo bar";
|
||||
const char * expect = "bar\rfoo";
|
||||
char buffer[1024] = {0};
|
||||
LRESULT result;
|
||||
TEXTRANGEA textRange;
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
|
||||
|
||||
textRange.lpstrText = buffer;
|
||||
textRange.chrg.cpMin = 4;
|
||||
textRange.chrg.cpMax = 11;
|
||||
result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
ok(!strcmp(expect, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
|
||||
|
||||
textRange.lpstrText = buffer;
|
||||
textRange.chrg.cpMin = 4;
|
||||
textRange.chrg.cpMax = 11;
|
||||
result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
ok(!strcmp(expect, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_GETSELTEXT(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
const char * text1 = "foo bar\r\nfoo bar";
|
||||
const char * text2 = "foo bar\rfoo bar";
|
||||
const char * expect = "bar\rfoo";
|
||||
char buffer[1024] = {0};
|
||||
LRESULT result;
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
|
||||
|
||||
SendMessage(hwndRichEdit, EM_SETSEL, 4, 11);
|
||||
result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
ok(!strcmp(expect, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
|
||||
|
||||
SendMessage(hwndRichEdit, EM_SETSEL, 4, 11);
|
||||
result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
ok(!strcmp(expect, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
/* FIXME: need to test unimplemented options and robustly test wparam */
|
||||
static void test_EM_SETOPTIONS(void)
|
||||
{
|
||||
@@ -852,7 +1009,7 @@ static void test_EM_SCROLL(void)
|
||||
"a LONG LINE LONG LINE LONG LINE LONG LINE LONG LINE "
|
||||
"LONG LINE LONG LINE LONG LINE LONG LINE LONG LINE "
|
||||
"LONG LINE \nb\nc\nd\ne");
|
||||
for (j = 0; j < 12; j++) /* reset scrol position to top */
|
||||
for (j = 0; j < 12; j++) /* reset scroll position to top */
|
||||
SendMessage(hwndRichEdit, EM_SCROLL, SB_PAGEUP, 0);
|
||||
|
||||
/* get first visible line */
|
||||
@@ -1041,6 +1198,20 @@ static void test_ES_PASSWORD(void)
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,
|
||||
LPBYTE pbBuff,
|
||||
LONG cb,
|
||||
LONG *pcb)
|
||||
{
|
||||
char** str = (char**)dwCookie;
|
||||
*pcb = cb;
|
||||
if (*pcb > 0) {
|
||||
memcpy(*str, pbBuff, *pcb);
|
||||
*str += *pcb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_WM_SETTEXT()
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
@@ -1057,8 +1228,11 @@ static void test_WM_SETTEXT()
|
||||
const char * TestItem6_after = "TestSomeText \r\nTestSomeText";
|
||||
const char * TestItem7 = "TestSomeText\r\n\r\r\n\rTestSomeText";
|
||||
const char * TestItem7_after = "TestSomeText\r\n \r\nTestSomeText";
|
||||
|
||||
char buf[1024] = {0};
|
||||
LRESULT result;
|
||||
EDITSTREAM es;
|
||||
char * p;
|
||||
|
||||
/* This test attempts to show that WM_SETTEXT on a riched20 control causes
|
||||
any solitary \r to be converted to \r\n on return. Properly paired
|
||||
@@ -1086,10 +1260,76 @@ static void test_WM_SETTEXT()
|
||||
TEST_SETTEXT(TestItem6, TestItem6_after)
|
||||
TEST_SETTEXT(TestItem7, TestItem7_after)
|
||||
|
||||
/* The following test demonstrates that WM_SETTEXT supports RTF strings */
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
trace("EM_STREAMOUT produced: \n%s\n", buf);
|
||||
TEST_SETTEXT(buf, TestItem1)
|
||||
|
||||
#undef TEST_SETTEXT
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_STREAMOUT(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
int r;
|
||||
EDITSTREAM es;
|
||||
char buf[1024] = {0};
|
||||
char * p;
|
||||
|
||||
const char * TestItem1 = "TestSomeText";
|
||||
const char * TestItem2 = "TestSomeText\r";
|
||||
const char * TestItem3 = "TestSomeText\r\n";
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||
r = strlen(buf);
|
||||
ok(r == 12, "streamed text length is %d, expecting 12\n", r);
|
||||
ok(strcmp(buf, TestItem1) == 0,
|
||||
"streamed text different, got %s\n", buf);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||
r = strlen(buf);
|
||||
/* Here again, \r gets converted to \r\n, like WM_GETTEXT */
|
||||
ok(r == 14, "streamed text length is %d, expecting 14\n", r);
|
||||
ok(strcmp(buf, TestItem3) == 0,
|
||||
"streamed text different from, got %s\n", buf);
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||
r = strlen(buf);
|
||||
ok(r == 14, "streamed text length is %d, expecting 14\n", r);
|
||||
ok(strcmp(buf, TestItem3) == 0,
|
||||
"streamed text different, got %s\n", buf);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_SETTEXTEX(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
@@ -1126,8 +1366,10 @@ static void test_EM_SETTEXTEX(void)
|
||||
' ','\r', 0};
|
||||
#define MAX_BUF_LEN 1024
|
||||
WCHAR buf[MAX_BUF_LEN];
|
||||
char * p;
|
||||
int result;
|
||||
CHARRANGE cr;
|
||||
EDITSTREAM es;
|
||||
|
||||
setText.codepage = 1200; /* no constant for unicode */
|
||||
getText.codepage = 1200; /* no constant for unicode */
|
||||
@@ -1274,6 +1516,31 @@ static void test_EM_SETTEXTEX(void)
|
||||
"EM_SETTEXTEX to replace selection with more text failed: %i.\n",
|
||||
lstrlenW(buf) );
|
||||
|
||||
/* The following test demonstrates that EM_SETTEXTEX supports RTF strings */
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "TestSomeText"); /* TestItem1 */
|
||||
p = (char *)buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
trace("EM_STREAMOUT produced: \n%s\n", (char *)buf);
|
||||
|
||||
setText.codepage = CP_ACP;/* EM_STREAMOUT saved as ANSI string */
|
||||
getText.codepage = 1200; /* no constant for unicode */
|
||||
getText.cb = MAX_BUF_LEN;
|
||||
getText.flags = GT_DEFAULT;
|
||||
getText.lpDefaultChar = NULL;
|
||||
getText.lpUsedDefChar = NULL;
|
||||
|
||||
setText.flags = 0;
|
||||
SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) buf);
|
||||
SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf);
|
||||
ok(lstrcmpW(buf, TestItem1) == 0,
|
||||
"EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
|
||||
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
@@ -1492,21 +1759,21 @@ static void test_WM_SETFONT(void)
|
||||
|
||||
GetObjectA(testFont1, sizeof(LOGFONTA), &sentLogFont);
|
||||
ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
|
||||
"EM_GETCHARFOMAT: Returned wrong font on test 1. Sent: %s, Returned: %s\n",
|
||||
"EM_GETCHARFORMAT: Returned wrong font on test 1. Sent: %s, Returned: %s\n",
|
||||
sentLogFont.lfFaceName,returnedCF2A.szFaceName);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont2,(LPARAM) MAKELONG((WORD) TRUE, 0));
|
||||
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &returnedCF2A);
|
||||
GetObjectA(testFont2, sizeof(LOGFONTA), &sentLogFont);
|
||||
ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
|
||||
"EM_GETCHARFOMAT: Returned wrong font on test 2. Sent: %s, Returned: %s\n",
|
||||
"EM_GETCHARFORMAT: Returned wrong font on test 2. Sent: %s, Returned: %s\n",
|
||||
sentLogFont.lfFaceName,returnedCF2A.szFaceName);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont3,(LPARAM) MAKELONG((WORD) TRUE, 0));
|
||||
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &returnedCF2A);
|
||||
GetObjectA(testFont3, sizeof(LOGFONTA), &sentLogFont);
|
||||
ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
|
||||
"EM_GETCHARFOMAT: Returned wrong font on test 3. Sent: %s, Returned: %s\n",
|
||||
"EM_GETCHARFORMAT: Returned wrong font on test 3. Sent: %s, Returned: %s\n",
|
||||
sentLogFont.lfFaceName,returnedCF2A.szFaceName);
|
||||
|
||||
/* This last test is special since we send in NULL. We clear the variables
|
||||
@@ -1519,7 +1786,7 @@ static void test_WM_SETFONT(void)
|
||||
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &returnedCF2A);
|
||||
GetObjectA(NULL, sizeof(LOGFONTA), &sentLogFont);
|
||||
ok (!strcmp("System",returnedCF2A.szFaceName),
|
||||
"EM_GETCHARFOMAT: Returned wrong font on test 4. Sent: NULL, Returned: %s. Expected \"System\".\n",returnedCF2A.szFaceName);
|
||||
"EM_GETCHARFORMAT: Returned wrong font on test 4. Sent: NULL, Returned: %s. Expected \"System\".\n",returnedCF2A.szFaceName);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
@@ -1532,7 +1799,7 @@ static DWORD CALLBACK test_EM_GETMODIFY_esCallback(DWORD_PTR dwCookie,
|
||||
{
|
||||
const char** str = (const char**)dwCookie;
|
||||
int size = strlen(*str);
|
||||
if(size > 3) /* let's make it peice-meal for fun */
|
||||
if(size > 3) /* let's make it piecemeal for fun */
|
||||
size = 3;
|
||||
*pcb = cb;
|
||||
if (*pcb > size) {
|
||||
@@ -1793,7 +2060,7 @@ static void test_EM_EXSETSEL(void)
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_REPLACESEL(void)
|
||||
static void test_EM_REPLACESEL(int redraw)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
char buffer[1024] = {0};
|
||||
@@ -1818,6 +2085,9 @@ static void test_EM_REPLACESEL(void)
|
||||
|
||||
hwndRichEdit = new_richedit(NULL);
|
||||
|
||||
trace("Testing EM_REPLACESEL behavior with redraw=%d\n", redraw);
|
||||
SendMessage(hwndRichEdit, WM_SETREDRAW, redraw, 0);
|
||||
|
||||
/* Test behavior with carriage returns and newlines */
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "RichEdit1");
|
||||
@@ -1834,6 +2104,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, "RichEdit1") == 0,
|
||||
"EM_GETTEXTEX results not what was set by EM_REPLACESEL\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 1, "EM_GETLINECOUNT returned %d, expected 1\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "RichEdit1\r");
|
||||
ok(10 == r, "EM_REPLACESEL returned %d, expected 10\n", r);
|
||||
@@ -1849,6 +2123,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, "RichEdit1\r") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r);
|
||||
|
||||
/* Win98's riched20 and WinXP's riched20 disagree on what to return from
|
||||
EM_REPLACESEL. The general rule seems to be that Win98's riched20
|
||||
returns the number of characters *inserted* into the control (after
|
||||
@@ -1861,6 +2139,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(11 == r /* WinXP */ || 10 == r /* Win98 */,
|
||||
"EM_REPLACESEL returned %d, expected 11 or 10\n", r);
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r);
|
||||
|
||||
r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
|
||||
ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
|
||||
ok(cr.cpMin == 10, "EM_EXGETSEL returned cpMin=%d, expected 10\n", cr.cpMin);
|
||||
@@ -1907,6 +2189,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, "\r\r") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n");
|
||||
ok(3 == r /* WinXP */ || 1 == r /* Win98 */,
|
||||
@@ -1926,6 +2212,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, " ") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 1, "EM_GETLINECOUNT returned %d, expected 1\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\r\r\r\n\r\r\r");
|
||||
ok(9 == r /* WinXP */ || 7 == r /* Win98 */,
|
||||
@@ -1945,6 +2235,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, "\r\r\r \r\r\r") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 7, "EM_GETLINECOUNT returned %d, expected 7\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n\r\n");
|
||||
ok(5 == r /* WinXP */ || 2 == r /* Win98 */,
|
||||
@@ -1964,6 +2258,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, " \r") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n\r\r");
|
||||
ok(5 == r /* WinXP */ || 3 == r /* Win98 */,
|
||||
@@ -1983,6 +2281,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, " \r\r") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\rX\r\n\r\r");
|
||||
ok(6 == r /* WinXP */ || 5 == r /* Win98 */,
|
||||
@@ -2002,6 +2304,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, "\rX\r\r\r") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 5, "EM_GETLINECOUNT returned %d, expected 5\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\n\n");
|
||||
ok(2 == r, "EM_REPLACESEL returned %d, expected 2\n", r);
|
||||
@@ -2020,6 +2326,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, "\r\r") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
|
||||
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\n\n\n\n\r\r\r\r\n");
|
||||
ok(9 == r /* WinXP */ || 7 == r /* Win98 */,
|
||||
@@ -2039,6 +2349,10 @@ static void test_EM_REPLACESEL(void)
|
||||
ok(strcmp(buffer, "\r\r\r\r\r\r ") == 0,
|
||||
"EM_GETTEXTEX returned incorrect string\n");
|
||||
|
||||
/* Test number of lines reported after EM_REPLACESEL */
|
||||
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
|
||||
ok(r == 7, "EM_GETLINECOUNT returned %d, expected 7\n", r);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
@@ -2199,6 +2513,139 @@ static DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff,
|
||||
return 1; /* indicates callback failed */
|
||||
}
|
||||
|
||||
static DWORD CALLBACK test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie,
|
||||
LPBYTE pbBuff,
|
||||
LONG cb,
|
||||
LONG *pcb)
|
||||
{
|
||||
const char** str = (const char**)dwCookie;
|
||||
int size = strlen(*str);
|
||||
*pcb = cb;
|
||||
if (*pcb > size) {
|
||||
*pcb = size;
|
||||
}
|
||||
if (*pcb > 0) {
|
||||
memcpy(pbBuff, *str, *pcb);
|
||||
*str += *pcb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void test_EM_STREAMIN(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
LRESULT result;
|
||||
EDITSTREAM es;
|
||||
char buffer[1024] = {0};
|
||||
|
||||
const char * streamText0 = "{\\rtf1 TestSomeText}";
|
||||
const char * streamText0a = "{\\rtf1 TestSomeText\\par}";
|
||||
const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
|
||||
|
||||
const char * streamText1 =
|
||||
"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n" \
|
||||
"\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n" \
|
||||
"}\r\n";
|
||||
|
||||
/* In richedit 2.0 mode, this should NOT be accepted, unlike 1.0 */
|
||||
const char * streamText2 =
|
||||
"{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;" \
|
||||
"\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255" \
|
||||
"\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 " \
|
||||
"\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 " \
|
||||
"\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 " \
|
||||
"\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 " \
|
||||
"\\tx11448 \\tx11872 \\tx12296 \\tx12720 \\tx13144 \\cf2 RichEdit1\\line }";
|
||||
|
||||
const char * streamText3 = "RichEdit1";
|
||||
|
||||
/* Minimal test without \par at the end */
|
||||
es.dwCookie = (DWORD_PTR)&streamText0;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 12,
|
||||
"EM_STREAMIN: Test 0 returned %ld, expected 12\n", result);
|
||||
result = strcmp (buffer,"TestSomeText");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
/* Native richedit 2.0 ignores last \par */
|
||||
es.dwCookie = (DWORD_PTR)&streamText0a;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 12,
|
||||
"EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result);
|
||||
result = strcmp (buffer,"TestSomeText");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0-a set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
/* Native richedit 2.0 ignores last \par, next-to-last \par appears */
|
||||
es.dwCookie = (DWORD_PTR)&streamText0b;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 14,
|
||||
"EM_STREAMIN: Test 0-b returned %ld, expected 14\n", result);
|
||||
result = strcmp (buffer,"TestSomeText\r\n");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 0-b set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0-b set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
es.dwCookie = (DWORD_PTR)&streamText1;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 12,
|
||||
"EM_STREAMIN: Test 1 returned %ld, expected 12\n", result);
|
||||
result = strcmp (buffer,"TestSomeText");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 1 set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
es.dwCookie = (DWORD_PTR)&streamText2;
|
||||
es.dwError = 0;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 2 returned %ld, expected 0\n", result);
|
||||
ok (strlen(buffer) == 0,
|
||||
"EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == -16, "EM_STREAMIN: Test 2 set error %d, expected %d\n", es.dwError, -16);
|
||||
|
||||
es.dwCookie = (DWORD_PTR)&streamText3;
|
||||
es.dwError = 0;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 3 returned %ld, expected 0\n", result);
|
||||
ok (strlen(buffer) == 0,
|
||||
"EM_STREAMIN: Test 3 set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == -16, "EM_STREAMIN: Test 3 set error %d, expected %d\n", es.dwError, -16);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_StreamIn_Undo(void)
|
||||
{
|
||||
/* The purpose of this test is to determine when a EM_StreamIn should be
|
||||
@@ -2684,6 +3131,82 @@ static void test_eventMask(void)
|
||||
|
||||
}
|
||||
|
||||
static int received_WM_NOTIFY = 0;
|
||||
static int modify_at_WM_NOTIFY = 0;
|
||||
static HWND hwndRichedit_WM_NOTIFY;
|
||||
|
||||
static LRESULT WINAPI WM_NOTIFY_ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if(message == WM_NOTIFY)
|
||||
{
|
||||
received_WM_NOTIFY = 1;
|
||||
modify_at_WM_NOTIFY = SendMessage(hwndRichedit_WM_NOTIFY, EM_GETMODIFY, 0, 0);
|
||||
}
|
||||
return DefWindowProcA(hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
static void test_WM_NOTIFY(void)
|
||||
{
|
||||
HWND parent;
|
||||
WNDCLASSA cls;
|
||||
CHARFORMAT2 cf2;
|
||||
|
||||
/* register class to capture WM_NOTIFY */
|
||||
cls.style = 0;
|
||||
cls.lpfnWndProc = WM_NOTIFY_ParentMsgCheckProcA;
|
||||
cls.cbClsExtra = 0;
|
||||
cls.cbWndExtra = 0;
|
||||
cls.hInstance = GetModuleHandleA(0);
|
||||
cls.hIcon = 0;
|
||||
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
|
||||
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
cls.lpszMenuName = NULL;
|
||||
cls.lpszClassName = "WM_NOTIFY_ParentClass";
|
||||
if(!RegisterClassA(&cls)) assert(0);
|
||||
|
||||
parent = CreateWindow(cls.lpszClassName, NULL, WS_POPUP|WS_VISIBLE,
|
||||
0, 0, 200, 60, NULL, NULL, NULL, NULL);
|
||||
ok (parent != 0, "Failed to create parent window\n");
|
||||
|
||||
hwndRichedit_WM_NOTIFY = new_richedit(parent);
|
||||
ok(hwndRichedit_WM_NOTIFY != 0, "Failed to create edit window\n");
|
||||
|
||||
SendMessage(hwndRichedit_WM_NOTIFY, EM_SETEVENTMASK, 0, ENM_SELCHANGE);
|
||||
|
||||
/* Notifications for selection change should only be sent when selection
|
||||
actually changes. EM_SETCHARFORMAT is one message that calls
|
||||
ME_CommitUndo, which should check whether message should be sent */
|
||||
received_WM_NOTIFY = 0;
|
||||
cf2.cbSize = sizeof(CHARFORMAT2);
|
||||
SendMessage(hwndRichedit_WM_NOTIFY, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT,
|
||||
(LPARAM) &cf2);
|
||||
cf2.dwMask = CFM_ITALIC | cf2.dwMask;
|
||||
cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
|
||||
SendMessage(hwndRichedit_WM_NOTIFY, EM_SETCHARFORMAT, 0, (LPARAM) &cf2);
|
||||
ok(received_WM_NOTIFY == 0, "Unexpected WM_NOTIFY was sent!\n");
|
||||
|
||||
/* WM_SETTEXT should NOT cause a WM_NOTIFY to be sent when selection is
|
||||
already at 0. */
|
||||
received_WM_NOTIFY = 0;
|
||||
modify_at_WM_NOTIFY = 0;
|
||||
SendMessage(hwndRichedit_WM_NOTIFY, WM_SETTEXT, 0, (LPARAM)"sometext");
|
||||
ok(received_WM_NOTIFY == 0, "Unexpected WM_NOTIFY was sent!\n");
|
||||
ok(modify_at_WM_NOTIFY == 0, "WM_NOTIFY callback saw text flagged as modified!\n");
|
||||
|
||||
received_WM_NOTIFY = 0;
|
||||
modify_at_WM_NOTIFY = 0;
|
||||
SendMessage(hwndRichedit_WM_NOTIFY, EM_SETSEL, 4, 4);
|
||||
ok(received_WM_NOTIFY == 1, "Expected WM_NOTIFY was NOT sent!\n");
|
||||
|
||||
received_WM_NOTIFY = 0;
|
||||
modify_at_WM_NOTIFY = 0;
|
||||
SendMessage(hwndRichedit_WM_NOTIFY, WM_SETTEXT, 0, (LPARAM)"sometext");
|
||||
ok(received_WM_NOTIFY == 1, "Expected WM_NOTIFY was NOT sent!\n");
|
||||
ok(modify_at_WM_NOTIFY == 0, "WM_NOTIFY callback saw text flagged as modified!\n");
|
||||
|
||||
DestroyWindow(hwndRichedit_WM_NOTIFY);
|
||||
DestroyWindow(parent);
|
||||
}
|
||||
|
||||
START_TEST( editor )
|
||||
{
|
||||
@@ -2694,18 +3217,20 @@ START_TEST( editor )
|
||||
* RICHED20.DLL, so the linker doesn't actually link to it. */
|
||||
hmoduleRichEdit = LoadLibrary("RICHED20.DLL");
|
||||
ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
|
||||
|
||||
test_WM_CHAR();
|
||||
test_EM_FINDTEXT();
|
||||
test_EM_GETLINE();
|
||||
test_EM_SCROLLCARET();
|
||||
test_EM_SCROLL();
|
||||
test_WM_SETTEXT();
|
||||
test_EM_LINELENGTH();
|
||||
test_EM_SETCHARFORMAT();
|
||||
test_EM_SETTEXTMODE();
|
||||
test_TM_PLAINTEXT();
|
||||
test_EM_SETOPTIONS();
|
||||
test_WM_GETTEXT();
|
||||
test_EM_GETTEXTRANGE();
|
||||
test_EM_GETSELTEXT();
|
||||
test_EM_AUTOURLDETECT();
|
||||
test_EM_SETUNDOLIMIT();
|
||||
test_ES_PASSWORD();
|
||||
@@ -2717,11 +3242,15 @@ START_TEST( editor )
|
||||
test_EM_GETMODIFY();
|
||||
test_EM_EXSETSEL();
|
||||
test_WM_PASTE();
|
||||
test_EM_STREAMIN();
|
||||
test_EM_STREAMOUT();
|
||||
test_EM_StreamIn_Undo();
|
||||
test_EM_FORMATRANGE();
|
||||
test_unicode_conversions();
|
||||
test_EM_GETTEXTLENGTHEX();
|
||||
test_EM_REPLACESEL();
|
||||
test_EM_REPLACESEL(1);
|
||||
test_EM_REPLACESEL(0);
|
||||
test_WM_NOTIFY();
|
||||
test_eventMask();
|
||||
|
||||
/* Set the environment variable WINETEST_RICHED20 to keep windows
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="riched20_winetest" type="win32cui" installbase="bin" installname="riched20_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="riched20_winetest" type="win32cui" installbase="bin" installname="riched20_winetest.exe" allowwarnings="true">
|
||||
<include base="riched20_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -64,6 +64,9 @@ static void test_WM_SETTEXT()
|
||||
const char * TestItem11 = "TestSomeText TestSomeText";
|
||||
const char * TestItem12 = "TestSomeText \r\nTestSomeText";
|
||||
const char * TestItem13 = "TestSomeText\r\n \r\nTestSomeText";
|
||||
const char * TestItem14 = "TestSomeText\n";
|
||||
const char * TestItem15 = "TestSomeText\r\r\r";
|
||||
const char * TestItem16 = "TestSomeText\r\r\rSomeMoreText";
|
||||
char buf[1024] = {0};
|
||||
LRESULT result;
|
||||
|
||||
@@ -72,9 +75,19 @@ static void test_WM_SETTEXT()
|
||||
return it as is. In particular, \r\r\n is NOT converted, unlike riched20.
|
||||
Currently, builtin riched32 mangles solitary \r or \n when not part of
|
||||
a \r\n pair.
|
||||
|
||||
For riched32, the rules for breaking lines seem to be the following:
|
||||
- \r\n is one line break. This is the normal case.
|
||||
- \r{0,N}\n is one line break. In particular, \n by itself is a line break.
|
||||
- \n{1,N} are that many line breaks.
|
||||
- \r with text or other characters (except \n) past it, is a line break. That
|
||||
is, a run of \r{N} without a terminating \n is considered N line breaks
|
||||
- \r at the end of the text is NOT a line break. This differs from riched20,
|
||||
where \r at the end of the text is a proper line break. This causes
|
||||
TestItem2 to fail its test.
|
||||
*/
|
||||
|
||||
#define TEST_SETTEXT(a, b, is_todo) \
|
||||
#define TEST_SETTEXT(a, b, nlines, is_todo, is_todo2) \
|
||||
result = SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) a); \
|
||||
ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); \
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buf); \
|
||||
@@ -88,21 +101,30 @@ static void test_WM_SETTEXT()
|
||||
} else { \
|
||||
ok(result == 0, \
|
||||
"WM_SETTEXT round trip: strcmp = %ld\n", result); \
|
||||
} \
|
||||
result = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0); \
|
||||
if (is_todo2) todo_wine { \
|
||||
ok(result == nlines, "EM_GETLINECOUNT returned %ld, expected %d\n", result, nlines); \
|
||||
} else { \
|
||||
ok(result == nlines, "EM_GETLINECOUNT returned %ld, expected %d\n", result, nlines); \
|
||||
}
|
||||
|
||||
TEST_SETTEXT(TestItem1, TestItem1, 0)
|
||||
TEST_SETTEXT(TestItem2, TestItem2, 1)
|
||||
TEST_SETTEXT(TestItem3, TestItem3, 1)
|
||||
TEST_SETTEXT(TestItem4, TestItem4, 1)
|
||||
TEST_SETTEXT(TestItem5, TestItem5, 1)
|
||||
TEST_SETTEXT(TestItem6, TestItem6, 1)
|
||||
TEST_SETTEXT(TestItem7, TestItem7, 1)
|
||||
TEST_SETTEXT(TestItem8, TestItem8, 0)
|
||||
TEST_SETTEXT(TestItem9, TestItem9, 0)
|
||||
TEST_SETTEXT(TestItem10, TestItem10, 0)
|
||||
TEST_SETTEXT(TestItem11, TestItem11, 0)
|
||||
TEST_SETTEXT(TestItem12, TestItem12, 0)
|
||||
TEST_SETTEXT(TestItem13, TestItem13, 0)
|
||||
TEST_SETTEXT(TestItem1, TestItem1, 1, 0, 0)
|
||||
TEST_SETTEXT(TestItem2, TestItem2, 1, 0, 0)
|
||||
TEST_SETTEXT(TestItem3, TestItem3, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem4, TestItem4, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem5, TestItem5, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem6, TestItem6, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem7, TestItem7, 4, 0, 0)
|
||||
TEST_SETTEXT(TestItem8, TestItem8, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem9, TestItem9, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem10, TestItem10, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem11, TestItem11, 1, 0, 0)
|
||||
TEST_SETTEXT(TestItem12, TestItem12, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem13, TestItem13, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem14, TestItem14, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem15, TestItem15, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem16, TestItem16, 4, 0, 0)
|
||||
|
||||
#undef TEST_SETTEXT
|
||||
DestroyWindow(hwndRichEdit);
|
||||
@@ -131,6 +153,551 @@ static void test_WM_GETTEXTLENGTH(void)
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static DWORD CALLBACK test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie,
|
||||
LPBYTE pbBuff,
|
||||
LONG cb,
|
||||
LONG *pcb)
|
||||
{
|
||||
const char** str = (const char**)dwCookie;
|
||||
int size = strlen(*str);
|
||||
*pcb = cb;
|
||||
if (*pcb > size) {
|
||||
*pcb = size;
|
||||
}
|
||||
if (*pcb > 0) {
|
||||
memcpy(pbBuff, *str, *pcb);
|
||||
*str += *pcb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void test_EM_STREAMIN(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
LRESULT result;
|
||||
EDITSTREAM es;
|
||||
char buffer[1024] = {0};
|
||||
|
||||
const char * streamText0 = "{\\rtf1 TestSomeText}";
|
||||
const char * streamText0a = "{\\rtf1 TestSomeText\\par}";
|
||||
const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
|
||||
|
||||
const char * streamText1 =
|
||||
"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n" \
|
||||
"\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n" \
|
||||
"}\r\n";
|
||||
|
||||
/* This should be accepted in richedit 1.0 emulation. See bug #8326 */
|
||||
const char * streamText2 =
|
||||
"{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;" \
|
||||
"\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255" \
|
||||
"\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 " \
|
||||
"\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 " \
|
||||
"\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 " \
|
||||
"\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 " \
|
||||
"\\tx11448 \\tx11872 \\tx12296 \\tx12720 \\tx13144 \\cf2 RichEdit1\\line }";
|
||||
|
||||
const char * streamText3 = "RichEdit1";
|
||||
|
||||
/* Minimal test without \par at the end */
|
||||
es.dwCookie = (DWORD_PTR)&streamText0;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 12,
|
||||
"EM_STREAMIN: Test 0 returned %ld, expected 12\n", result);
|
||||
result = strcmp (buffer,"TestSomeText");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
/* Native richedit 2.0 ignores last \par */
|
||||
es.dwCookie = (DWORD_PTR)&streamText0a;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 12,
|
||||
"EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result);
|
||||
result = strcmp (buffer,"TestSomeText");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
/* Native richedit 2.0 ignores last \par, next-to-last \par appears */
|
||||
es.dwCookie = (DWORD_PTR)&streamText0b;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 14,
|
||||
"EM_STREAMIN: Test 0-b returned %ld, expected 14\n", result);
|
||||
result = strcmp (buffer,"TestSomeText\r\n");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 0-b set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
es.dwCookie = (DWORD_PTR)&streamText1;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_EM_STREAMIN_esCallback;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 12,
|
||||
"EM_STREAMIN: Test 1 returned %ld, expected 12\n", result);
|
||||
result = strcmp (buffer,"TestSomeText");
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
|
||||
es.dwCookie = (DWORD_PTR)&streamText2;
|
||||
es.dwError = 0;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
todo_wine {
|
||||
ok (result == 9,
|
||||
"EM_STREAMIN: Test 2 returned %ld, expected 9\n", result);
|
||||
}
|
||||
result = strcmp (buffer,"RichEdit1");
|
||||
todo_wine {
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
|
||||
}
|
||||
ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
|
||||
|
||||
es.dwCookie = (DWORD_PTR)&streamText3;
|
||||
es.dwError = 0;
|
||||
SendMessage(hwndRichEdit, EM_STREAMIN,
|
||||
(WPARAM)(SF_RTF), (LPARAM)&es);
|
||||
|
||||
result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
|
||||
ok (result == 0,
|
||||
"EM_STREAMIN: Test 3 returned %ld, expected 0\n", result);
|
||||
ok (strlen(buffer) == 0,
|
||||
"EM_STREAMIN: Test 3 set wrong text: Result: %s\n",buffer);
|
||||
ok(es.dwError == -16, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, -16);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,
|
||||
LPBYTE pbBuff,
|
||||
LONG cb,
|
||||
LONG *pcb)
|
||||
{
|
||||
char** str = (char**)dwCookie;
|
||||
*pcb = cb;
|
||||
if (*pcb > 0) {
|
||||
memcpy(*str, pbBuff, *pcb);
|
||||
*str += *pcb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_EM_STREAMOUT(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
int r;
|
||||
EDITSTREAM es;
|
||||
char buf[1024] = {0};
|
||||
char * p;
|
||||
|
||||
const char * TestItem1 = "TestSomeText";
|
||||
const char * TestItem2 = "TestSomeText\r";
|
||||
const char * TestItem3 = "TestSomeText\r\n";
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||
r = strlen(buf);
|
||||
ok(r == 12, "streamed text length is %d, expecting 12\n", r);
|
||||
ok(strcmp(buf, TestItem1) == 0,
|
||||
"streamed text different, got %s\n", buf);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||
r = strlen(buf);
|
||||
|
||||
ok(r == 13, "streamed text length is %d, expecting 13\n", r);
|
||||
ok(strcmp(buf, TestItem2) == 0,
|
||||
"streamed text different, got %s\n", buf);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||
r = strlen(buf);
|
||||
ok(r == 14, "streamed text length is %d, expecting 14\n", r);
|
||||
ok(strcmp(buf, TestItem3) == 0,
|
||||
"streamed text different, got %s\n", buf);
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static const struct getline_s {
|
||||
int line;
|
||||
size_t buffer_len;
|
||||
const char *text;
|
||||
int wine_todo;
|
||||
} gl[] = {
|
||||
{0, 10, "foo bar\r\n", 0},
|
||||
{1, 10, "\n", 0},
|
||||
{2, 10, "bar\n", 0},
|
||||
{3, 10, "\r\n", 0},
|
||||
|
||||
/* Buffer smaller than line length */
|
||||
{0, 2, "foo bar\r", 0},
|
||||
{0, 1, "foo bar\r", 0},
|
||||
{0, 0, "foo bar\r", 0}
|
||||
};
|
||||
|
||||
static void test_EM_GETLINE(void)
|
||||
{
|
||||
int i;
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
static const int nBuf = 1024;
|
||||
char dest[1024], origdest[1024];
|
||||
const char text[] = "foo bar\r\n"
|
||||
"\n"
|
||||
"bar\n";
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
|
||||
|
||||
memset(origdest, 0xBB, nBuf);
|
||||
for (i = 0; i < sizeof(gl)/sizeof(struct getline_s); i++)
|
||||
{
|
||||
int nCopied;
|
||||
int expected_nCopied = min(gl[i].buffer_len, strlen(gl[i].text));
|
||||
int expected_bytes_written = min(gl[i].buffer_len, strlen(gl[i].text) + 1);
|
||||
memset(dest, 0xBB, nBuf);
|
||||
*(WORD *) dest = gl[i].buffer_len;
|
||||
|
||||
/* EM_GETLINE appends a "\r\0" to the end of the line
|
||||
* nCopied counts up to and including the '\r' */
|
||||
nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest);
|
||||
if (gl[i].wine_todo) todo_wine {
|
||||
ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
|
||||
expected_nCopied);
|
||||
} else
|
||||
ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
|
||||
expected_nCopied);
|
||||
/* two special cases since a parameter is passed via dest */
|
||||
if (gl[i].buffer_len == 0)
|
||||
ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
|
||||
"buffer_len=0\n");
|
||||
else if (gl[i].buffer_len == 1)
|
||||
ok(dest[0] == gl[i].text[0] && !dest[1] &&
|
||||
!strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
|
||||
else
|
||||
{
|
||||
if (gl[i].wine_todo) todo_wine {
|
||||
ok(!strncmp(dest, gl[i].text, expected_bytes_written),
|
||||
"%d: expected_bytes_written=%d\n", i, expected_bytes_written);
|
||||
ok(!strncmp(dest + expected_bytes_written, origdest
|
||||
+ expected_bytes_written, nBuf - expected_bytes_written),
|
||||
"%d: expected_bytes_written=%d\n", i, expected_bytes_written);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(!strncmp(dest, gl[i].text, expected_bytes_written),
|
||||
"%d: expected_bytes_written=%d\n", i, expected_bytes_written);
|
||||
ok(!strncmp(dest + expected_bytes_written, origdest
|
||||
+ expected_bytes_written, nBuf - expected_bytes_written),
|
||||
"%d: expected_bytes_written=%d\n", i, expected_bytes_written);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_LINELENGTH(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
const char * text =
|
||||
"richedit1\r"
|
||||
"richedit1\n"
|
||||
"richedit1\r\n"
|
||||
"richedit1\r\r\r\r\r\n";
|
||||
int offset_test[10][2] = {
|
||||
{0, 9},
|
||||
{5, 9},
|
||||
{10, 9},
|
||||
{15, 9},
|
||||
{20, 9},
|
||||
{25, 9},
|
||||
{30, 9},
|
||||
{35, 9},
|
||||
{40, 9}, /* <----- in the middle of the \r run, but run not counted */
|
||||
{45, 0},
|
||||
};
|
||||
int i;
|
||||
LRESULT result;
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
result = SendMessage(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
|
||||
ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
|
||||
offset_test[i][0], result, offset_test[i][1]);
|
||||
}
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_GETTEXTRANGE(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
const char * text1 = "foo bar\r\nfoo bar";
|
||||
const char * text2 = "foo bar\rfoo bar";
|
||||
const char * expect1 = "bar\r\nfoo";
|
||||
const char * expect2 = "bar\rfoo";
|
||||
char buffer[1024] = {0};
|
||||
LRESULT result;
|
||||
TEXTRANGEA textRange;
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
|
||||
|
||||
textRange.lpstrText = buffer;
|
||||
textRange.chrg.cpMin = 4;
|
||||
textRange.chrg.cpMax = 12;
|
||||
result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
|
||||
ok(result == 8, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
ok(!strcmp(expect1, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
|
||||
|
||||
textRange.lpstrText = buffer;
|
||||
textRange.chrg.cpMin = 4;
|
||||
textRange.chrg.cpMax = 11;
|
||||
result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
|
||||
ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static void test_EM_GETSELTEXT(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
const char * text1 = "foo bar\r\nfoo bar";
|
||||
const char * text2 = "foo bar\rfoo bar";
|
||||
const char * expect1 = "bar\r\nfoo";
|
||||
const char * expect2 = "bar\rfoo";
|
||||
char buffer[1024] = {0};
|
||||
LRESULT result;
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
|
||||
|
||||
SendMessage(hwndRichEdit, EM_SETSEL, 4, 12);
|
||||
result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
|
||||
ok(result == 8, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
ok(!strcmp(expect1, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
|
||||
|
||||
SendMessage(hwndRichEdit, EM_SETSEL, 4, 11);
|
||||
result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
|
||||
|
||||
ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
static const char haystack[] = "WINEWine wineWine wine WineWine";
|
||||
/* ^0 ^10 ^20 ^30 */
|
||||
|
||||
struct find_s {
|
||||
int start;
|
||||
int end;
|
||||
const char *needle;
|
||||
int flags;
|
||||
int expected_loc;
|
||||
int _todo_wine;
|
||||
};
|
||||
|
||||
|
||||
struct find_s find_tests[] = {
|
||||
/* Find in empty text */
|
||||
{0, -1, "foo", FR_DOWN, -1, 0},
|
||||
{0, -1, "foo", 0, -1, 0},
|
||||
{0, -1, "", FR_DOWN, -1, 0},
|
||||
{20, 5, "foo", FR_DOWN, -1, 0},
|
||||
{5, 20, "foo", FR_DOWN, -1, 0}
|
||||
};
|
||||
|
||||
struct find_s find_tests2[] = {
|
||||
/* No-result find */
|
||||
{0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1, 0},
|
||||
{5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1, 0},
|
||||
|
||||
/* Subsequent finds */
|
||||
{0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4, 0},
|
||||
{5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13, 0},
|
||||
{14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
|
||||
{24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
|
||||
|
||||
/* Find backwards */
|
||||
{19, 20, "Wine", FR_MATCHCASE, -1, 0},
|
||||
{10, 20, "Wine", FR_MATCHCASE, 13, 0},
|
||||
{20, 10, "Wine", FR_MATCHCASE, -1, 0},
|
||||
|
||||
/* Case-insensitive */
|
||||
{1, 31, "wInE", FR_DOWN, 4, 0},
|
||||
{1, 31, "Wine", FR_DOWN, 4, 0},
|
||||
|
||||
/* High-to-low ranges */
|
||||
{20, 5, "Wine", FR_DOWN, -1, 0},
|
||||
{2, 1, "Wine", FR_DOWN, -1, 0},
|
||||
{30, 29, "Wine", FR_DOWN, -1, 0},
|
||||
{20, 5, "Wine", 0, /*13*/ -1, 0},
|
||||
|
||||
/* Find nothing */
|
||||
{5, 10, "", FR_DOWN, -1, 0},
|
||||
{10, 5, "", FR_DOWN, -1, 0},
|
||||
{0, -1, "", FR_DOWN, -1, 0},
|
||||
{10, 5, "", 0, -1, 0},
|
||||
|
||||
/* Whole-word search */
|
||||
{0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 0},
|
||||
{0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1, 0},
|
||||
{13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 0},
|
||||
{0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0, 0},
|
||||
{10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23, 0},
|
||||
{11, -1, "winewine", FR_WHOLEWORD, 23, 0},
|
||||
{31, -1, "winewine", FR_WHOLEWORD, -1, 0},
|
||||
|
||||
/* Bad ranges */
|
||||
{5, 200, "XXX", FR_DOWN, -1, 0},
|
||||
{-20, 20, "Wine", FR_DOWN, -1, 0},
|
||||
{-20, 20, "Wine", FR_DOWN, -1, 0},
|
||||
{-15, -20, "Wine", FR_DOWN, -1, 0},
|
||||
{1<<12, 1<<13, "Wine", FR_DOWN, -1, 0},
|
||||
|
||||
/* Check the case noted in bug 4479 where matches at end aren't recognized */
|
||||
{23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
|
||||
{27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
|
||||
{27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
|
||||
{13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
|
||||
{13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
|
||||
|
||||
/* The backwards case of bug 4479; bounds look right
|
||||
* Fails because backward find is wrong */
|
||||
{19, 20, "WINE", FR_MATCHCASE, -1, 0},
|
||||
{0, 20, "WINE", FR_MATCHCASE, 0, 0},
|
||||
|
||||
{0, -1, "wineWine wine", FR_DOWN, 0, 0},
|
||||
{0, -1, "wineWine wine", 0, 0, 0},
|
||||
{0, -1, "INEW", 0, 1, 0},
|
||||
{0, 31, "INEW", 0, 1, 0},
|
||||
{4, -1, "INEW", 0, 10, 0},
|
||||
};
|
||||
|
||||
static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id) {
|
||||
int findloc;
|
||||
FINDTEXT ft;
|
||||
memset(&ft, 0, sizeof(ft));
|
||||
ft.chrg.cpMin = f->start;
|
||||
ft.chrg.cpMax = f->end;
|
||||
ft.lpstrText = f->needle;
|
||||
findloc = SendMessage(hwnd, EM_FINDTEXT, f->flags, (LPARAM) &ft);
|
||||
ok(findloc == f->expected_loc,
|
||||
"EM_FINDTEXT(%s,%d) '%s' in range(%d,%d), flags %08x, got start at %d, expected %d\n",
|
||||
name, id, f->needle, f->start, f->end, f->flags, findloc, f->expected_loc);
|
||||
}
|
||||
|
||||
static void check_EM_FINDTEXTEX(HWND hwnd, const char *name, struct find_s *f,
|
||||
int id) {
|
||||
int findloc;
|
||||
FINDTEXTEX ft;
|
||||
int expected_end_loc;
|
||||
|
||||
memset(&ft, 0, sizeof(ft));
|
||||
ft.chrg.cpMin = f->start;
|
||||
ft.chrg.cpMax = f->end;
|
||||
ft.lpstrText = f->needle;
|
||||
findloc = SendMessage(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM) &ft);
|
||||
ok(findloc == f->expected_loc,
|
||||
"EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
|
||||
name, id, f->needle, f->start, f->end, f->flags, findloc);
|
||||
ok(ft.chrgText.cpMin == f->expected_loc,
|
||||
"EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d, expected %d\n",
|
||||
name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMin, f->expected_loc);
|
||||
expected_end_loc = ((f->expected_loc == -1) ? -1
|
||||
: f->expected_loc + strlen(f->needle));
|
||||
ok(ft.chrgText.cpMax == expected_end_loc,
|
||||
"EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %d, expected %d\n",
|
||||
name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMax, expected_end_loc);
|
||||
}
|
||||
|
||||
static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *find,
|
||||
int num_tests)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_tests; i++) {
|
||||
if (find[i]._todo_wine) {
|
||||
todo_wine {
|
||||
check_EM_FINDTEXT(hwnd, name, &find[i], i);
|
||||
check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
|
||||
}
|
||||
} else {
|
||||
check_EM_FINDTEXT(hwnd, name, &find[i], i);
|
||||
check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_EM_FINDTEXT(void)
|
||||
{
|
||||
HWND hwndRichEdit = new_richedit(NULL);
|
||||
|
||||
/* Empty rich edit control */
|
||||
run_tests_EM_FINDTEXT(hwndRichEdit, "1", find_tests,
|
||||
sizeof(find_tests)/sizeof(struct find_s));
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
|
||||
|
||||
/* Haystack text */
|
||||
run_tests_EM_FINDTEXT(hwndRichEdit, "2", find_tests2,
|
||||
sizeof(find_tests2)/sizeof(struct find_s));
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
START_TEST( editor )
|
||||
{
|
||||
MSG msg;
|
||||
@@ -142,7 +709,14 @@ START_TEST( editor )
|
||||
ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
|
||||
|
||||
test_WM_SETTEXT();
|
||||
test_EM_GETTEXTRANGE();
|
||||
test_EM_GETSELTEXT();
|
||||
test_WM_GETTEXTLENGTH();
|
||||
test_EM_STREAMIN();
|
||||
test_EM_STREAMOUT();
|
||||
test_EM_GETLINE();
|
||||
test_EM_LINELENGTH();
|
||||
test_EM_FINDTEXT();
|
||||
|
||||
/* Set the environment variable WINETEST_RICHED32 to keep windows
|
||||
* responsive and open for 30 seconds. This is useful for debugging.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="riched32_winetest" type="win32cui" installbase="bin" installname="riched32_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="riched32_winetest" type="win32cui" installbase="bin" installname="riched32_winetest.exe" allowwarnings="true">
|
||||
<include base="riched32_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -924,6 +924,8 @@ static void test_delegating_Invoke(IPSFactoryBuffer *ppsf)
|
||||
ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08x\n", *(DWORD*)msg.Buffer);
|
||||
ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08x\n", *((DWORD*)msg.Buffer + 1));
|
||||
}
|
||||
/* free the buffer allocated by delegating_invoke_chan_get_buffer */
|
||||
HeapFree(GetProcessHeap(), 0, msg.Buffer);
|
||||
IRpcStubBuffer_Release(pstub);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "wine/test.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Compability macros
|
||||
* Compatibility macros
|
||||
*/
|
||||
|
||||
#define DWORD_PTR UINT_PTR
|
||||
|
||||
@@ -72,6 +72,31 @@ static const MIDL_STUB_DESC Object_StubDesc =
|
||||
0 /* Reserved5 */
|
||||
};
|
||||
|
||||
static RPC_DISPATCH_FUNCTION IFoo_table[] =
|
||||
{
|
||||
0
|
||||
};
|
||||
|
||||
static RPC_DISPATCH_TABLE IFoo_v0_0_DispatchTable =
|
||||
{
|
||||
0,
|
||||
IFoo_table
|
||||
};
|
||||
|
||||
static const RPC_SERVER_INTERFACE IFoo___RpcServerInterface =
|
||||
{
|
||||
sizeof(RPC_SERVER_INTERFACE),
|
||||
{{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x34}},{0,0}},
|
||||
{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},
|
||||
&IFoo_v0_0_DispatchTable,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
static RPC_IF_HANDLE IFoo_v0_0_s_ifspec = (RPC_IF_HANDLE)& IFoo___RpcServerInterface;
|
||||
|
||||
static void test_ndr_simple_type(void)
|
||||
{
|
||||
@@ -251,7 +276,7 @@ todo_wine {
|
||||
ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
|
||||
else
|
||||
ok(mem == StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem doesn't point to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
|
||||
ok(!cmp(mem, memsrc, size), "%s: incorrecly unmarshaled\n", msgpfx);
|
||||
ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx);
|
||||
ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
|
||||
ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
|
||||
if (formattypes[2] != 0xd /* FC_ENUM16 */) {
|
||||
@@ -452,6 +477,161 @@ static void test_simple_types(void)
|
||||
|
||||
}
|
||||
|
||||
static void test_nontrivial_pointer_types(void)
|
||||
{
|
||||
RPC_MESSAGE RpcMessage;
|
||||
MIDL_STUB_MESSAGE StubMsg;
|
||||
MIDL_STUB_DESC StubDesc;
|
||||
void *ptr;
|
||||
char **p1;
|
||||
char *p2;
|
||||
char ch;
|
||||
unsigned char *mem, *mem_orig;
|
||||
|
||||
static const unsigned char fmtstr_ref_unique_out[] =
|
||||
{
|
||||
0x12, 0x8, /* FC_UP [simple_pointer] */
|
||||
0x2, /* FC_CHAR */
|
||||
0x5c, /* FC_PAD */
|
||||
0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */
|
||||
NdrFcShort( 0xfffffffa ), /* Offset= -6 (0) */
|
||||
};
|
||||
|
||||
p1 = &p2;
|
||||
p2 = &ch;
|
||||
ch = 0x22;
|
||||
|
||||
StubDesc = Object_StubDesc;
|
||||
StubDesc.pFormatTypes = fmtstr_ref_unique_out;
|
||||
|
||||
NdrClientInitializeNew(
|
||||
&RpcMessage,
|
||||
&StubMsg,
|
||||
&StubDesc,
|
||||
0);
|
||||
|
||||
StubMsg.BufferLength = 0;
|
||||
NdrPointerBufferSize( &StubMsg,
|
||||
(unsigned char *)p1,
|
||||
&fmtstr_ref_unique_out[4] );
|
||||
|
||||
/* Windows overestimates the buffer size */
|
||||
ok(StubMsg.BufferLength >= 5, "length %d\n", StubMsg.BufferLength);
|
||||
|
||||
/*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
|
||||
StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
|
||||
StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
|
||||
|
||||
ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)p1, &fmtstr_ref_unique_out[4] );
|
||||
ok(ptr == NULL, "ret %p\n", ptr);
|
||||
ok(StubMsg.Buffer - StubMsg.BufferStart == 5, "Buffer %p Start %p len %d\n",
|
||||
StubMsg.Buffer, StubMsg.BufferStart, StubMsg.Buffer - StubMsg.BufferStart);
|
||||
ok(*(unsigned int *)StubMsg.BufferStart != 0, "pointer ID marshalled incorrectly\n");
|
||||
ok(*(unsigned char *)(StubMsg.BufferStart + 4) == 0x22, "char data marshalled incorrectly: 0x%x\n",
|
||||
*(unsigned char *)(StubMsg.BufferStart + 4));
|
||||
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
StubMsg.MemorySize = 0;
|
||||
mem = NULL;
|
||||
|
||||
/* Client */
|
||||
my_alloc_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(void *));
|
||||
*(void **)mem = NULL;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
|
||||
|
||||
my_alloc_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
|
||||
todo_wine {
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
|
||||
my_free_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
ok(my_free_called == 1, "free called %d\n", my_free_called);
|
||||
|
||||
mem = my_alloc(sizeof(void *));
|
||||
*(void **)mem = NULL;
|
||||
my_free_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
ok(my_free_called == 0, "free called %d\n", my_free_called);
|
||||
my_free(mem);
|
||||
|
||||
mem = my_alloc(sizeof(void *));
|
||||
*(void **)mem = my_alloc(sizeof(char));
|
||||
my_free_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
ok(my_free_called == 1, "free called %d\n", my_free_called);
|
||||
my_free(mem);
|
||||
|
||||
/* Server */
|
||||
my_alloc_called = 0;
|
||||
StubMsg.IsClient = 0;
|
||||
mem = NULL;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
|
||||
ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
|
||||
todo_wine
|
||||
ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
|
||||
my_alloc_called = 0;
|
||||
mem = NULL;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
|
||||
ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
|
||||
todo_wine
|
||||
ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
|
||||
my_alloc_called = 0;
|
||||
mem = mem_orig;
|
||||
*(void **)mem = NULL;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
|
||||
todo_wine {
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
|
||||
my_alloc_called = 0;
|
||||
mem = mem_orig;
|
||||
*(void **)mem = NULL;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
|
||||
todo_wine {
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
|
||||
mem = my_alloc(sizeof(void *));
|
||||
*(void **)mem = NULL;
|
||||
my_free_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
ok(my_free_called == 0, "free called %d\n", my_free_called);
|
||||
my_free(mem);
|
||||
|
||||
mem = my_alloc(sizeof(void *));
|
||||
*(void **)mem = my_alloc(sizeof(char));
|
||||
my_free_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
ok(my_free_called == 1, "free called %d\n", my_free_called);
|
||||
my_free(mem);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, mem_orig);
|
||||
HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
|
||||
}
|
||||
|
||||
static void test_simple_struct_marshal(const unsigned char *formattypes,
|
||||
void *memsrc,
|
||||
long srcsize,
|
||||
@@ -520,7 +700,7 @@ todo_wine {
|
||||
my_alloc_called = 0;
|
||||
ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
|
||||
|
||||
/* if we're a server we still use the suppiled memory */
|
||||
/* If we're a server we still use the supplied memory */
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
StubMsg.IsClient = 0;
|
||||
ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
|
||||
@@ -866,11 +1046,27 @@ static void test_client_init(void)
|
||||
MIDL_STUB_MESSAGE stubMsg;
|
||||
RPC_MESSAGE rpcMsg;
|
||||
|
||||
memset(&rpcMsg, 0, sizeof(rpcMsg));
|
||||
memset(&rpcMsg, 0xcc, sizeof(rpcMsg));
|
||||
memset(&stubMsg, 0xcc, sizeof(stubMsg));
|
||||
|
||||
NdrClientInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc, 1);
|
||||
|
||||
#define TEST_POINTER_UNSET(field) ok(rpcMsg.field == (void *)0xcccccccc, #field " should have been unset instead of %p\n", rpcMsg.field)
|
||||
|
||||
ok(rpcMsg.Handle == NULL, "rpcMsg.Handle should have been NULL instead of %p\n", rpcMsg.Handle);
|
||||
TEST_POINTER_UNSET(Buffer);
|
||||
ok(rpcMsg.BufferLength == 0xcccccccc, "rpcMsg.BufferLength should have been unset instead of %d\n", rpcMsg.BufferLength);
|
||||
ok(rpcMsg.ProcNum == 0x8001, "rpcMsg.ProcNum should have been 0x8001 instead of 0x%x\n", rpcMsg.ProcNum);
|
||||
TEST_POINTER_UNSET(TransferSyntax);
|
||||
ok(rpcMsg.RpcInterfaceInformation == Object_StubDesc.RpcInterfaceInformation,
|
||||
"rpcMsg.RpcInterfaceInformation should have been %p instead of %p\n",
|
||||
Object_StubDesc.RpcInterfaceInformation, rpcMsg.RpcInterfaceInformation);
|
||||
/* Note: ReservedForRuntime not tested */
|
||||
TEST_POINTER_UNSET(ManagerEpv);
|
||||
TEST_POINTER_UNSET(ImportContext);
|
||||
ok(rpcMsg.RpcFlags == 0, "rpcMsg.RpcFlags should have been 0 instead of 0x%lx\n", rpcMsg.RpcFlags);
|
||||
#undef TEST_POINTER_UNSET
|
||||
|
||||
#define TEST_ZERO(field, fmt) ok(stubMsg.field == 0, #field " should have been set to zero instead of " fmt "\n", stubMsg.field)
|
||||
#define TEST_POINTER_UNSET(field) ok(stubMsg.field == (void *)0xcccccccc, #field " should have been unset instead of %p\n", stubMsg.field)
|
||||
#define TEST_ULONG_UNSET(field) ok(stubMsg.field == 0xcccccccc, #field " should have been unset instead of 0x%x\n", stubMsg.field)
|
||||
@@ -1509,10 +1705,120 @@ static void test_nonconformant_string(void)
|
||||
HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
|
||||
}
|
||||
|
||||
static void test_ndr_buffer(void)
|
||||
{
|
||||
static unsigned char ncalrpc[] = "ncalrpc";
|
||||
static unsigned char endpoint[] = "winetest:test_ndr_buffer";
|
||||
RPC_MESSAGE RpcMessage;
|
||||
MIDL_STUB_MESSAGE StubMsg;
|
||||
MIDL_STUB_DESC StubDesc = Object_StubDesc;
|
||||
unsigned char *ret;
|
||||
unsigned char *binding;
|
||||
RPC_BINDING_HANDLE Handle;
|
||||
RPC_STATUS status;
|
||||
|
||||
StubDesc.RpcInterfaceInformation = (void *)&IFoo___RpcServerInterface;
|
||||
|
||||
status = RpcServerUseProtseqEp(ncalrpc, 20, endpoint, NULL);
|
||||
ok(RPC_S_OK == status, "RpcServerUseProtseqEp failed with status %lu\n", status);
|
||||
status = RpcServerRegisterIf(IFoo_v0_0_s_ifspec, NULL, NULL);
|
||||
ok(RPC_S_OK == status, "RpcServerRegisterIf failed with status %lu\n", status);
|
||||
status = RpcServerListen(1, 20, TRUE);
|
||||
ok(RPC_S_OK == status, "RpcServerListen failed with status %lu\n", status);
|
||||
if (status != RPC_S_OK)
|
||||
{
|
||||
/* Failed to create a server, running client tests is useless */
|
||||
return;
|
||||
}
|
||||
|
||||
status = RpcStringBindingCompose(NULL, ncalrpc, NULL, endpoint, NULL, &binding);
|
||||
ok(status == RPC_S_OK, "RpcStringBindingCompose failed (%lu)\n", status);
|
||||
|
||||
status = RpcBindingFromStringBinding(binding, &Handle);
|
||||
ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%lu)\n", status);
|
||||
RpcStringFree(&binding);
|
||||
|
||||
NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 5);
|
||||
|
||||
ret = NdrGetBuffer(&StubMsg, 10, Handle);
|
||||
ok(ret == StubMsg.Buffer, "NdrGetBuffer should have returned the same value as StubMsg.Buffer instead of %p\n", ret);
|
||||
ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n");
|
||||
ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n");
|
||||
ok(RpcMessage.BufferLength == 10, "RpcMessage.BufferLength should have been 10 instead of %d\n", RpcMessage.BufferLength);
|
||||
ok(RpcMessage.RpcFlags == 0, "RpcMessage.RpcFlags should have been 0x0 instead of 0x%lx\n", RpcMessage.RpcFlags);
|
||||
ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n");
|
||||
ok(!StubMsg.BufferStart, "BufferStart should have been NULL instead of %p\n", StubMsg.BufferStart);
|
||||
ok(!StubMsg.BufferEnd, "BufferEnd should have been NULL instead of %p\n", StubMsg.BufferEnd);
|
||||
todo_wine
|
||||
ok(StubMsg.BufferLength == 0, "BufferLength should have left as 0 instead of being set to %d\n", StubMsg.BufferLength);
|
||||
ok(StubMsg.fBufferValid == TRUE, "fBufferValid should have been TRUE instead of 0x%x\n", StubMsg.fBufferValid);
|
||||
|
||||
StubMsg.BufferLength = 1;
|
||||
NdrFreeBuffer(&StubMsg);
|
||||
ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n");
|
||||
ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n");
|
||||
ok(RpcMessage.BufferLength == 10, "RpcMessage.BufferLength should have been left as 10 instead of %d\n", RpcMessage.BufferLength);
|
||||
ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n");
|
||||
ok(StubMsg.BufferLength == 1, "BufferLength should have left as 1 instead of being set to %d\n", StubMsg.BufferLength);
|
||||
ok(StubMsg.fBufferValid == FALSE, "fBufferValid should have been FALSE instead of 0x%x\n", StubMsg.fBufferValid);
|
||||
|
||||
/* attempt double-free */
|
||||
NdrFreeBuffer(&StubMsg);
|
||||
|
||||
RpcBindingFree(&Handle);
|
||||
|
||||
status = RpcServerUnregisterIf(NULL, NULL, FALSE);
|
||||
ok(status == RPC_S_OK, "RpcServerUnregisterIf failed (%lu)\n", status);
|
||||
}
|
||||
|
||||
static void test_NdrMapCommAndFaultStatus(void)
|
||||
{
|
||||
RPC_STATUS rpc_status;
|
||||
MIDL_STUB_MESSAGE StubMsg;
|
||||
RPC_MESSAGE RpcMessage;
|
||||
|
||||
NdrClientInitializeNew(&RpcMessage, &StubMsg, &Object_StubDesc, 5);
|
||||
|
||||
for (rpc_status = 0; rpc_status < 10000; rpc_status++)
|
||||
{
|
||||
RPC_STATUS status;
|
||||
ULONG comm_status = 0;
|
||||
ULONG fault_status = 0;
|
||||
ULONG expected_comm_status = 0;
|
||||
ULONG expected_fault_status = 0;
|
||||
status = NdrMapCommAndFaultStatus(&StubMsg, &comm_status, &fault_status, rpc_status);
|
||||
ok(status == RPC_S_OK, "NdrMapCommAndFaultStatus failed with error %ld\n", status);
|
||||
switch (rpc_status)
|
||||
{
|
||||
case ERROR_INVALID_HANDLE:
|
||||
case RPC_S_INVALID_BINDING:
|
||||
case RPC_S_UNKNOWN_IF:
|
||||
case RPC_S_SERVER_UNAVAILABLE:
|
||||
case RPC_S_SERVER_TOO_BUSY:
|
||||
case RPC_S_CALL_FAILED_DNE:
|
||||
case RPC_S_PROTOCOL_ERROR:
|
||||
case RPC_S_UNSUPPORTED_TRANS_SYN:
|
||||
case RPC_S_UNSUPPORTED_TYPE:
|
||||
case RPC_S_PROCNUM_OUT_OF_RANGE:
|
||||
case EPT_S_NOT_REGISTERED:
|
||||
case RPC_S_COMM_FAILURE:
|
||||
expected_comm_status = rpc_status;
|
||||
break;
|
||||
default:
|
||||
expected_fault_status = rpc_status;
|
||||
}
|
||||
ok(comm_status == expected_comm_status, "NdrMapCommAndFaultStatus should have mapped %ld to comm status %d instead of %d\n",
|
||||
rpc_status, expected_comm_status, comm_status);
|
||||
ok(fault_status == expected_fault_status, "NdrMapCommAndFaultStatus should have mapped %ld to fault status %d instead of %d\n",
|
||||
rpc_status, expected_fault_status, fault_status);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST( ndr_marshall )
|
||||
{
|
||||
test_ndr_simple_type();
|
||||
test_simple_types();
|
||||
test_nontrivial_pointer_types();
|
||||
test_simple_struct();
|
||||
test_fullpointer_xlat();
|
||||
test_client_init();
|
||||
@@ -1521,4 +1827,6 @@ START_TEST( ndr_marshall )
|
||||
test_conformant_array();
|
||||
test_conformant_string();
|
||||
test_nonconformant_string();
|
||||
test_ndr_buffer();
|
||||
test_NdrMapCommAndFaultStatus();
|
||||
}
|
||||
|
||||
@@ -21,11 +21,14 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ntstatus.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include "wine/test.h"
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winnt.h>
|
||||
#include <winerror.h>
|
||||
#include <ntdef.h>
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rpcdce.h"
|
||||
@@ -110,6 +113,7 @@ static void UuidConversionAndComparison(void) {
|
||||
ok( (UuidFromStringA((unsigned char*)str, &Uuid1) == RPC_S_INVALID_STRING_UUID), "Invalid UUID String\n" );
|
||||
str[i2] = x; /* change it back so remaining tests are interesting. */
|
||||
}
|
||||
RpcStringFree((unsigned char **)&str);
|
||||
}
|
||||
|
||||
/* Uuid to String to Uuid (wchar) */
|
||||
@@ -130,6 +134,7 @@ static void UuidConversionAndComparison(void) {
|
||||
ok( (UuidFromStringW(wstr, &Uuid1) == RPC_S_INVALID_STRING_UUID), "Invalid UUID WString\n" );
|
||||
wstr[i2] = wx; /* change it back so remaining tests are interesting. */
|
||||
}
|
||||
RpcStringFreeW(&wstr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,6 +326,12 @@ static void test_towers(void)
|
||||
|
||||
ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_ip_tcp", "135", "10.0.0.1", &tower);
|
||||
ok(ret == RPC_S_OK, "TowerConstruct failed with error %ld\n", ret);
|
||||
if (ret == RPC_S_INVALID_RPC_PROTSEQ)
|
||||
{
|
||||
/* Windows Vista fails with this error and crashes if we continue */
|
||||
skip("TowerConstruct failed, we are most likely on Windows Vista\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* first check we have the right amount of data */
|
||||
ok(tower->tower_length == sizeof(tower_data_tcp_ip1) ||
|
||||
@@ -372,6 +383,272 @@ static void test_towers(void)
|
||||
|
||||
I_RpcFree(address);
|
||||
I_RpcFree(tower);
|
||||
|
||||
/* test the behaviour for np with no address */
|
||||
ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_np", "\\pipe\\test", NULL, &tower);
|
||||
ok(ret == RPC_S_OK, "TowerConstruct failed with error %ld\n", ret);
|
||||
ret = TowerExplode(tower, NULL, NULL, NULL, NULL, &address);
|
||||
ok(ret == RPC_S_OK, "TowerExplode failed with error %ld\n", ret);
|
||||
/* Windows XP SP3 sets address to NULL */
|
||||
ok(!address || !strcmp(address, ""), "address was \"%s\" instead of \"\"\n or NULL (XP SP3)", address);
|
||||
|
||||
I_RpcFree(address);
|
||||
I_RpcFree(tower);
|
||||
}
|
||||
|
||||
static void test_I_RpcMapWin32Status(void)
|
||||
{
|
||||
LONG win32status;
|
||||
RPC_STATUS rpc_status;
|
||||
BOOL w2k3_up = FALSE;
|
||||
|
||||
/* Windows 2003 and Vista return STATUS_UNSUCCESSFUL if given an unknown status */
|
||||
win32status = I_RpcMapWin32Status(9999);
|
||||
if (win32status == STATUS_UNSUCCESSFUL)
|
||||
{
|
||||
trace("We are on Windows 2003 or Vista\n");
|
||||
w2k3_up = TRUE;
|
||||
}
|
||||
|
||||
for (rpc_status = 0; rpc_status < 10000; rpc_status++)
|
||||
{
|
||||
LONG expected_win32status;
|
||||
win32status = I_RpcMapWin32Status(rpc_status);
|
||||
switch (rpc_status)
|
||||
{
|
||||
case ERROR_SUCCESS: expected_win32status = ERROR_SUCCESS; break;
|
||||
case ERROR_ACCESS_DENIED: expected_win32status = STATUS_ACCESS_DENIED; break;
|
||||
case ERROR_INVALID_HANDLE: expected_win32status = RPC_NT_SS_CONTEXT_MISMATCH; break;
|
||||
case ERROR_OUTOFMEMORY: expected_win32status = STATUS_NO_MEMORY; break;
|
||||
case ERROR_INVALID_PARAMETER: expected_win32status = STATUS_INVALID_PARAMETER; break;
|
||||
case ERROR_INSUFFICIENT_BUFFER: expected_win32status = STATUS_BUFFER_TOO_SMALL; break;
|
||||
case ERROR_MAX_THRDS_REACHED: expected_win32status = STATUS_NO_MEMORY; break;
|
||||
case ERROR_NOACCESS: expected_win32status = STATUS_ACCESS_VIOLATION; break;
|
||||
case ERROR_NOT_ENOUGH_SERVER_MEMORY: expected_win32status = STATUS_INSUFF_SERVER_RESOURCES; break;
|
||||
case ERROR_WRONG_PASSWORD: expected_win32status = STATUS_WRONG_PASSWORD; break;
|
||||
case ERROR_INVALID_LOGON_HOURS: expected_win32status = STATUS_INVALID_LOGON_HOURS; break;
|
||||
case ERROR_PASSWORD_EXPIRED: expected_win32status = STATUS_PASSWORD_EXPIRED; break;
|
||||
case ERROR_ACCOUNT_DISABLED: expected_win32status = STATUS_ACCOUNT_DISABLED; break;
|
||||
case ERROR_INVALID_SECURITY_DESCR: expected_win32status = STATUS_INVALID_SECURITY_DESCR; break;
|
||||
case RPC_S_INVALID_STRING_BINDING: expected_win32status = RPC_NT_INVALID_STRING_BINDING; break;
|
||||
case RPC_S_WRONG_KIND_OF_BINDING: expected_win32status = RPC_NT_WRONG_KIND_OF_BINDING; break;
|
||||
case RPC_S_INVALID_BINDING: expected_win32status = RPC_NT_INVALID_BINDING; break;
|
||||
case RPC_S_PROTSEQ_NOT_SUPPORTED: expected_win32status = RPC_NT_PROTSEQ_NOT_SUPPORTED; break;
|
||||
case RPC_S_INVALID_RPC_PROTSEQ: expected_win32status = RPC_NT_INVALID_RPC_PROTSEQ; break;
|
||||
case RPC_S_INVALID_STRING_UUID: expected_win32status = RPC_NT_INVALID_STRING_UUID; break;
|
||||
case RPC_S_INVALID_ENDPOINT_FORMAT: expected_win32status = RPC_NT_INVALID_ENDPOINT_FORMAT; break;
|
||||
case RPC_S_INVALID_NET_ADDR: expected_win32status = RPC_NT_INVALID_NET_ADDR; break;
|
||||
case RPC_S_NO_ENDPOINT_FOUND: expected_win32status = RPC_NT_NO_ENDPOINT_FOUND; break;
|
||||
case RPC_S_INVALID_TIMEOUT: expected_win32status = RPC_NT_INVALID_TIMEOUT; break;
|
||||
case RPC_S_OBJECT_NOT_FOUND: expected_win32status = RPC_NT_OBJECT_NOT_FOUND; break;
|
||||
case RPC_S_ALREADY_REGISTERED: expected_win32status = RPC_NT_ALREADY_REGISTERED; break;
|
||||
case RPC_S_TYPE_ALREADY_REGISTERED: expected_win32status = RPC_NT_TYPE_ALREADY_REGISTERED; break;
|
||||
case RPC_S_ALREADY_LISTENING: expected_win32status = RPC_NT_ALREADY_LISTENING; break;
|
||||
case RPC_S_NO_PROTSEQS_REGISTERED: expected_win32status = RPC_NT_NO_PROTSEQS_REGISTERED; break;
|
||||
case RPC_S_NOT_LISTENING: expected_win32status = RPC_NT_NOT_LISTENING; break;
|
||||
case RPC_S_UNKNOWN_MGR_TYPE: expected_win32status = RPC_NT_UNKNOWN_MGR_TYPE; break;
|
||||
case RPC_S_UNKNOWN_IF: expected_win32status = RPC_NT_UNKNOWN_IF; break;
|
||||
case RPC_S_NO_BINDINGS: expected_win32status = RPC_NT_NO_BINDINGS; break;
|
||||
case RPC_S_NO_PROTSEQS: expected_win32status = RPC_NT_NO_PROTSEQS; break;
|
||||
case RPC_S_CANT_CREATE_ENDPOINT: expected_win32status = RPC_NT_CANT_CREATE_ENDPOINT; break;
|
||||
case RPC_S_OUT_OF_RESOURCES: expected_win32status = RPC_NT_OUT_OF_RESOURCES; break;
|
||||
case RPC_S_SERVER_UNAVAILABLE: expected_win32status = RPC_NT_SERVER_UNAVAILABLE; break;
|
||||
case RPC_S_SERVER_TOO_BUSY: expected_win32status = RPC_NT_SERVER_TOO_BUSY; break;
|
||||
case RPC_S_INVALID_NETWORK_OPTIONS: expected_win32status = RPC_NT_INVALID_NETWORK_OPTIONS; break;
|
||||
case RPC_S_NO_CALL_ACTIVE: expected_win32status = RPC_NT_NO_CALL_ACTIVE; break;
|
||||
case RPC_S_CALL_FAILED: expected_win32status = RPC_NT_CALL_FAILED; break;
|
||||
case RPC_S_CALL_FAILED_DNE: expected_win32status = RPC_NT_CALL_FAILED_DNE; break;
|
||||
case RPC_S_PROTOCOL_ERROR: expected_win32status = RPC_NT_PROTOCOL_ERROR; break;
|
||||
case RPC_S_UNSUPPORTED_TRANS_SYN: expected_win32status = RPC_NT_UNSUPPORTED_TRANS_SYN; break;
|
||||
case RPC_S_UNSUPPORTED_TYPE: expected_win32status = RPC_NT_UNSUPPORTED_TYPE; break;
|
||||
case RPC_S_INVALID_TAG: expected_win32status = RPC_NT_INVALID_TAG; break;
|
||||
case RPC_S_INVALID_BOUND: expected_win32status = RPC_NT_INVALID_BOUND; break;
|
||||
case RPC_S_NO_ENTRY_NAME: expected_win32status = RPC_NT_NO_ENTRY_NAME; break;
|
||||
case RPC_S_INVALID_NAME_SYNTAX: expected_win32status = RPC_NT_INVALID_NAME_SYNTAX; break;
|
||||
case RPC_S_UNSUPPORTED_NAME_SYNTAX: expected_win32status = RPC_NT_UNSUPPORTED_NAME_SYNTAX; break;
|
||||
case RPC_S_UUID_NO_ADDRESS: expected_win32status = RPC_NT_UUID_NO_ADDRESS; break;
|
||||
case RPC_S_DUPLICATE_ENDPOINT: expected_win32status = RPC_NT_DUPLICATE_ENDPOINT; break;
|
||||
case RPC_S_UNKNOWN_AUTHN_TYPE: expected_win32status = RPC_NT_UNKNOWN_AUTHN_TYPE; break;
|
||||
case RPC_S_MAX_CALLS_TOO_SMALL: expected_win32status = RPC_NT_MAX_CALLS_TOO_SMALL; break;
|
||||
case RPC_S_STRING_TOO_LONG: expected_win32status = RPC_NT_STRING_TOO_LONG; break;
|
||||
case RPC_S_PROTSEQ_NOT_FOUND: expected_win32status = RPC_NT_PROTSEQ_NOT_FOUND; break;
|
||||
case RPC_S_PROCNUM_OUT_OF_RANGE: expected_win32status = RPC_NT_PROCNUM_OUT_OF_RANGE; break;
|
||||
case RPC_S_BINDING_HAS_NO_AUTH: expected_win32status = RPC_NT_BINDING_HAS_NO_AUTH; break;
|
||||
case RPC_S_UNKNOWN_AUTHN_SERVICE: expected_win32status = RPC_NT_UNKNOWN_AUTHN_SERVICE; break;
|
||||
case RPC_S_UNKNOWN_AUTHN_LEVEL: expected_win32status = RPC_NT_UNKNOWN_AUTHN_LEVEL; break;
|
||||
case RPC_S_INVALID_AUTH_IDENTITY: expected_win32status = RPC_NT_INVALID_AUTH_IDENTITY; break;
|
||||
case RPC_S_UNKNOWN_AUTHZ_SERVICE: expected_win32status = RPC_NT_UNKNOWN_AUTHZ_SERVICE; break;
|
||||
case EPT_S_INVALID_ENTRY: expected_win32status = EPT_NT_INVALID_ENTRY; break;
|
||||
case EPT_S_CANT_PERFORM_OP: expected_win32status = EPT_NT_CANT_PERFORM_OP; break;
|
||||
case EPT_S_NOT_REGISTERED: expected_win32status = EPT_NT_NOT_REGISTERED; break;
|
||||
case EPT_S_CANT_CREATE: expected_win32status = EPT_NT_CANT_CREATE; break;
|
||||
case RPC_S_NOTHING_TO_EXPORT: expected_win32status = RPC_NT_NOTHING_TO_EXPORT; break;
|
||||
case RPC_S_INCOMPLETE_NAME: expected_win32status = RPC_NT_INCOMPLETE_NAME; break;
|
||||
case RPC_S_INVALID_VERS_OPTION: expected_win32status = RPC_NT_INVALID_VERS_OPTION; break;
|
||||
case RPC_S_NO_MORE_MEMBERS: expected_win32status = RPC_NT_NO_MORE_MEMBERS; break;
|
||||
case RPC_S_NOT_ALL_OBJS_UNEXPORTED: expected_win32status = RPC_NT_NOT_ALL_OBJS_UNEXPORTED; break;
|
||||
case RPC_S_INTERFACE_NOT_FOUND: expected_win32status = RPC_NT_INTERFACE_NOT_FOUND; break;
|
||||
case RPC_S_ENTRY_ALREADY_EXISTS: expected_win32status = RPC_NT_ENTRY_ALREADY_EXISTS; break;
|
||||
case RPC_S_ENTRY_NOT_FOUND: expected_win32status = RPC_NT_ENTRY_NOT_FOUND; break;
|
||||
case RPC_S_NAME_SERVICE_UNAVAILABLE: expected_win32status = RPC_NT_NAME_SERVICE_UNAVAILABLE; break;
|
||||
case RPC_S_INVALID_NAF_ID: expected_win32status = RPC_NT_INVALID_NAF_ID; break;
|
||||
case RPC_S_CANNOT_SUPPORT: expected_win32status = RPC_NT_CANNOT_SUPPORT; break;
|
||||
case RPC_S_NO_CONTEXT_AVAILABLE: expected_win32status = RPC_NT_NO_CONTEXT_AVAILABLE; break;
|
||||
case RPC_S_INTERNAL_ERROR: expected_win32status = RPC_NT_INTERNAL_ERROR; break;
|
||||
case RPC_S_ZERO_DIVIDE: expected_win32status = RPC_NT_ZERO_DIVIDE; break;
|
||||
case RPC_S_ADDRESS_ERROR: expected_win32status = RPC_NT_ADDRESS_ERROR; break;
|
||||
case RPC_S_FP_DIV_ZERO: expected_win32status = RPC_NT_FP_DIV_ZERO; break;
|
||||
case RPC_S_FP_UNDERFLOW: expected_win32status = RPC_NT_FP_UNDERFLOW; break;
|
||||
case RPC_S_FP_OVERFLOW: expected_win32status = RPC_NT_FP_OVERFLOW; break;
|
||||
case RPC_S_CALL_IN_PROGRESS: expected_win32status = RPC_NT_CALL_IN_PROGRESS; break;
|
||||
case RPC_S_NO_MORE_BINDINGS: expected_win32status = RPC_NT_NO_MORE_BINDINGS; break;
|
||||
case RPC_S_CALL_CANCELLED: expected_win32status = RPC_NT_CALL_CANCELLED; break;
|
||||
case RPC_S_INVALID_OBJECT: expected_win32status = RPC_NT_INVALID_OBJECT; break;
|
||||
case RPC_S_INVALID_ASYNC_HANDLE: expected_win32status = RPC_NT_INVALID_ASYNC_HANDLE; break;
|
||||
case RPC_S_INVALID_ASYNC_CALL: expected_win32status = RPC_NT_INVALID_ASYNC_CALL; break;
|
||||
case RPC_S_GROUP_MEMBER_NOT_FOUND: expected_win32status = RPC_NT_GROUP_MEMBER_NOT_FOUND; break;
|
||||
case RPC_X_NO_MORE_ENTRIES: expected_win32status = RPC_NT_NO_MORE_ENTRIES; break;
|
||||
case RPC_X_SS_CHAR_TRANS_OPEN_FAIL: expected_win32status = RPC_NT_SS_CHAR_TRANS_OPEN_FAIL; break;
|
||||
case RPC_X_SS_CHAR_TRANS_SHORT_FILE: expected_win32status = RPC_NT_SS_CHAR_TRANS_SHORT_FILE; break;
|
||||
case RPC_X_SS_IN_NULL_CONTEXT: expected_win32status = RPC_NT_SS_IN_NULL_CONTEXT; break;
|
||||
case RPC_X_SS_CONTEXT_DAMAGED: expected_win32status = RPC_NT_SS_CONTEXT_DAMAGED; break;
|
||||
case RPC_X_SS_HANDLES_MISMATCH: expected_win32status = RPC_NT_SS_HANDLES_MISMATCH; break;
|
||||
case RPC_X_SS_CANNOT_GET_CALL_HANDLE: expected_win32status = RPC_NT_SS_CANNOT_GET_CALL_HANDLE; break;
|
||||
case RPC_X_NULL_REF_POINTER: expected_win32status = RPC_NT_NULL_REF_POINTER; break;
|
||||
case RPC_X_ENUM_VALUE_OUT_OF_RANGE: expected_win32status = RPC_NT_ENUM_VALUE_OUT_OF_RANGE; break;
|
||||
case RPC_X_BYTE_COUNT_TOO_SMALL: expected_win32status = RPC_NT_BYTE_COUNT_TOO_SMALL; break;
|
||||
case RPC_X_BAD_STUB_DATA: expected_win32status = RPC_NT_BAD_STUB_DATA; break;
|
||||
case RPC_X_PIPE_CLOSED: expected_win32status = RPC_NT_PIPE_CLOSED; break;
|
||||
case RPC_X_PIPE_DISCIPLINE_ERROR: expected_win32status = RPC_NT_PIPE_DISCIPLINE_ERROR; break;
|
||||
case RPC_X_PIPE_EMPTY: expected_win32status = RPC_NT_PIPE_EMPTY; break;
|
||||
case ERROR_PASSWORD_MUST_CHANGE: expected_win32status = STATUS_PASSWORD_MUST_CHANGE; break;
|
||||
case ERROR_ACCOUNT_LOCKED_OUT: expected_win32status = STATUS_ACCOUNT_LOCKED_OUT; break;
|
||||
default:
|
||||
if (w2k3_up)
|
||||
expected_win32status = STATUS_UNSUCCESSFUL;
|
||||
else
|
||||
expected_win32status = rpc_status;
|
||||
}
|
||||
ok(win32status == expected_win32status, "I_RpcMapWin32Status(%ld) should have returned 0x%x instead of 0x%x\n",
|
||||
rpc_status, expected_win32status, win32status);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_RpcStringBindingParseA(void)
|
||||
{
|
||||
static unsigned char valid_binding[] = "00000000-0000-0000-c000-000000000046@ncacn_np:.[endpoint=\\pipe\\test]";
|
||||
static unsigned char valid_binding2[] = "00000000-0000-0000-c000-000000000046@ncacn_np:.[\\pipe\\test]";
|
||||
static unsigned char invalid_uuid_binding[] = "{00000000-0000-0000-c000-000000000046}@ncacn_np:.[endpoint=\\pipe\\test]";
|
||||
static unsigned char invalid_ep_binding[] = "00000000-0000-0000-c000-000000000046@ncacn_np:.[endpoint=test]";
|
||||
static unsigned char invalid_binding[] = "00000000-0000-0000-c000-000000000046@ncacn_np";
|
||||
RPC_STATUS status;
|
||||
unsigned char *uuid;
|
||||
unsigned char *protseq;
|
||||
unsigned char *network_addr;
|
||||
unsigned char *endpoint;
|
||||
unsigned char *options;
|
||||
|
||||
/* test all parameters */
|
||||
status = RpcStringBindingParseA(valid_binding, &uuid, &protseq, &network_addr, &endpoint, &options);
|
||||
ok(status == RPC_S_OK, "RpcStringBindingParseA failed with error %ld\n", status);
|
||||
ok(!strcmp((char *)uuid, "00000000-0000-0000-c000-000000000046"), "uuid should have been 00000000-0000-0000-C000-000000000046 instead of %s\n", uuid);
|
||||
ok(!strcmp((char *)protseq, "ncacn_np"), "protseq should have been ncacn_np instead of %s\n", protseq);
|
||||
ok(!strcmp((char *)network_addr, "."), "network_addr should have been . instead of %s\n", network_addr);
|
||||
todo_wine
|
||||
ok(!strcmp((char *)endpoint, "pipetest"), "endpoint should have been pipetest instead of %s\n", endpoint);
|
||||
todo_wine
|
||||
ok(options && !strcmp((char *)options, ""), "options should have been \"\" of \"%s\"\n", options);
|
||||
RpcStringFreeA(&uuid);
|
||||
RpcStringFreeA(&protseq);
|
||||
RpcStringFreeA(&network_addr);
|
||||
RpcStringFreeA(&endpoint);
|
||||
RpcStringFreeA(&options);
|
||||
|
||||
/* test all parameters with different type of string binding */
|
||||
status = RpcStringBindingParseA(valid_binding2, &uuid, &protseq, &network_addr, &endpoint, &options);
|
||||
ok(status == RPC_S_OK, "RpcStringBindingParseA failed with error %ld\n", status);
|
||||
ok(!strcmp((char *)uuid, "00000000-0000-0000-c000-000000000046"), "uuid should have been 00000000-0000-0000-C000-000000000046 instead of %s\n", uuid);
|
||||
ok(!strcmp((char *)protseq, "ncacn_np"), "protseq should have been ncacn_np instead of %s\n", protseq);
|
||||
ok(!strcmp((char *)network_addr, "."), "network_addr should have been . instead of %s\n", network_addr);
|
||||
todo_wine
|
||||
ok(!strcmp((char *)endpoint, "pipetest"), "endpoint should have been pipetest instead of %s\n", endpoint);
|
||||
todo_wine
|
||||
ok(options && !strcmp((char *)options, ""), "options should have been \"\" of \"%s\"\n", options);
|
||||
RpcStringFreeA(&uuid);
|
||||
RpcStringFreeA(&protseq);
|
||||
RpcStringFreeA(&network_addr);
|
||||
RpcStringFreeA(&endpoint);
|
||||
RpcStringFreeA(&options);
|
||||
|
||||
/* test with as many parameters NULL as possible */
|
||||
status = RpcStringBindingParseA(valid_binding, NULL, &protseq, NULL, NULL, NULL);
|
||||
ok(status == RPC_S_OK, "RpcStringBindingParseA failed with error %ld\n", status);
|
||||
ok(!strcmp((char *)protseq, "ncacn_np"), "protseq should have been ncacn_np instead of %s\n", protseq);
|
||||
RpcStringFreeA(&protseq);
|
||||
|
||||
/* test with invalid uuid */
|
||||
status = RpcStringBindingParseA(invalid_uuid_binding, NULL, &protseq, NULL, NULL, NULL);
|
||||
todo_wine
|
||||
ok(status == RPC_S_INVALID_STRING_UUID, "RpcStringBindingParseA should have returned RPC_S_INVALID_STRING_UUID instead of %ld\n", status);
|
||||
todo_wine
|
||||
ok(protseq == NULL, "protseq was %p instead of NULL\n", protseq);
|
||||
|
||||
/* test with invalid endpoint */
|
||||
status = RpcStringBindingParseA(invalid_ep_binding, NULL, &protseq, NULL, NULL, NULL);
|
||||
ok(status == RPC_S_OK, "RpcStringBindingParseA failed with error %ld\n", status);
|
||||
RpcStringFreeA(&protseq);
|
||||
|
||||
/* test with invalid binding */
|
||||
status = RpcStringBindingParseA(invalid_binding, &uuid, &protseq, &network_addr, &endpoint, &options);
|
||||
todo_wine
|
||||
ok(status == RPC_S_INVALID_STRING_BINDING, "RpcStringBindingParseA should have returned RPC_S_INVALID_STRING_BINDING instead of %ld\n", status);
|
||||
todo_wine
|
||||
ok(uuid == NULL, "uuid was %p instead of NULL\n", uuid);
|
||||
ok(protseq == NULL, "protseq was %p instead of NULL\n", protseq);
|
||||
todo_wine
|
||||
ok(network_addr == NULL, "network_addr was %p instead of NULL\n", network_addr);
|
||||
ok(endpoint == NULL, "endpoint was %p instead of NULL\n", endpoint);
|
||||
ok(options == NULL, "options was %p instead of NULL\n", options);
|
||||
}
|
||||
|
||||
static void test_I_RpcExceptionFilter(void)
|
||||
{
|
||||
ULONG exception;
|
||||
int retval;
|
||||
int (WINAPI *pI_RpcExceptionFilter)(ULONG) = (void *)GetProcAddress(GetModuleHandle("rpcrt4.dll"), "I_RpcExceptionFilter");
|
||||
|
||||
if (!pI_RpcExceptionFilter)
|
||||
{
|
||||
skip("I_RpcExceptionFilter not exported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (exception = 0; exception < STATUS_REG_NAT_CONSUMPTION; exception++)
|
||||
{
|
||||
/* skip over uninteresting bits of the number space */
|
||||
if (exception == 2000) exception = 0x40000000;
|
||||
if (exception == 0x40000005) exception = 0x80000000;
|
||||
if (exception == 0x80000005) exception = 0xc0000000;
|
||||
|
||||
retval = pI_RpcExceptionFilter(exception);
|
||||
switch (exception)
|
||||
{
|
||||
case STATUS_DATATYPE_MISALIGNMENT:
|
||||
case STATUS_BREAKPOINT:
|
||||
case STATUS_ACCESS_VIOLATION:
|
||||
case STATUS_ILLEGAL_INSTRUCTION:
|
||||
case STATUS_PRIVILEGED_INSTRUCTION:
|
||||
case 0xc00000aa /* STATUS_INSTRUCTION_MISALIGNMENT */:
|
||||
case STATUS_STACK_OVERFLOW:
|
||||
case 0xc0000194 /* STATUS_POSSIBLE_DEADLOCK */:
|
||||
ok(retval == EXCEPTION_CONTINUE_SEARCH, "I_RpcExceptionFilter(0x%x) should have returned %d instead of %d\n",
|
||||
exception, EXCEPTION_CONTINUE_SEARCH, retval);
|
||||
break;
|
||||
default:
|
||||
ok(retval == EXCEPTION_EXECUTE_HANDLER, "I_RpcExceptionFilter(0x%x) should have returned %d instead of %d\n",
|
||||
exception, EXCEPTION_EXECUTE_HANDLER, retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST( rpc )
|
||||
@@ -382,4 +659,7 @@ START_TEST( rpc )
|
||||
TestDceErrorInqText();
|
||||
test_rpc_ncacn_ip_tcp();
|
||||
test_towers();
|
||||
test_I_RpcMapWin32Status();
|
||||
test_RpcStringBindingParseA();
|
||||
test_I_RpcExceptionFilter();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Unit test suite for rpc functions
|
||||
*
|
||||
* Copyright 2008 Robert Shearman (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 <rpc.h>
|
||||
#include <rpcasync.h>
|
||||
|
||||
RPC_STATUS (RPC_ENTRY *pRpcAsyncInitializeHandle)(PRPC_ASYNC_STATE,unsigned int);
|
||||
RPC_STATUS (RPC_ENTRY *pRpcAsyncGetCallStatus)(PRPC_ASYNC_STATE);
|
||||
|
||||
static void test_RpcAsyncInitializeHandle(void)
|
||||
{
|
||||
char buffer[256];
|
||||
RPC_ASYNC_STATE async;
|
||||
RPC_STATUS status;
|
||||
int i;
|
||||
|
||||
status = pRpcAsyncInitializeHandle((PRPC_ASYNC_STATE)buffer, sizeof(buffer));
|
||||
ok(status == ERROR_INVALID_PARAMETER, "RpcAsyncInitializeHandle with large Size should have returned ERROR_INVALID_PARAMETER instead of %ld\n", status);
|
||||
|
||||
status = pRpcAsyncInitializeHandle(&async, sizeof(async) - 1);
|
||||
ok(status == ERROR_INVALID_PARAMETER, "RpcAsyncInitializeHandle with small Size should have returned ERROR_INVALID_PARAMETER instead of %ld\n", status);
|
||||
|
||||
memset(&async, 0xcc, sizeof(async));
|
||||
status = pRpcAsyncInitializeHandle(&async, sizeof(async));
|
||||
ok(status == RPC_S_OK, "RpcAsyncInitializeHandle failed with error %ld\n", status);
|
||||
|
||||
ok(async.Size == sizeof(async), "async.Size wrong: %d\n", async.Size);
|
||||
ok(async.Signature == 0x43595341, "async.Signature should be 0x43595341, but is 0x%x instead\n", async.Signature);
|
||||
ok(async.Lock == 0, "async.Lock should be 0, but is %d instead\n", async.Lock);
|
||||
ok(async.Flags == 0, "async.Flags should be 0, but is %d instead\n", async.Flags);
|
||||
ok(async.StubInfo == NULL, "async.StubInfo should be NULL, not %p\n", async.StubInfo);
|
||||
ok(async.UserInfo == (void *)0xcccccccc, "async.UserInfo should be unset, not %p\n", async.UserInfo);
|
||||
ok(async.RuntimeInfo == NULL, "async.RuntimeInfo should be NULL, not %p\n", async.RuntimeInfo);
|
||||
ok(async.Event == 0xcccccccc, "async.Event should be unset, not %d\n", async.Event);
|
||||
ok(async.NotificationType == 0xcccccccc, "async.NotificationType should be unset, not %d\n", async.NotificationType);
|
||||
for (i = 0; i < 4; i++)
|
||||
ok(async.Reserved[i] == 0x0, "async.Reserved[%d] should be 0x0, not 0x%lx\n", i, async.Reserved[i]);
|
||||
}
|
||||
|
||||
static void test_RpcAsyncGetCallStatus(void)
|
||||
{
|
||||
RPC_ASYNC_STATE async;
|
||||
RPC_STATUS status;
|
||||
|
||||
status = pRpcAsyncInitializeHandle(&async, sizeof(async));
|
||||
ok(status == RPC_S_OK, "RpcAsyncInitializeHandle failed with error %ld\n", status);
|
||||
|
||||
status = pRpcAsyncGetCallStatus(&async);
|
||||
todo_wine
|
||||
ok(status == RPC_S_INVALID_BINDING, "RpcAsyncGetCallStatus should have returned RPC_S_INVALID_BINDING instead of %ld\n", status);
|
||||
|
||||
memset(&async, 0, sizeof(async));
|
||||
status = pRpcAsyncGetCallStatus(&async);
|
||||
todo_wine
|
||||
ok(status == RPC_S_INVALID_BINDING, "RpcAsyncGetCallStatus should have returned RPC_S_INVALID_BINDING instead of %ld\n", status);
|
||||
}
|
||||
|
||||
START_TEST( rpc_async )
|
||||
{
|
||||
HMODULE hRpcRt4 = GetModuleHandle("rpcrt4.dll");
|
||||
pRpcAsyncInitializeHandle = (void *)GetProcAddress(hRpcRt4, "RpcAsyncInitializeHandle");
|
||||
pRpcAsyncGetCallStatus = (void *)GetProcAddress(hRpcRt4, "RpcAsyncGetCallStatus");
|
||||
if (!pRpcAsyncInitializeHandle || !pRpcAsyncGetCallStatus)
|
||||
{
|
||||
skip("asynchronous functions not available\n");
|
||||
return;
|
||||
}
|
||||
test_RpcAsyncInitializeHandle();
|
||||
test_RpcAsyncGetCallStatus();
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
<file>generated.c</file>
|
||||
<file>ndr_marshall.c</file>
|
||||
<file>rpc.c</file>
|
||||
<file>rpc_async.c</file>
|
||||
<file>server.c</file>
|
||||
<file>testlist.c</file>
|
||||
</module>
|
||||
</module>
|
||||
|
||||
@@ -36,6 +36,17 @@ static const char *progname;
|
||||
|
||||
static HANDLE stop_event;
|
||||
|
||||
static void (WINAPI *pNDRSContextMarshall2)(RPC_BINDING_HANDLE, NDR_SCONTEXT, void*, NDR_RUNDOWN, void*, ULONG);
|
||||
static NDR_SCONTEXT (WINAPI *pNDRSContextUnmarshall2)(RPC_BINDING_HANDLE, void*, ULONG, void*, ULONG);
|
||||
|
||||
static void InitFunctionPointers(void)
|
||||
{
|
||||
HMODULE hrpcrt4 = GetModuleHandleA("rpcrt4.dll");
|
||||
|
||||
pNDRSContextMarshall2 = (void *)GetProcAddress(hrpcrt4, "NDRSContextMarshall2");
|
||||
pNDRSContextUnmarshall2 = (void *)GetProcAddress(hrpcrt4, "NDRSContextUnmarshall2");
|
||||
}
|
||||
|
||||
void __RPC_FAR *__RPC_USER
|
||||
midl_user_allocate(size_t n)
|
||||
{
|
||||
@@ -92,6 +103,12 @@ s_str_length(const char *s)
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
int
|
||||
s_str_t_length(str_t s)
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
int
|
||||
s_cstr_length(const char *s, int n)
|
||||
{
|
||||
@@ -316,10 +333,10 @@ s_square_encu(encu_t *eu)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
s_sum_parr(int *a[3])
|
||||
void
|
||||
s_check_se2(se_t *s)
|
||||
{
|
||||
return s_sum_pcarr(a, 3);
|
||||
ok(s->f == E2, "check_se2\n");
|
||||
}
|
||||
|
||||
int
|
||||
@@ -331,6 +348,12 @@ s_sum_pcarr(int *a[], int n)
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
s_sum_parr(int *a[3])
|
||||
{
|
||||
return s_sum_pcarr(a, 3);
|
||||
}
|
||||
|
||||
int
|
||||
s_enum_ord(e_t e)
|
||||
{
|
||||
@@ -497,6 +520,16 @@ s_sum_L1_norms(int n, vector_t *vs)
|
||||
return sum;
|
||||
}
|
||||
|
||||
s123_t *
|
||||
s_get_s123(void)
|
||||
{
|
||||
s123_t *s = MIDL_user_allocate(sizeof *s);
|
||||
s->f1 = 1;
|
||||
s->f2 = 2;
|
||||
s->f3 = 3;
|
||||
return s;
|
||||
}
|
||||
|
||||
str_t
|
||||
s_get_filename(void)
|
||||
{
|
||||
@@ -526,40 +559,40 @@ s_context_handle_test(void)
|
||||
binding = I_RpcGetCurrentCallHandle();
|
||||
ok(binding != NULL, "I_RpcGetCurrentCallHandle returned NULL\n");
|
||||
|
||||
h = NDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0);
|
||||
h = pNDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0);
|
||||
ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n");
|
||||
|
||||
/* marshal a context handle with NULL userContext */
|
||||
memset(buf, 0xcc, sizeof(buf));
|
||||
NDRSContextMarshall2(binding, h, buf, NULL, NULL, 0);
|
||||
pNDRSContextMarshall2(binding, h, buf, NULL, NULL, 0);
|
||||
ok(*(ULONG *)buf == 0, "attributes should have been set to 0 instead of 0x%x\n", *(ULONG *)buf);
|
||||
ok(UuidIsNil((UUID *)&buf[4], &status), "uuid should have been nil\n");
|
||||
|
||||
h = NDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0);
|
||||
h = pNDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0);
|
||||
ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n");
|
||||
|
||||
/* marshal a context handle with non-NULL userContext */
|
||||
memset(buf, 0xcc, sizeof(buf));
|
||||
h->userContext = (void *)0xdeadbeef;
|
||||
NDRSContextMarshall2(binding, h, buf, NULL, NULL, 0);
|
||||
pNDRSContextMarshall2(binding, h, buf, NULL, NULL, 0);
|
||||
ok(*(ULONG *)buf == 0, "attributes should have been set to 0 instead of 0x%x\n", *(ULONG *)buf);
|
||||
ok(!UuidIsNil((UUID *)&buf[4], &status), "uuid should not have been nil\n");
|
||||
|
||||
h = NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0);
|
||||
h = pNDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0);
|
||||
ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n");
|
||||
ok(h->userContext == (void *)0xdeadbeef, "userContext of interface didn't unmarshal properly: %p\n", h->userContext);
|
||||
|
||||
/* marshal a context handle with an interface specified */
|
||||
h = NDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, &server_if.InterfaceId, 0);
|
||||
h = pNDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, &server_if.InterfaceId, 0);
|
||||
ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n");
|
||||
|
||||
memset(buf, 0xcc, sizeof(buf));
|
||||
h->userContext = (void *)0xcafebabe;
|
||||
NDRSContextMarshall2(binding, h, buf, NULL, &server_if.InterfaceId, 0);
|
||||
pNDRSContextMarshall2(binding, h, buf, NULL, &server_if.InterfaceId, 0);
|
||||
ok(*(ULONG *)buf == 0, "attributes should have been set to 0 instead of 0x%x\n", *(ULONG *)buf);
|
||||
ok(!UuidIsNil((UUID *)&buf[4], &status), "uuid should not have been nil\n");
|
||||
|
||||
h = NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if.InterfaceId, 0);
|
||||
h = pNDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if.InterfaceId, 0);
|
||||
ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n");
|
||||
ok(h->userContext == (void *)0xcafebabe, "userContext of interface didn't unmarshal properly: %p\n", h->userContext);
|
||||
|
||||
@@ -569,7 +602,7 @@ s_context_handle_test(void)
|
||||
{
|
||||
RPC_SERVER_INTERFACE server_if_clone = server_if;
|
||||
|
||||
NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if_clone.InterfaceId, 0);
|
||||
pNDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if_clone.InterfaceId, 0);
|
||||
}
|
||||
|
||||
/* test different interface data, but different pointer */
|
||||
@@ -588,9 +621,9 @@ s_context_handle_test(void)
|
||||
0,
|
||||
0,
|
||||
};
|
||||
NDRSContextMarshall2(binding, h, buf, NULL, &server_if.InterfaceId, 0);
|
||||
pNDRSContextMarshall2(binding, h, buf, NULL, &server_if.InterfaceId, 0);
|
||||
|
||||
NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if2.InterfaceId, 0);
|
||||
pNDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if2.InterfaceId, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,25 +667,21 @@ make_cmdline(char buffer[MAX_PATH], const char *test)
|
||||
sprintf(buffer, "%s server %s", progname, test);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
run_client(const char *test)
|
||||
{
|
||||
char cmdline[MAX_PATH];
|
||||
PROCESS_INFORMATION info;
|
||||
STARTUPINFOA startup;
|
||||
DWORD exitcode;
|
||||
|
||||
memset(&startup, 0, sizeof startup);
|
||||
startup.cb = sizeof startup;
|
||||
|
||||
make_cmdline(cmdline, test);
|
||||
ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
ok(GetExitCodeProcess(info.hProcess, &exitcode), "GetExitCodeProcess\n");
|
||||
winetest_wait_child_process( info.hProcess );
|
||||
ok(CloseHandle(info.hProcess), "CloseHandle\n");
|
||||
ok(CloseHandle(info.hThread), "CloseHandle\n");
|
||||
|
||||
return exitcode == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -682,6 +711,7 @@ basic_tests(void)
|
||||
str_struct_t ss = {string};
|
||||
wstr_struct_t ws = {wstring};
|
||||
str_t str;
|
||||
se_t se;
|
||||
|
||||
ok(int_return() == INT_CODE, "RPC int_return\n");
|
||||
|
||||
@@ -697,6 +727,7 @@ basic_tests(void)
|
||||
ok(x == 25, "RPC square_ref\n");
|
||||
|
||||
ok(str_length(string) == strlen(string), "RPC str_length\n");
|
||||
ok(str_t_length(string) == strlen(string), "RPC str_length\n");
|
||||
ok(dot_self(&a) == 59, "RPC dot_self\n");
|
||||
|
||||
ok(str_struct_len(&ss) == lstrlenA(string), "RPC str_struct_len\n");
|
||||
@@ -750,6 +781,9 @@ basic_tests(void)
|
||||
ok(enum_ord(E3) == 3, "RPC enum_ord\n");
|
||||
ok(enum_ord(E4) == 4, "RPC enum_ord\n");
|
||||
|
||||
se.f = E2;
|
||||
check_se2(&se);
|
||||
|
||||
memset(&aligns, 0, sizeof(aligns));
|
||||
aligns.c = 3;
|
||||
aligns.i = 4;
|
||||
@@ -963,6 +997,7 @@ pointer_tests(void)
|
||||
name_t name;
|
||||
void *buffer;
|
||||
int *pa2;
|
||||
s123_t *s123;
|
||||
|
||||
ok(test_list_length(list) == 3, "RPC test_list_length\n");
|
||||
ok(square_puint(p1) == 121, "RPC square_puint\n");
|
||||
@@ -1016,6 +1051,10 @@ pointer_tests(void)
|
||||
|
||||
pa2 = a;
|
||||
ok(sum_pcarr2(4, &pa2) == 10, "RPC sum_pcarr2\n");
|
||||
|
||||
s123 = get_s123();
|
||||
ok(s123->f1 == 1 && s123->f2 == 2 && s123->f3 == 3, "RPC get_s123\n");
|
||||
MIDL_user_free(s123);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1200,22 +1239,38 @@ server(void)
|
||||
static unsigned char port[] = PORT;
|
||||
static unsigned char np[] = "ncacn_np";
|
||||
static unsigned char pipe[] = PIPE;
|
||||
RPC_STATUS status, iptcp_status, np_status;
|
||||
|
||||
ok(RPC_S_OK == RpcServerUseProtseqEp(iptcp, 20, port, NULL), "RpcServerUseProtseqEp\n");
|
||||
//ok(RPC_S_OK == RpcServerRegisterIf(s_IServer_v0_0_s_ifspec, NULL, NULL), "RpcServerRegisterIf\n");
|
||||
ok(RPC_S_OK == RpcServerListen(1, 20, TRUE), "RpcServerListen\n");
|
||||
iptcp_status = RpcServerUseProtseqEp(iptcp, 20, port, NULL);
|
||||
ok(iptcp_status == RPC_S_OK, "RpcServerUseProtseqEp(ncacn_ip_tcp) failed with status %ld\n", iptcp_status);
|
||||
np_status = RpcServerUseProtseqEp(np, 0, pipe, NULL);
|
||||
ok(np_status == RPC_S_OK, "RpcServerUseProtseqEp(ncacn_np) failed with status %ld\n", np_status);
|
||||
|
||||
//status = RpcServerRegisterIf(s_IServer_v0_0_s_ifspec, NULL, NULL);
|
||||
//ok(status == RPC_S_OK, "RpcServerRegisterIf failed with status %ld\n", status);
|
||||
status = RpcServerListen(1, 20, TRUE);
|
||||
ok(status == RPC_S_OK, "RpcServerListen failed with status %ld\n", status);
|
||||
stop_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
ok(stop_event != NULL, "CreateEvent failed\n");
|
||||
ok(stop_event != NULL, "CreateEvent failed with error %d\n", GetLastError());
|
||||
|
||||
ok(run_client("tcp_basic"), "tcp_basic client test failed\n");
|
||||
if (iptcp_status == RPC_S_OK)
|
||||
run_client("tcp_basic");
|
||||
else
|
||||
skip("tcp_basic tests skipped due to earlier failure\n");
|
||||
|
||||
ok(RPC_S_OK == RpcServerUseProtseqEp(np, 0, pipe, NULL), "RpcServerUseProtseqEp\n");
|
||||
ok(run_client("np_basic"), "np_basic client test failed\n");
|
||||
if (np_status == RPC_S_OK)
|
||||
run_client("np_basic");
|
||||
else
|
||||
{
|
||||
skip("np_basic tests skipped due to earlier failure\n");
|
||||
/* np client is what signals stop_event, so bail out if we didn't run do it */
|
||||
return;
|
||||
}
|
||||
|
||||
ok(WAIT_OBJECT_0 == WaitForSingleObject(stop_event, 60000), "WaitForSingleObject\n");
|
||||
status = RpcMgmtWaitServerListen();
|
||||
todo_wine {
|
||||
ok(RPC_S_OK == RpcMgmtWaitServerListen(), "RpcMgmtWaitServerListening\n");
|
||||
ok(status == RPC_S_OK, "RpcMgmtWaitServerListening failed with status %ld\n", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1224,6 +1279,8 @@ START_TEST(server)
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
InitFunctionPointers();
|
||||
|
||||
argc = winetest_get_mainargs(&argv);
|
||||
progname = argv[0];
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ cpp_quote("#endif")
|
||||
void square_out(int x, [out] int *y);
|
||||
void square_ref([in, out] int *x);
|
||||
int str_length([string] const char *s);
|
||||
int str_t_length(str_t s);
|
||||
int cstr_length([string, size_is(n)] const char *s, int n);
|
||||
int dot_self(vector_t *v);
|
||||
double square_half(double x, [out] double *y);
|
||||
@@ -208,11 +209,17 @@ cpp_quote("#endif")
|
||||
case E2: float f2;
|
||||
} encue_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
e_t f;
|
||||
} se_t;
|
||||
|
||||
double square_encu(encu_t *eu);
|
||||
int sum_parr(int *a[3]);
|
||||
int sum_pcarr([size_is(n)] int *a[], int n);
|
||||
int enum_ord(e_t e);
|
||||
double square_encue(encue_t *eue);
|
||||
void check_se2(se_t *s);
|
||||
|
||||
int sum_toplev_conf_2n([size_is(n * 2)] int *x, int n);
|
||||
int sum_toplev_conf_cond([size_is(c ? a : b)] int *x, int a, int b, int c);
|
||||
@@ -300,6 +307,18 @@ cpp_quote("#endif")
|
||||
int sum_pcarr2(int n, [size_is(, n)] int **pa);
|
||||
int sum_L1_norms(int n, [size_is(n)] vector_t *vs);
|
||||
|
||||
/* Don't use this except in the get_s123 test. */
|
||||
typedef struct
|
||||
{
|
||||
int f1;
|
||||
int f2;
|
||||
int f3;
|
||||
} s123_t;
|
||||
|
||||
/* Make sure WIDL generates a type format string for a previously unseen
|
||||
type as a return value. */
|
||||
s123_t *get_s123(void);
|
||||
|
||||
void get_5numbers([in] int count, [out, length_is(count)] pints_t pn[5]);
|
||||
void get_numbers([in] int length, [in] int size, [out, length_is(length), size_is(size)] pints_t pn[]);
|
||||
str_t get_filename(void);
|
||||
|
||||
@@ -10,6 +10,7 @@ extern void func_cstub(void);
|
||||
extern void func_generated(void);
|
||||
extern void func_ndr_marshall(void);
|
||||
extern void func_rpc(void);
|
||||
extern void func_rpc_async(void);
|
||||
extern void func_server(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
@@ -18,6 +19,7 @@ const struct test winetest_testlist[] =
|
||||
{ "generated", func_generated },
|
||||
{ "ndr_marshall", func_ndr_marshall },
|
||||
{ "rpc", func_rpc },
|
||||
{ "rpc_async", func_rpc_async },
|
||||
{ "server", func_server },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="rsabase_winetest" type="win32cui" installbase="bin" installname="rsabase_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="rsabase_winetest" type="win32cui" installbase="bin" installname="rsabase_winetest.exe" allowwarnings="true">
|
||||
<include base="rsabase_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wincrypt.h"
|
||||
#include "winreg.h"
|
||||
|
||||
static HCRYPTPROV hProv;
|
||||
static const char szContainer[] = "winetest";
|
||||
@@ -55,6 +56,33 @@ static const cryptdata cTestData[4] = {
|
||||
12,12,16}
|
||||
};
|
||||
|
||||
/*
|
||||
* 1. Take the MD5 Hash of the container name (with an extra null byte)
|
||||
* 2. Turn the hash into a 4 DWORD hex value
|
||||
* 3. Append a '_'
|
||||
* 4. Add the MachineGuid
|
||||
*
|
||||
*/
|
||||
static void uniquecontainer(char *unique)
|
||||
{
|
||||
/* MD5 hash of "winetest\0" in 4 DWORD hex */
|
||||
static const char szContainer_md5[] = "9d20fd8d05ed2b8455d125d0bf6d6a70";
|
||||
static const char szCryptography[] = "Software\\Microsoft\\Cryptography";
|
||||
static const char szMachineGuid[] = "MachineGuid";
|
||||
HKEY hkey;
|
||||
char guid[MAX_PATH];
|
||||
DWORD size = MAX_PATH;
|
||||
|
||||
/* Get the MachineGUID */
|
||||
RegOpenKeyA(HKEY_LOCAL_MACHINE, szCryptography, &hkey);
|
||||
RegQueryValueExA(hkey, szMachineGuid, NULL, NULL, (LPBYTE)guid, &size);
|
||||
RegCloseKey(hkey);
|
||||
|
||||
lstrcpy(unique, szContainer_md5);
|
||||
lstrcat(unique, "_");
|
||||
lstrcat(unique, guid);
|
||||
}
|
||||
|
||||
static void printBytes(const char *heading, const BYTE *pb, size_t cb)
|
||||
{
|
||||
size_t i;
|
||||
@@ -1849,11 +1877,21 @@ static void test_null_provider(void)
|
||||
SetLastError(0xdeadbeef);
|
||||
result = CryptGetProvParam(prov, PP_UNIQUE_CONTAINER, (LPBYTE)szName, &dataLen, 0);
|
||||
if (!result && GetLastError() == NTE_BAD_TYPE)
|
||||
{
|
||||
skip("PP_UNIQUE_CONTAINER is not supported (win9x or NT)\n");
|
||||
}
|
||||
else
|
||||
ok(result && dataLen == strlen(szContainer)+1 && strcmp(szContainer,szName) == 0,
|
||||
"failed getting PP_UNIQUE_CONTAINER. result = %s. Error 0x%08X. returned length = %d\n",
|
||||
(result)? "TRUE":"FALSE",GetLastError(),dataLen);
|
||||
{
|
||||
char container[MAX_PATH];
|
||||
|
||||
ok(result, "failed getting PP_UNIQUE_CONTAINER : 0x%08X\n", GetLastError());
|
||||
uniquecontainer(container);
|
||||
todo_wine
|
||||
{
|
||||
ok(dataLen == strlen(container)+1, "Expected a param length of 70, got %d\n", dataLen);
|
||||
ok(!strcmp(container, szName), "Wrong container name : %s\n", szName);
|
||||
}
|
||||
}
|
||||
result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
|
||||
ok(!result && GetLastError() == NTE_NO_KEY,
|
||||
"Expected NTE_NO_KEY, got %08x\n", GetLastError());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="rsaenh_winetest" type="win32cui" installbase="bin" installname="rsaenh_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="rsaenh_winetest" type="win32cui" installbase="bin" installname="rsaenh_winetest.exe" allowwarnings="true">
|
||||
<include base="rsaenh_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -156,13 +156,19 @@ static void testGetInfo(void)
|
||||
if (!pTables)
|
||||
return;
|
||||
status = pTables->GetInfo(&PackageInfo);
|
||||
ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
|
||||
ok(PackageInfo.fCapabilities == 0x107b3, "fCapabilities: 0x%lx\n",
|
||||
PackageInfo.fCapabilities);
|
||||
ok(PackageInfo.wVersion == 1, "wVersion: %d\n", PackageInfo.wVersion);
|
||||
ok(PackageInfo.wRPCID == 14, "wRPCID: %d\n", PackageInfo.wRPCID);
|
||||
ok(PackageInfo.cbMaxToken == 0x4000, "cbMaxToken: 0x%lx\n",
|
||||
PackageInfo.cbMaxToken);
|
||||
ok(status == STATUS_SUCCESS ||
|
||||
status == SEC_E_UNSUPPORTED_FUNCTION, /* win2k3 */
|
||||
"status: 0x%x\n", status);
|
||||
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
ok(PackageInfo.fCapabilities == 0x107b3, "fCapabilities: 0x%lx\n",
|
||||
PackageInfo.fCapabilities);
|
||||
ok(PackageInfo.wVersion == 1, "wVersion: %d\n", PackageInfo.wVersion);
|
||||
ok(PackageInfo.wRPCID == 14, "wRPCID: %d\n", PackageInfo.wRPCID);
|
||||
ok(PackageInfo.cbMaxToken == 0x4000, "cbMaxToken: 0x%lx\n",
|
||||
PackageInfo.cbMaxToken);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(main)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="schannel_winetest" type="win32cui" installbase="bin" installname="schannel_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="schannel_winetest" type="win32cui" installbase="bin" installname="schannel_winetest.exe" allowwarnings="true">
|
||||
<include base="schannel_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,117 +1,396 @@
|
||||
/*
|
||||
* INF file parsing tests
|
||||
* Unit test for setupapi.dll install functions
|
||||
*
|
||||
* Copyright 2006 Hervé Poussineau
|
||||
* Copyright 2007 Misha Koshelev
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public Licence as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
* 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 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
|
||||
* 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 <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winnls.h"
|
||||
#include "winuser.h"
|
||||
#include "winreg.h"
|
||||
#include "winsvc.h"
|
||||
#include "setupapi.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
#define TMPFILE ".\\tmp.inf"
|
||||
static const char inffile[] = "test.inf";
|
||||
static char CURR_DIR[MAX_PATH];
|
||||
|
||||
#define STD_HEADER "[Version]\r\nSignature=\"$CHICAGO$\"\r\n"
|
||||
/* Notes on InstallHinfSectionA/W:
|
||||
* - InstallHinfSectionW on Win98 and InstallHinfSectionA on WinXP seem to be stubs - they do not do anything
|
||||
* and simply return without displaying any error message or setting last error. We test whether
|
||||
* InstallHinfSectionA sets last error, and if it doesn't we set it to NULL and use the W version if available.
|
||||
* - These functions do not return a value and do not always set last error to ERROR_SUCCESS when installation still
|
||||
* occurs (e.g., unquoted inf file with spaces, registry keys are written but last error is 6). Also, on Win98 last error
|
||||
* is set to ERROR_SUCCESS even if install fails (e.g., quoted inf file with spaces, no registry keys set, MessageBox with
|
||||
* "Installation Error" displayed). Thus, we must use functional tests (e.g., is registry key created) to determine whether
|
||||
* or not installation occurred.
|
||||
* - On installation problems, a MessageBox() is displayed and a Beep() is issued. The MessageBox() is disabled with a
|
||||
* CBT hook.
|
||||
*/
|
||||
|
||||
/* create a new file with specified contents and open it */
|
||||
static HINF test_file_contents( const char *data, UINT *err_line )
|
||||
static void (WINAPI *pInstallHinfSectionA)(HWND, HINSTANCE, LPCSTR, INT);
|
||||
static void (WINAPI *pInstallHinfSectionW)(HWND, HINSTANCE, LPCWSTR, INT);
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
static void create_inf_file(LPCSTR filename, const char *data)
|
||||
{
|
||||
DWORD res;
|
||||
HANDLE handle = CreateFileA( TMPFILE, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
if (handle == INVALID_HANDLE_VALUE) return 0;
|
||||
if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" );
|
||||
CloseHandle( handle );
|
||||
return SetupOpenInfFileA( TMPFILE, 0, INF_STYLE_WIN4, err_line );
|
||||
HANDLE handle = CreateFile(filename, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
assert(handle != INVALID_HANDLE_VALUE);
|
||||
assert(WriteFile(handle, data, strlen(data), &res, NULL));
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
static void test_InstallHinfSectionA(void)
|
||||
/* CBT hook to ensure a window (e.g., MessageBox) cannot be created */
|
||||
static HHOOK hhook;
|
||||
static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
char buffer[MAX_INF_STRING_LENGTH];
|
||||
UINT err_line;
|
||||
HINF hinf;
|
||||
DWORD err;
|
||||
DWORD len;
|
||||
return nCode == HCBT_CREATEWND ? 1: CallNextHookEx(hhook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
hinf = test_file_contents( STD_HEADER
|
||||
"[s]\r\nAddReg=s.Reg\r\n[s.Reg]\r\nHKCU,,Test,,none\r\n"
|
||||
"[s.Win]\r\nAddReg=sWin.Reg\r\n[sWin.Reg]\r\nHKCU,,Test,,win\r\n"
|
||||
"[s.NT]\r\nAddReg=sNT.Reg\r\n[sNT.Reg]\r\nHKCU,,Test,,nt\r\n"
|
||||
, &err_line );
|
||||
ok( hinf != INVALID_HANDLE_VALUE, "open failed err %lx", GetLastError() );
|
||||
if ( hinf == INVALID_HANDLE_VALUE ) return;
|
||||
/*
|
||||
* Tests
|
||||
*/
|
||||
|
||||
system( "rundll32.exe setupapi,InstallHinfSection s 128 " TMPFILE );
|
||||
static const char *cmdline_inf = "[Version]\n"
|
||||
"Signature=\"$Chicago$\"\n"
|
||||
"[DefaultInstall]\n"
|
||||
"AddReg=Add.Settings\n"
|
||||
"[Add.Settings]\n"
|
||||
"HKCU,Software\\Wine\\setupapitest,,\n";
|
||||
|
||||
len = sizeof( buffer );
|
||||
err = RegQueryValueExA( HKEY_CURRENT_USER, "Test", NULL, NULL, (LPBYTE)buffer, &len );
|
||||
ok( err == ERROR_SUCCESS, "error %lx", err);
|
||||
static void run_cmdline(LPCSTR section, int mode, LPCSTR path)
|
||||
{
|
||||
CHAR cmdline[MAX_PATH * 2];
|
||||
|
||||
if (GetVersion() & 0x80000000)
|
||||
ok( !strcmp( buffer, "win" ), "bad section %s/win\n", buffer );
|
||||
sprintf(cmdline, "%s %d %s", section, mode, path);
|
||||
if (pInstallHinfSectionA) pInstallHinfSectionA(NULL, NULL, cmdline, 0);
|
||||
else
|
||||
ok( !strcmp( buffer, "nt" ), "bad section %s/nt\n", buffer );
|
||||
|
||||
err = RegDeleteValue( HKEY_CURRENT_USER, "Test" );
|
||||
ok( err == ERROR_SUCCESS, "error %lx", err);
|
||||
{
|
||||
WCHAR cmdlinew[MAX_PATH * 2];
|
||||
MultiByteToWideChar(CP_ACP, 0, cmdline, -1, cmdlinew, MAX_PATH*2);
|
||||
pInstallHinfSectionW(NULL, NULL, cmdlinew, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_SetupInstallFromInfSectionA(void)
|
||||
static void ok_registry(BOOL expectsuccess)
|
||||
{
|
||||
char buffer[MAX_INF_STRING_LENGTH];
|
||||
UINT err_line;
|
||||
HINF hinf;
|
||||
DWORD err;
|
||||
DWORD len;
|
||||
LONG ret;
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
hinf = test_file_contents( STD_HEADER
|
||||
"[s]\r\nAddReg=s.Reg\r\n[s.Reg]\r\nHKR,,Test,,none\r\n"
|
||||
"[s.Win]\r\nAddReg=sWin.Reg\r\n[sWin.Reg]\r\nHKR,,Test,,win\r\n"
|
||||
"[s.NT]\r\nAddReg=sNT.Reg\r\n[sNT.Reg]\r\nHKR,,Test,,nt\r\n"
|
||||
, &err_line );
|
||||
ok( hinf != INVALID_HANDLE_VALUE, "open failed err %lx", GetLastError() );
|
||||
if (hinf == INVALID_HANDLE_VALUE) return;
|
||||
/* Functional tests for success of install and clean up */
|
||||
ret = RegDeleteKey(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest");
|
||||
ok((expectsuccess && ret == ERROR_SUCCESS) ||
|
||||
(!expectsuccess && ret == ERROR_FILE_NOT_FOUND),
|
||||
"Expected registry key Software\\Wine\\setupapitest to %s, RegDeleteKey returned %d\n",
|
||||
expectsuccess ? "exist" : "not exist",
|
||||
ret);
|
||||
}
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ok ( SetupInstallFromInfSectionA( NULL, hinf, "s", SPINST_REGISTRY, HKEY_CURRENT_USER, NULL, 0, NULL, NULL, NULL, NULL ),
|
||||
"Error code set to %lx", GetLastError() );
|
||||
/* Test command line processing */
|
||||
static void test_cmdline(void)
|
||||
{
|
||||
static const char infwithspaces[] = "test file.inf";
|
||||
char path[MAX_PATH];
|
||||
|
||||
len = sizeof( buffer );
|
||||
err = RegQueryValueExA( HKEY_CURRENT_USER, "Test", NULL, NULL, (LPBYTE)buffer, &len );
|
||||
ok( err == ERROR_SUCCESS, "error %lx", err);
|
||||
ok( !strcmp( buffer, "none" ), "bad value %s/none", buffer );
|
||||
create_inf_file(inffile, cmdline_inf);
|
||||
sprintf(path, "%s\\%s", CURR_DIR, inffile);
|
||||
run_cmdline("DefaultInstall", 128, path);
|
||||
ok_registry(TRUE);
|
||||
ok(DeleteFile(inffile), "Expected source inf to exist, last error was %d\n", GetLastError());
|
||||
|
||||
err = RegDeleteValue( HKEY_CURRENT_USER, "Test" );
|
||||
ok( err == ERROR_SUCCESS, "error %lx", err);
|
||||
/* Test handling of spaces in path, unquoted and quoted */
|
||||
create_inf_file(infwithspaces, cmdline_inf);
|
||||
|
||||
sprintf(path, "%s\\%s", CURR_DIR, infwithspaces);
|
||||
run_cmdline("DefaultInstall", 128, path);
|
||||
ok_registry(TRUE);
|
||||
|
||||
sprintf(path, "\"%s\\%s\"", CURR_DIR, infwithspaces);
|
||||
run_cmdline("DefaultInstall", 128, path);
|
||||
ok_registry(FALSE);
|
||||
|
||||
ok(DeleteFile(infwithspaces), "Expected source inf to exist, last error was %d\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_install_svc_from(void)
|
||||
{
|
||||
char inf[2048];
|
||||
char path[MAX_PATH];
|
||||
HINF infhandle;
|
||||
BOOL ret;
|
||||
SC_HANDLE scm_handle, svc_handle;
|
||||
|
||||
/* Bail out if we are on win98 */
|
||||
SetLastError(0xdeadbeef);
|
||||
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
|
||||
|
||||
if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
||||
{
|
||||
skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
|
||||
return;
|
||||
}
|
||||
CloseServiceHandle(scm_handle);
|
||||
|
||||
/* Basic inf file to satisfy SetupOpenInfFileA */
|
||||
strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
|
||||
create_inf_file(inffile, inf);
|
||||
sprintf(path, "%s\\%s", CURR_DIR, inffile);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
|
||||
/* Nothing but the Version section */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
|
||||
"Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
/* Add the section */
|
||||
strcat(inf, "[Winetest.Services]\n");
|
||||
create_inf_file(inffile, inf);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
|
||||
"Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
/* Add a reference */
|
||||
strcat(inf, "AddService=Winetest,,Winetest.Service\n");
|
||||
create_inf_file(inffile, inf);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
|
||||
"Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
/* Add the section */
|
||||
strcat(inf, "[Winetest.Service]\n");
|
||||
create_inf_file(inffile, inf);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
|
||||
"Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
/* Just the ServiceBinary */
|
||||
strcat(inf, "ServiceBinary=%12%\\winetest.sys\n");
|
||||
create_inf_file(inffile, inf);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
|
||||
"Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
/* Add the ServiceType */
|
||||
strcat(inf, "ServiceType=1\n");
|
||||
create_inf_file(inffile, inf);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
|
||||
"Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
/* Add the StartType */
|
||||
strcat(inf, "StartType=4\n");
|
||||
create_inf_file(inffile, inf);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
|
||||
"Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
/* This should be it, the minimal entries to install a service */
|
||||
strcat(inf, "ErrorControl=1");
|
||||
create_inf_file(inffile, inf);
|
||||
infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
|
||||
ok(ret, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS,
|
||||
"Expected ERROR_SUCCESS, got %08x\n", GetLastError());
|
||||
SetupCloseInfFile(infhandle);
|
||||
DeleteFile(inffile);
|
||||
|
||||
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
|
||||
|
||||
/* Open the service to see if it's really there */
|
||||
svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE);
|
||||
ok(svc_handle != NULL, "Service was not created\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = DeleteService(svc_handle);
|
||||
ok(ret, "Service could not be deleted : %d\n", GetLastError());
|
||||
|
||||
CloseServiceHandle(svc_handle);
|
||||
CloseServiceHandle(scm_handle);
|
||||
|
||||
/* TODO: Test the Flags */
|
||||
}
|
||||
|
||||
static void test_driver_install(void)
|
||||
{
|
||||
HANDLE handle;
|
||||
SC_HANDLE scm_handle, svc_handle;
|
||||
BOOL ret;
|
||||
char path[MAX_PATH], windir[MAX_PATH], driver[MAX_PATH];
|
||||
DWORD attrs;
|
||||
/* Minimal stuff needed */
|
||||
static const char *inf =
|
||||
"[Version]\n"
|
||||
"Signature=\"$Chicago$\"\n"
|
||||
"[DestinationDirs]\n"
|
||||
"Winetest.DriverFiles=12\n"
|
||||
"[DefaultInstall]\n"
|
||||
"CopyFiles=Winetest.DriverFiles\n"
|
||||
"[DefaultInstall.Services]\n"
|
||||
"AddService=Winetest,,Winetest.Service\n"
|
||||
"[Winetest.Service]\n"
|
||||
"ServiceBinary=%12%\\winetest.sys\n"
|
||||
"ServiceType=1\n"
|
||||
"StartType=4\n"
|
||||
"ErrorControl=1\n"
|
||||
"[Winetest.DriverFiles]\n"
|
||||
"winetest.sys";
|
||||
|
||||
/* Bail out if we are on win98 */
|
||||
SetLastError(0xdeadbeef);
|
||||
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
|
||||
|
||||
if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
||||
{
|
||||
skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
|
||||
return;
|
||||
}
|
||||
CloseServiceHandle(scm_handle);
|
||||
|
||||
/* Place where we expect the driver to be installed */
|
||||
GetWindowsDirectoryA(windir, MAX_PATH);
|
||||
lstrcpyA(driver, windir);
|
||||
lstrcatA(driver, "\\system32\\drivers\\winetest.sys");
|
||||
|
||||
/* Create a dummy driver file */
|
||||
handle = CreateFileA("winetest.sys", GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
CloseHandle(handle);
|
||||
|
||||
create_inf_file(inffile, inf);
|
||||
sprintf(path, "%s\\%s", CURR_DIR, inffile);
|
||||
run_cmdline("DefaultInstall", 128, path);
|
||||
|
||||
/* Driver should have been installed */
|
||||
attrs = GetFileAttributes(driver);
|
||||
ok(attrs != INVALID_FILE_ATTRIBUTES, "Expected driver to exist\n");
|
||||
|
||||
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
|
||||
|
||||
/* Open the service to see if it's really there */
|
||||
svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE);
|
||||
ok(svc_handle != NULL, "Service was not created\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = DeleteService(svc_handle);
|
||||
ok(ret, "Service could not be deleted : %d\n", GetLastError());
|
||||
|
||||
CloseServiceHandle(svc_handle);
|
||||
CloseServiceHandle(scm_handle);
|
||||
|
||||
/* File cleanup */
|
||||
DeleteFile(inffile);
|
||||
DeleteFile("winetest.sys");
|
||||
DeleteFile(driver);
|
||||
}
|
||||
|
||||
START_TEST(install)
|
||||
{
|
||||
test_InstallHinfSectionA();
|
||||
test_SetupInstallFromInfSectionA();
|
||||
DeleteFileA( TMPFILE );
|
||||
HMODULE hsetupapi = GetModuleHandle("setupapi.dll");
|
||||
char temp_path[MAX_PATH], prev_path[MAX_PATH];
|
||||
DWORD len;
|
||||
|
||||
GetCurrentDirectory(MAX_PATH, prev_path);
|
||||
GetTempPath(MAX_PATH, temp_path);
|
||||
SetCurrentDirectory(temp_path);
|
||||
|
||||
strcpy(CURR_DIR, temp_path);
|
||||
len = strlen(CURR_DIR);
|
||||
if(len && (CURR_DIR[len - 1] == '\\'))
|
||||
CURR_DIR[len - 1] = 0;
|
||||
|
||||
pInstallHinfSectionA = (void *)GetProcAddress(hsetupapi, "InstallHinfSectionA");
|
||||
pInstallHinfSectionW = (void *)GetProcAddress(hsetupapi, "InstallHinfSectionW");
|
||||
if (pInstallHinfSectionA)
|
||||
{
|
||||
/* Check if pInstallHinfSectionA sets last error or is a stub (as on WinXP) */
|
||||
static const char *minimal_inf = "[Version]\nSignature=\"$Chicago$\"\n";
|
||||
char cmdline[MAX_PATH*2];
|
||||
create_inf_file(inffile, minimal_inf);
|
||||
sprintf(cmdline, "DefaultInstall 128 %s\\%s", CURR_DIR, inffile);
|
||||
SetLastError(0xdeadbeef);
|
||||
pInstallHinfSectionA(NULL, NULL, cmdline, 0);
|
||||
if (GetLastError() == 0xdeadbeef)
|
||||
{
|
||||
skip("InstallHinfSectionA is broken (stub)\n");
|
||||
pInstallHinfSectionA = NULL;
|
||||
}
|
||||
ok(DeleteFile(inffile), "Expected source inf to exist, last error was %d\n", GetLastError());
|
||||
}
|
||||
if (!pInstallHinfSectionW && !pInstallHinfSectionA)
|
||||
skip("InstallHinfSectionA and InstallHinfSectionW are not available\n");
|
||||
else
|
||||
{
|
||||
/* Set CBT hook to disallow MessageBox creation in current thread */
|
||||
hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
|
||||
assert(hhook != 0);
|
||||
|
||||
test_cmdline();
|
||||
test_install_svc_from();
|
||||
test_driver_install();
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
}
|
||||
|
||||
SetCurrentDirectory(prev_path);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,595 @@
|
||||
/*
|
||||
* Miscellaneous tests
|
||||
*
|
||||
* Copyright 2007 James Hawkins
|
||||
* Copyright 2007 Hans Leidekker
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winnls.h"
|
||||
#include "winuser.h"
|
||||
#include "winreg.h"
|
||||
#include "setupapi.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static CHAR CURR_DIR[MAX_PATH];
|
||||
|
||||
/* test:
|
||||
* - fails if not administrator
|
||||
* - what if it's not a .inf file?
|
||||
* - copied to %windir%/Inf
|
||||
* - SourceInfFileName should be a full path
|
||||
* - SourceInfFileName should be <= MAX_PATH
|
||||
* - copy styles
|
||||
*/
|
||||
|
||||
static BOOL (WINAPI *pSetupGetFileCompressionInfoExA)(PCSTR, PSTR, DWORD, PDWORD, PDWORD, PDWORD, PUINT);
|
||||
static BOOL (WINAPI *pSetupCopyOEMInfA)(PCSTR, PCSTR, DWORD, DWORD, PSTR, DWORD, PDWORD, PSTR *);
|
||||
static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(PSP_INF_INFORMATION, UINT, PSP_ALTPLATFORM_INFO, PSP_ORIGINAL_FILE_INFO_A);
|
||||
|
||||
static void append_str(char **str, const char *data)
|
||||
{
|
||||
sprintf(*str, data);
|
||||
*str += strlen(*str);
|
||||
}
|
||||
|
||||
static void create_inf_file(LPCSTR filename)
|
||||
{
|
||||
char data[1024];
|
||||
char *ptr = data;
|
||||
DWORD dwNumberOfBytesWritten;
|
||||
HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
append_str(&ptr, "[Version]\n");
|
||||
append_str(&ptr, "Signature=\"$Chicago$\"\n");
|
||||
append_str(&ptr, "AdvancedINF=2.5\n");
|
||||
append_str(&ptr, "[DefaultInstall]\n");
|
||||
append_str(&ptr, "RegisterOCXs=RegisterOCXsSection\n");
|
||||
append_str(&ptr, "[RegisterOCXsSection]\n");
|
||||
append_str(&ptr, "%%11%%\\ole32.dll\n");
|
||||
|
||||
WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
|
||||
CloseHandle(hf);
|
||||
}
|
||||
|
||||
static void get_temp_filename(LPSTR path)
|
||||
{
|
||||
CHAR temp[MAX_PATH];
|
||||
LPSTR ptr;
|
||||
|
||||
GetTempFileName(CURR_DIR, "set", 0, temp);
|
||||
ptr = strrchr(temp, '\\');
|
||||
|
||||
lstrcpy(path, ptr + 1);
|
||||
}
|
||||
|
||||
static BOOL file_exists(LPSTR path)
|
||||
{
|
||||
return GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
static BOOL check_format(LPSTR path, LPSTR inf)
|
||||
{
|
||||
CHAR check[MAX_PATH];
|
||||
BOOL res;
|
||||
|
||||
static const CHAR format[] = "\\INF\\oem";
|
||||
|
||||
GetWindowsDirectory(check, MAX_PATH);
|
||||
lstrcat(check, format);
|
||||
res = CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, check, -1, path, lstrlen(check)) == CSTR_EQUAL &&
|
||||
path[lstrlen(check)] != '\\';
|
||||
|
||||
return (!inf) ? res : res && (inf == path + lstrlen(check) - 3);
|
||||
}
|
||||
|
||||
static void test_original_file_name(LPCSTR original, LPCSTR dest)
|
||||
{
|
||||
HINF hinf;
|
||||
PSP_INF_INFORMATION pspii;
|
||||
SP_ORIGINAL_FILE_INFO spofi;
|
||||
BOOL res;
|
||||
DWORD size;
|
||||
|
||||
if (!pSetupQueryInfOriginalFileInformationA)
|
||||
{
|
||||
skip("SetupQueryInfOriginalFileInformationA is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hinf = SetupOpenInfFileA(dest, NULL, INF_STYLE_WIN4, NULL);
|
||||
ok(hinf != NULL, "SetupOpenInfFileA failed with error %d\n", GetLastError());
|
||||
|
||||
res = SetupGetInfInformation(hinf, INFINFO_INF_SPEC_IS_HINF, NULL, 0, &size);
|
||||
ok(res, "SetupGetInfInformation failed with error %d\n", GetLastError());
|
||||
|
||||
pspii = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
|
||||
res = SetupGetInfInformation(hinf, INFINFO_INF_SPEC_IS_HINF, pspii, size, NULL);
|
||||
ok(res, "SetupGetInfInformation failed with error %d\n", GetLastError());
|
||||
|
||||
spofi.cbSize = 0;
|
||||
res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi);
|
||||
ok(!res && GetLastError() == ERROR_INVALID_USER_BUFFER,
|
||||
"SetupQueryInfOriginalFileInformationA should have failed with ERROR_INVALID_USER_BUFFER instead of %d\n", GetLastError());
|
||||
|
||||
spofi.cbSize = sizeof(spofi);
|
||||
res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi);
|
||||
ok(res, "SetupQueryInfOriginalFileInformationA failed with error %d\n", GetLastError());
|
||||
ok(!spofi.OriginalCatalogName[0], "spofi.OriginalCatalogName should have been \"\" instead of \"%s\"\n", spofi.OriginalCatalogName);
|
||||
todo_wine
|
||||
ok(!strcmp(original, spofi.OriginalInfName), "spofi.OriginalInfName of %s didn't match real original name %s\n", spofi.OriginalInfName, original);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, pspii);
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
}
|
||||
|
||||
static void test_SetupCopyOEMInf(void)
|
||||
{
|
||||
CHAR toolong[MAX_PATH * 2];
|
||||
CHAR path[MAX_PATH], dest[MAX_PATH];
|
||||
CHAR tmpfile[MAX_PATH], dest_save[MAX_PATH];
|
||||
LPSTR inf;
|
||||
DWORD size;
|
||||
BOOL res;
|
||||
|
||||
/* try NULL SourceInfFileName */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(NULL, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
/* try empty SourceInfFileName */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA("", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
/* try a relative nonexistent SourceInfFileName */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA("nonexistent", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
/* try an absolute nonexistent SourceInfFileName */
|
||||
lstrcpy(path, CURR_DIR);
|
||||
lstrcat(path, "\\nonexistent");
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
/* try a long SourceInfFileName */
|
||||
memset(toolong, 'a', MAX_PATH * 2);
|
||||
toolong[MAX_PATH * 2 - 1] = '\0';
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(toolong, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
get_temp_filename(tmpfile);
|
||||
create_inf_file(tmpfile);
|
||||
|
||||
/* try a relative SourceInfFileName */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(tmpfile, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
ok(file_exists(tmpfile), "Expected tmpfile to exist\n");
|
||||
|
||||
/* try SP_COPY_REPLACEONLY, dest does not exist */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
ok(file_exists(tmpfile), "Expected source inf to exist\n");
|
||||
|
||||
/* try an absolute SourceInfFileName, without DestinationInfFileName */
|
||||
lstrcpy(path, CURR_DIR);
|
||||
lstrcat(path, "\\");
|
||||
lstrcat(path, tmpfile);
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, NULL, 0, NULL, NULL);
|
||||
ok(res == TRUE, "Expected TRUE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
ok(file_exists(path), "Expected source inf to exist\n");
|
||||
|
||||
/* try SP_COPY_REPLACEONLY, dest exists */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL);
|
||||
ok(res == TRUE, "Expected TRUE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
ok(file_exists(path), "Expected source inf to exist\n");
|
||||
|
||||
/* try SP_COPY_NOOVERWRITE */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_FILE_EXISTS,
|
||||
"Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
|
||||
|
||||
/* get the DestinationInfFileName */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, NULL, NULL);
|
||||
ok(res == TRUE, "Expected TRUE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
ok(lstrlen(dest) != 0, "Expected a non-zero length string\n");
|
||||
ok(file_exists(dest), "Expected destination inf to exist\n");
|
||||
ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
|
||||
ok(file_exists(path), "Expected source inf to exist\n");
|
||||
|
||||
lstrcpy(dest_save, dest);
|
||||
DeleteFile(dest_save);
|
||||
|
||||
/* get the DestinationInfFileName, DestinationInfFileNameSize is too small
|
||||
* - inf is still copied
|
||||
*/
|
||||
lstrcpy(dest, "aaa");
|
||||
size = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, 5, &size, NULL);
|
||||
ok(res == FALSE, "Expected FALSE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
|
||||
ok(file_exists(path), "Expected source inf to exist\n");
|
||||
ok(file_exists(dest_save), "Expected dest inf to exist\n");
|
||||
ok(!lstrcmp(dest, "aaa"), "Expected dest to be unchanged\n");
|
||||
ok(size == lstrlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
|
||||
|
||||
/* get the DestinationInfFileName and DestinationInfFileNameSize */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, NULL);
|
||||
ok(res == TRUE, "Expected TRUE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
ok(lstrlen(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlen(dest), size);
|
||||
ok(file_exists(dest), "Expected destination inf to exist\n");
|
||||
ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
|
||||
ok(file_exists(path), "Expected source inf to exist\n");
|
||||
ok(size == lstrlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
|
||||
|
||||
test_original_file_name(strrchr(path, '\\') + 1, dest);
|
||||
|
||||
/* get the DestinationInfFileName, DestinationInfFileNameSize, and DestinationInfFileNameComponent */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, &inf);
|
||||
ok(res == TRUE, "Expected TRUE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
ok(lstrlen(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlen(dest), size);
|
||||
ok(file_exists(dest), "Expected destination inf to exist\n");
|
||||
ok(check_format(dest, inf), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest);
|
||||
ok(file_exists(path), "Expected source inf to exist\n");
|
||||
ok(size == lstrlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n");
|
||||
|
||||
/* try SP_COPY_DELETESOURCE */
|
||||
SetLastError(0xdeadbeef);
|
||||
res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_DELETESOURCE, NULL, 0, NULL, NULL);
|
||||
ok(res == TRUE, "Expected TRUE, got %d\n", res);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
ok(!file_exists(path), "Expected source inf to not exist\n");
|
||||
}
|
||||
|
||||
static void create_source_file(LPSTR filename, const BYTE *data, DWORD size)
|
||||
{
|
||||
HANDLE handle;
|
||||
DWORD written;
|
||||
|
||||
handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
WriteFile(handle, data, size, &written, NULL);
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
static BOOL compare_file_data(LPSTR file, const BYTE *data, DWORD size)
|
||||
{
|
||||
DWORD read;
|
||||
HANDLE handle;
|
||||
BOOL ret = FALSE;
|
||||
LPBYTE buffer;
|
||||
|
||||
handle = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (buffer)
|
||||
{
|
||||
ReadFile(handle, buffer, size, &read, NULL);
|
||||
if (read == size && !memcmp(data, buffer, size)) ret = TRUE;
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
}
|
||||
CloseHandle(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BYTE uncompressed[] = {
|
||||
'u','n','c','o','m','p','r','e','s','s','e','d','\r','\n'
|
||||
};
|
||||
static const BYTE comp_lzx[] = {
|
||||
0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33, 0x41, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x3f, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64
|
||||
};
|
||||
static const BYTE comp_zip[] = {
|
||||
0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11,
|
||||
0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x15, 0x00, 0x77, 0x69,
|
||||
0x6e, 0x65, 0x55, 0x54, 0x09, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46, 0xfd, 0x0d, 0x10, 0x46, 0x55,
|
||||
0x78, 0x04, 0x00, 0xe8, 0x03, 0xe8, 0x03, 0x00, 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x72,
|
||||
0x65, 0x73, 0x73, 0x65, 0x64, 0x50, 0x4b, 0x01, 0x02, 0x17, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xbd, 0xae, 0x81, 0x36, 0x75, 0x11, 0x2c, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00,
|
||||
0x00, 0x00, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x55, 0x54, 0x05, 0x00, 0x03, 0xd6, 0x0d, 0x10, 0x46,
|
||||
0x55, 0x78, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
|
||||
0x3f, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
static const BYTE comp_cab_lzx[] = {
|
||||
0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x0f, 0x0e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x36, 0x86, 0x72, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
|
||||
0x00, 0x19, 0xd0, 0x1a, 0xe3, 0x22, 0x00, 0x0e, 0x00, 0x5b, 0x80, 0x80, 0x8d, 0x00, 0x30, 0xe0,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x63,
|
||||
0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x0d, 0x0a
|
||||
};
|
||||
static const BYTE comp_cab_zip[] = {
|
||||
0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x36, 0x2f, 0xa5, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65,
|
||||
0x00, 0x7c, 0x80, 0x26, 0x2b, 0x12, 0x00, 0x0e, 0x00, 0x43, 0x4b, 0x2b, 0xcd, 0x4b, 0xce, 0xcf,
|
||||
0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0xe1, 0xe5, 0x02, 0x00
|
||||
};
|
||||
|
||||
static void test_SetupGetFileCompressionInfo(void)
|
||||
{
|
||||
DWORD ret, source_size, target_size;
|
||||
char source[MAX_PATH], temp[MAX_PATH], *name;
|
||||
UINT type;
|
||||
|
||||
GetTempPathA(sizeof(temp), temp);
|
||||
GetTempFileNameA(temp, "fci", 0, source);
|
||||
|
||||
create_source_file(source, uncompressed, sizeof(uncompressed));
|
||||
|
||||
ret = SetupGetFileCompressionInfoA(NULL, NULL, NULL, NULL, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
|
||||
|
||||
ret = SetupGetFileCompressionInfoA(source, NULL, NULL, NULL, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
|
||||
|
||||
ret = SetupGetFileCompressionInfoA(source, &name, NULL, NULL, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
|
||||
|
||||
ret = SetupGetFileCompressionInfoA(source, &name, &source_size, NULL, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
|
||||
|
||||
ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupGetFileCompressionInfo failed unexpectedly\n");
|
||||
|
||||
name = NULL;
|
||||
source_size = target_size = 0;
|
||||
type = 5;
|
||||
|
||||
ret = SetupGetFileCompressionInfoA(source, &name, &source_size, &target_size, &type);
|
||||
ok(!ret, "SetupGetFileCompressionInfo failed unexpectedly\n");
|
||||
ok(name && !lstrcmpA(name, source), "got %s, expected %s\n", name, source);
|
||||
ok(source_size == sizeof(uncompressed), "got %d\n", source_size);
|
||||
ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
|
||||
ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
|
||||
|
||||
DeleteFileA(source);
|
||||
}
|
||||
|
||||
static void test_SetupGetFileCompressionInfoEx(void)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD required_len, source_size, target_size;
|
||||
char source[MAX_PATH], temp[MAX_PATH], name[MAX_PATH];
|
||||
UINT type;
|
||||
|
||||
GetTempPathA(sizeof(temp), temp);
|
||||
GetTempFileNameA(temp, "doc", 0, source);
|
||||
|
||||
ret = pSetupGetFileCompressionInfoExA(NULL, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
|
||||
|
||||
ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
|
||||
|
||||
ret = pSetupGetFileCompressionInfoExA(source, NULL, 0, &required_len, NULL, NULL, NULL);
|
||||
ok(!ret, "SetupGetFileCompressionInfoEx succeeded unexpectedly\n");
|
||||
ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
|
||||
|
||||
create_source_file(source, comp_lzx, sizeof(comp_lzx));
|
||||
|
||||
ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
|
||||
ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
|
||||
ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
|
||||
ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
|
||||
ok(source_size == sizeof(comp_lzx), "got %d\n", source_size);
|
||||
ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
|
||||
ok(type == FILE_COMPRESSION_WINLZA, "got %d, expected FILE_COMPRESSION_WINLZA\n", type);
|
||||
DeleteFileA(source);
|
||||
|
||||
create_source_file(source, comp_zip, sizeof(comp_zip));
|
||||
|
||||
ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
|
||||
ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
|
||||
ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
|
||||
ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
|
||||
ok(source_size == sizeof(comp_zip), "got %d\n", source_size);
|
||||
ok(target_size == sizeof(comp_zip), "got %d\n", target_size);
|
||||
ok(type == FILE_COMPRESSION_NONE, "got %d, expected FILE_COMPRESSION_NONE\n", type);
|
||||
DeleteFileA(source);
|
||||
|
||||
create_source_file(source, comp_cab_lzx, sizeof(comp_cab_lzx));
|
||||
|
||||
ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
|
||||
ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
|
||||
ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
|
||||
ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
|
||||
ok(source_size == sizeof(comp_cab_lzx), "got %d\n", source_size);
|
||||
ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
|
||||
ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
|
||||
DeleteFileA(source);
|
||||
|
||||
create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
|
||||
|
||||
ret = pSetupGetFileCompressionInfoExA(source, name, sizeof(name), &required_len, &source_size, &target_size, &type);
|
||||
ok(ret, "SetupGetFileCompressionInfoEx failed unexpectedly: %d\n", ret);
|
||||
ok(!lstrcmpA(name, source), "got %s, expected %s\n", name, source);
|
||||
ok(required_len == lstrlenA(source) + 1, "got %d, expected %d\n", required_len, lstrlenA(source) + 1);
|
||||
ok(source_size == sizeof(comp_cab_zip), "got %d\n", source_size);
|
||||
ok(target_size == sizeof(uncompressed), "got %d\n", target_size);
|
||||
ok(type == FILE_COMPRESSION_MSZIP, "got %d, expected FILE_COMPRESSION_MSZIP\n", type);
|
||||
DeleteFileA(source);
|
||||
}
|
||||
|
||||
static void test_SetupDecompressOrCopyFile(void)
|
||||
{
|
||||
DWORD ret;
|
||||
char source[MAX_PATH], target[MAX_PATH], temp[MAX_PATH], *p;
|
||||
UINT type;
|
||||
|
||||
GetTempPathA(sizeof(temp), temp);
|
||||
GetTempFileNameA(temp, "doc", 0, source);
|
||||
GetTempFileNameA(temp, "doc", 0, target);
|
||||
|
||||
/* parameter tests */
|
||||
|
||||
create_source_file(source, uncompressed, sizeof(uncompressed));
|
||||
|
||||
ret = SetupDecompressOrCopyFileA(NULL, NULL, NULL);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
|
||||
|
||||
type = FILE_COMPRESSION_NONE;
|
||||
ret = SetupDecompressOrCopyFileA(NULL, target, &type);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
|
||||
|
||||
ret = SetupDecompressOrCopyFileA(source, NULL, &type);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
|
||||
|
||||
type = 5; /* try an invalid compression type */
|
||||
ret = SetupDecompressOrCopyFileA(source, target, &type);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SetupDecompressOrCopyFile failed unexpectedly\n");
|
||||
|
||||
DeleteFileA(target);
|
||||
|
||||
/* no compression tests */
|
||||
|
||||
ret = SetupDecompressOrCopyFileA(source, target, NULL);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
|
||||
|
||||
/* try overwriting existing file */
|
||||
ret = SetupDecompressOrCopyFileA(source, target, NULL);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
DeleteFileA(target);
|
||||
|
||||
type = FILE_COMPRESSION_NONE;
|
||||
ret = SetupDecompressOrCopyFileA(source, target, &type);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
|
||||
DeleteFileA(target);
|
||||
|
||||
type = FILE_COMPRESSION_WINLZA;
|
||||
ret = SetupDecompressOrCopyFileA(source, target, &type);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
|
||||
DeleteFileA(target);
|
||||
|
||||
/* lz compression tests */
|
||||
|
||||
create_source_file(source, comp_lzx, sizeof(comp_lzx));
|
||||
|
||||
ret = SetupDecompressOrCopyFileA(source, target, NULL);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
DeleteFileA(target);
|
||||
|
||||
/* zip compression tests */
|
||||
|
||||
create_source_file(source, comp_zip, sizeof(comp_zip));
|
||||
|
||||
ret = SetupDecompressOrCopyFileA(source, target, NULL);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
ok(compare_file_data(target, comp_zip, sizeof(comp_zip)), "incorrect target file\n");
|
||||
DeleteFileA(target);
|
||||
|
||||
/* cabinet compression tests */
|
||||
|
||||
create_source_file(source, comp_cab_zip, sizeof(comp_cab_zip));
|
||||
|
||||
p = strrchr(target, '\\');
|
||||
lstrcpyA(p + 1, "wine");
|
||||
|
||||
ret = SetupDecompressOrCopyFileA(source, target, NULL);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
|
||||
|
||||
/* try overwriting existing file */
|
||||
ret = SetupDecompressOrCopyFileA(source, target, NULL);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
|
||||
/* try zip compression */
|
||||
type = FILE_COMPRESSION_MSZIP;
|
||||
ret = SetupDecompressOrCopyFileA(source, target, &type);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
ok(compare_file_data(target, uncompressed, sizeof(uncompressed)), "incorrect target file\n");
|
||||
|
||||
/* try no compression */
|
||||
type = FILE_COMPRESSION_NONE;
|
||||
ret = SetupDecompressOrCopyFileA(source, target, &type);
|
||||
ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret);
|
||||
ok(compare_file_data(target, comp_cab_zip, sizeof(comp_cab_zip)), "incorrect target file\n");
|
||||
|
||||
DeleteFileA(target);
|
||||
DeleteFileA(source);
|
||||
}
|
||||
|
||||
START_TEST(misc)
|
||||
{
|
||||
HMODULE hsetupapi = GetModuleHandle("setupapi.dll");
|
||||
|
||||
pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA");
|
||||
pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA");
|
||||
pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA");
|
||||
|
||||
GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
|
||||
|
||||
if (pSetupCopyOEMInfA)
|
||||
test_SetupCopyOEMInf();
|
||||
else
|
||||
skip("SetupCopyOEMInfA is not available\n");
|
||||
|
||||
test_SetupGetFileCompressionInfo();
|
||||
|
||||
if (pSetupGetFileCompressionInfoExA)
|
||||
test_SetupGetFileCompressionInfoEx();
|
||||
else
|
||||
skip("SetupGetFileCompressionInfoExA is not available\n");
|
||||
|
||||
test_SetupDecompressOrCopyFile();
|
||||
}
|
||||
@@ -30,7 +30,18 @@
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static const char tmpfile[] = ".\\tmp.inf";
|
||||
/* function pointers */
|
||||
static HMODULE hSetupAPI;
|
||||
static LPCWSTR (WINAPI *pSetupGetField)(PINFCONTEXT,DWORD);
|
||||
|
||||
static void init_function_pointers(void)
|
||||
{
|
||||
hSetupAPI = GetModuleHandleA("setupapi.dll");
|
||||
|
||||
pSetupGetField = (void *)GetProcAddress(hSetupAPI, "pSetupGetField");
|
||||
}
|
||||
|
||||
static const char tmpfilename[] = ".\\tmp.inf";
|
||||
|
||||
/* some large strings */
|
||||
#define A255 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
|
||||
@@ -49,18 +60,19 @@ static const char tmpfile[] = ".\\tmp.inf";
|
||||
#define STR_SECTION "[Strings]\nfoo=aaa\nbar=bbb\nloop=%loop2%\nloop2=%loop%\n" \
|
||||
"per%%cent=abcd\nper=1\ncent=2\n22=foo\n" \
|
||||
"big=" A400 "\n" \
|
||||
"mydrive=\"C:\\\"\n" \
|
||||
"verybig=" A400 A400 A400 "\n"
|
||||
|
||||
/* create a new file with specified contents and open it */
|
||||
static HINF test_file_contents( const char *data, UINT *err_line )
|
||||
{
|
||||
DWORD res;
|
||||
HANDLE handle = CreateFileA( tmpfile, GENERIC_READ|GENERIC_WRITE,
|
||||
HANDLE handle = CreateFileA( tmpfilename, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
if (handle == INVALID_HANDLE_VALUE) return 0;
|
||||
if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" );
|
||||
CloseHandle( handle );
|
||||
return SetupOpenInfFileA( tmpfile, 0, INF_STYLE_WIN4, err_line );
|
||||
return SetupOpenInfFileA( tmpfilename, 0, INF_STYLE_WIN4, err_line );
|
||||
}
|
||||
|
||||
static const char *get_string_field( INFCONTEXT *context, DWORD index )
|
||||
@@ -130,20 +142,20 @@ static void test_invalid_files(void)
|
||||
err_line = 0xdeadbeef;
|
||||
hinf = test_file_contents( invalid_files[i].data, &err_line );
|
||||
err = GetLastError();
|
||||
trace( "hinf=%p err=%lx line=%d\n", hinf, err, err_line );
|
||||
trace( "hinf=%p err=0x%x line=%d\n", hinf, err, err_line );
|
||||
if (invalid_files[i].error) /* should fail */
|
||||
{
|
||||
ok( hinf == INVALID_HANDLE_VALUE, "file %u: Open succeeded\n", i );
|
||||
if (invalid_files[i].todo) todo_wine
|
||||
{
|
||||
ok( err == invalid_files[i].error, "file %u: Bad error %lx/%lx\n",
|
||||
ok( err == invalid_files[i].error, "file %u: Bad error %u/%u\n",
|
||||
i, err, invalid_files[i].error );
|
||||
ok( err_line == invalid_files[i].err_line, "file %u: Bad error line %d/%d\n",
|
||||
i, err_line, invalid_files[i].err_line );
|
||||
}
|
||||
else
|
||||
{
|
||||
ok( err == invalid_files[i].error, "file %u: Bad error %lx/%lx\n",
|
||||
ok( err == invalid_files[i].error, "file %u: Bad error %u/%u\n",
|
||||
i, err, invalid_files[i].error );
|
||||
ok( err_line == invalid_files[i].err_line, "file %u: Bad error line %d/%d\n",
|
||||
i, err_line, invalid_files[i].err_line );
|
||||
@@ -152,9 +164,9 @@ static void test_invalid_files(void)
|
||||
else /* should succeed */
|
||||
{
|
||||
ok( hinf != INVALID_HANDLE_VALUE, "file %u: Open failed\n", i );
|
||||
ok( err == 0, "file %u: Error code set to %lx\n", i, err );
|
||||
ok( err == 0, "file %u: Error code set to %u\n", i, err );
|
||||
}
|
||||
if (hinf != INVALID_HANDLE_VALUE) SetupCloseInfFile( hinf );
|
||||
SetupCloseInfFile( hinf );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,23 +222,23 @@ static void test_section_names(void)
|
||||
{
|
||||
SetLastError( 0xdeadbeef );
|
||||
hinf = test_file_contents( section_names[i].data, &err_line );
|
||||
ok( hinf != INVALID_HANDLE_VALUE, "line %u: open failed err %lx\n", i, GetLastError() );
|
||||
ok( hinf != INVALID_HANDLE_VALUE, "line %u: open failed err %u\n", i, GetLastError() );
|
||||
if (hinf == INVALID_HANDLE_VALUE) continue;
|
||||
|
||||
ret = SetupGetLineCountA( hinf, section_names[i].section );
|
||||
err = GetLastError();
|
||||
trace( "hinf=%p ret=%ld err=%lx\n", hinf, ret, err );
|
||||
trace( "hinf=%p ret=%d err=0x%x\n", hinf, ret, err );
|
||||
if (ret != -1)
|
||||
{
|
||||
ok( !section_names[i].error, "line %u: section name %s found\n",
|
||||
i, section_names[i].section );
|
||||
ok( !err, "line %u: bad error code %lx\n", i, err );
|
||||
ok( !err, "line %u: bad error code %u\n", i, err );
|
||||
}
|
||||
else
|
||||
{
|
||||
ok( section_names[i].error, "line %u: section name %s not found\n",
|
||||
i, section_names[i].section );
|
||||
ok( err == section_names[i].error, "line %u: bad error %lx/%lx\n",
|
||||
ok( err == section_names[i].error, "line %u: bad error %u/%u\n",
|
||||
i, err, section_names[i].error );
|
||||
}
|
||||
SetupCloseInfFile( hinf );
|
||||
@@ -273,6 +285,9 @@ static const struct
|
||||
{ "ab=cd\",\"ef", "ab", { "cd,ef" } },
|
||||
{ "ab=cd\",ef", "ab", { "cd,ef" } },
|
||||
{ "ab=cd\",ef\\\nab", "ab", { "cd,ef\\" } },
|
||||
|
||||
/* single quotes (unhandled)*/
|
||||
{ "HKLM,A,B,'C',D", NULL, { "HKLM", "A","B","'C'","D" } },
|
||||
/* spaces */
|
||||
{ " a b = c , d \n", "a b", { "c", "d" } },
|
||||
{ " a b = c ,\" d\" \n", "a b", { "c", " d" } },
|
||||
@@ -304,6 +319,16 @@ static const struct
|
||||
{ "a=%big%%big%%big%%big%\n" STR_SECTION, "a", { A400 A400 A400 A400 } },
|
||||
{ "a=%big%%big%%big%%big%%big%%big%%big%%big%%big%\n" STR_SECTION, "a", { A400 A400 A400 A400 A400 A400 A400 A400 A400 } },
|
||||
{ "a=%big%%big%%big%%big%%big%%big%%big%%big%%big%%big%%big%\n" STR_SECTION, "a", { A4097 /*MAX_INF_STRING_LENGTH+1*/ } },
|
||||
|
||||
/* Prove expansion of system entries removes extra \'s and string
|
||||
replacements doesn't */
|
||||
{ "ab=\"%24%\"\n" STR_SECTION, "ab", { "C:\\" } },
|
||||
{ "ab=\"%mydrive%\"\n" STR_SECTION, "ab", { "C:\\" } },
|
||||
{ "ab=\"%24%\\fred\"\n" STR_SECTION, "ab", { "C:\\fred" } },
|
||||
{ "ab=\"%mydrive%\\fred\"\n" STR_SECTION,"ab", { "C:\\\\fred" } },
|
||||
/* Confirm duplicate \'s kept */
|
||||
{ "ab=\"%24%\\\\fred\"", "ab", { "C:\\\\fred" } },
|
||||
{ "ab=C:\\\\FRED", "ab", { "C:\\\\FRED" } },
|
||||
};
|
||||
|
||||
/* check the key of a certain line */
|
||||
@@ -315,12 +340,12 @@ static const char *check_key( INFCONTEXT *context, const char *wanted )
|
||||
if (!key)
|
||||
{
|
||||
ok( !wanted, "missing key %s\n", wanted );
|
||||
ok( err == 0 || err == ERROR_INVALID_PARAMETER, "last error set to %lx\n", err );
|
||||
ok( err == 0 || err == ERROR_INVALID_PARAMETER, "last error set to %u\n", err );
|
||||
}
|
||||
else
|
||||
{
|
||||
ok( !strcmp( key, wanted ), "bad key %s/%s\n", key, wanted );
|
||||
ok( err == 0, "last error set to %lx\n", err );
|
||||
ok( err == 0, "last error set to %u\n", err );
|
||||
}
|
||||
return key;
|
||||
}
|
||||
@@ -342,7 +367,7 @@ static void test_key_names(void)
|
||||
strcat( buffer, key_names[i].data );
|
||||
SetLastError( 0xdeadbeef );
|
||||
hinf = test_file_contents( buffer, &err_line );
|
||||
ok( hinf != INVALID_HANDLE_VALUE, "line %u: open failed err %lx\n", i, GetLastError() );
|
||||
ok( hinf != INVALID_HANDLE_VALUE, "line %u: open failed err %u\n", i, GetLastError() );
|
||||
if (hinf == INVALID_HANDLE_VALUE) continue;
|
||||
|
||||
ret = SetupFindFirstLineA( hinf, "Test", 0, &context );
|
||||
@@ -357,7 +382,7 @@ static void test_key_names(void)
|
||||
err = GetLastError();
|
||||
if (field)
|
||||
{
|
||||
ok( err == 0, "line %u: bad error %lx\n", i, GetLastError() );
|
||||
ok( err == 0, "line %u: bad error %u\n", i, err );
|
||||
if (key_names[i].fields[index])
|
||||
ok( !strcmp( field, key_names[i].fields[index] ), "line %u: bad field %s/%s\n",
|
||||
i, field, key_names[i].fields[index] );
|
||||
@@ -369,7 +394,7 @@ static void test_key_names(void)
|
||||
else
|
||||
{
|
||||
ok( err == 0 || err == ERROR_INVALID_PARAMETER,
|
||||
"line %u: bad error %lx\n", i, GetLastError() );
|
||||
"line %u: bad error %u\n", i, err );
|
||||
if (key_names[i].fields[index])
|
||||
ok( 0, "line %u: missing field %s\n", i, key_names[i].fields[index] );
|
||||
}
|
||||
@@ -387,18 +412,253 @@ static void test_key_names(void)
|
||||
|
||||
}
|
||||
|
||||
static void test_SetupCloseInfFile(void)
|
||||
static void test_close_inf_file(void)
|
||||
{
|
||||
/* try to close with invalid handles */
|
||||
SetupCloseInfFile( NULL );
|
||||
SetupCloseInfFile( INVALID_HANDLE_VALUE );
|
||||
SetLastError(0xdeadbeef);
|
||||
SetupCloseInfFile(NULL);
|
||||
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
SetupCloseInfFile(INVALID_HANDLE_VALUE);
|
||||
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", GetLastError());
|
||||
|
||||
}
|
||||
|
||||
static const char *contents = "[Version]\n"
|
||||
"Signature=\"$Windows NT$\"\n"
|
||||
"FileVersion=5.1.1.2\n"
|
||||
"[FileBranchInfo]\n"
|
||||
"RTMQFE=\"%RTMGFE_NAME%\",SP1RTM,"A4097"\n"
|
||||
"[Strings]\n"
|
||||
"RTMQFE_NAME = \"RTMQFE\"\n";
|
||||
|
||||
static const WCHAR getfield_res[][20] =
|
||||
{
|
||||
{'R','T','M','Q','F','E',0},
|
||||
{'%','R','T','M','G','F','E','_','N','A','M','E','%',0},
|
||||
{'S','P','1','R','T','M',0},
|
||||
};
|
||||
|
||||
static void test_pSetupGetField(void)
|
||||
{
|
||||
UINT err;
|
||||
BOOL ret;
|
||||
HINF hinf;
|
||||
LPCWSTR field;
|
||||
INFCONTEXT context;
|
||||
int i;
|
||||
|
||||
hinf = test_file_contents( contents, &err );
|
||||
ok( hinf != NULL, "Expected valid INF file\n" );
|
||||
|
||||
ret = SetupFindFirstLine( hinf, "FileBranchInfo", NULL, &context );
|
||||
ok( ret, "Failed to find first line\n" );
|
||||
|
||||
/* native Windows crashes if a NULL context is sent in */
|
||||
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
field = pSetupGetField( &context, i );
|
||||
ok( field != NULL, "Failed to get field %i\n", i );
|
||||
ok( !lstrcmpW( getfield_res[i], field ), "Wrong string returned\n" );
|
||||
}
|
||||
|
||||
field = pSetupGetField( &context, 3 );
|
||||
ok( field != NULL, "Failed to get field 3\n" );
|
||||
ok( lstrlenW( field ) == 511, "Expected 511, got %d\n", lstrlenW( field ) );
|
||||
|
||||
field = pSetupGetField( &context, 4 );
|
||||
ok( field == NULL, "Expected NULL, got %p\n", field );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
|
||||
|
||||
SetupCloseInfFile( hinf );
|
||||
}
|
||||
|
||||
static void test_SetupGetIntField(void)
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
const char *key;
|
||||
const char *fields;
|
||||
DWORD index;
|
||||
INT value;
|
||||
DWORD err;
|
||||
} keys[] =
|
||||
{
|
||||
/* key fields index expected int errorcode */
|
||||
{ "Key=", "48", 1, 48, ERROR_SUCCESS },
|
||||
{ "Key=", "48", 0, -1, ERROR_INVALID_DATA },
|
||||
{ "123=", "48", 0, 123, ERROR_SUCCESS },
|
||||
{ "Key=", "0x4", 1, 4, ERROR_SUCCESS },
|
||||
{ "Key=", "Field1", 1, -1, ERROR_INVALID_DATA },
|
||||
{ "Key=", "Field1,34", 2, 34, ERROR_SUCCESS },
|
||||
{ "Key=", "Field1,,Field3", 2, 0, ERROR_SUCCESS },
|
||||
{ "Key=", "Field1,", 2, 0, ERROR_SUCCESS }
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++)
|
||||
{
|
||||
HINF hinf;
|
||||
char buffer[MAX_INF_STRING_LENGTH];
|
||||
INFCONTEXT context;
|
||||
UINT err;
|
||||
BOOL retb;
|
||||
INT intfield;
|
||||
|
||||
strcpy( buffer, STD_HEADER "[TestSection]\n" );
|
||||
strcat( buffer, keys[i].key );
|
||||
strcat( buffer, keys[i].fields );
|
||||
hinf = test_file_contents( buffer, &err);
|
||||
ok( hinf != NULL, "Expected valid INF file\n" );
|
||||
|
||||
SetupFindFirstLineA( hinf, "TestSection", "Key", &context );
|
||||
SetLastError( 0xdeadbeef );
|
||||
intfield = -1;
|
||||
retb = SetupGetIntField( &context, keys[i].index, &intfield );
|
||||
if ( keys[i].err == ERROR_SUCCESS )
|
||||
{
|
||||
ok( retb, "Expected success\n" );
|
||||
ok( GetLastError() == ERROR_SUCCESS ||
|
||||
GetLastError() == 0xdeadbeef /* win9x, NT4 */,
|
||||
"Expected ERROR_SUCCESS or 0xdeadbeef, got %u\n", GetLastError() );
|
||||
}
|
||||
else
|
||||
{
|
||||
ok( !retb, "Expected failure\n" );
|
||||
ok( GetLastError() == keys[i].err,
|
||||
"Expected %d, got %u\n", keys[i].err, GetLastError() );
|
||||
}
|
||||
ok( intfield == keys[i].value, "Expected %d, got %d\n", keys[i].value, intfield );
|
||||
|
||||
SetupCloseInfFile( hinf );
|
||||
}
|
||||
}
|
||||
|
||||
static void test_GLE(void)
|
||||
{
|
||||
static const char *inf =
|
||||
"[Version]\n"
|
||||
"Signature=\"$Windows NT$\"\n"
|
||||
"[Sectionname]\n"
|
||||
"Keyname1=Field1,Field2,Field3\n"
|
||||
"\n"
|
||||
"Keyname2=Field4,Field5\n";
|
||||
HINF hinf;
|
||||
UINT err;
|
||||
INFCONTEXT context;
|
||||
BOOL retb;
|
||||
LONG retl;
|
||||
char buf[MAX_INF_STRING_LENGTH];
|
||||
int bufsize = MAX_INF_STRING_LENGTH;
|
||||
DWORD retsize;
|
||||
|
||||
hinf = test_file_contents( inf, &err );
|
||||
ok( hinf != NULL, "Expected valid INF file\n" );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupFindFirstLineA( hinf, "ImNotThere", NULL, &context );
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupFindFirstLineA( hinf, "ImNotThere", "ImNotThere", &context );
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupFindFirstLineA( hinf, "Sectionname", NULL, &context );
|
||||
ok(retb, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS,
|
||||
"Expected ERROR_SUCCESS, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupFindFirstLineA( hinf, "Sectionname", "ImNotThere", &context );
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupFindFirstLineA( hinf, "Sectionname", "Keyname1", &context );
|
||||
ok(retb, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS,
|
||||
"Expected ERROR_SUCCESS, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupFindNextMatchLineA( &context, "ImNotThere", &context );
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupFindNextMatchLineA( &context, "Keyname2", &context );
|
||||
ok(retb, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS,
|
||||
"Expected ERROR_SUCCESS, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retl = SetupGetLineCountA( hinf, "ImNotThere");
|
||||
ok(retl == -1, "Expected -1, got %d\n", retl);
|
||||
ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
|
||||
"Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retl = SetupGetLineCountA( hinf, "Sectionname");
|
||||
ok(retl == 2, "Expected 2, got %d\n", retl);
|
||||
ok(GetLastError() == ERROR_SUCCESS,
|
||||
"Expected ERROR_SUCCESS, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupGetLineTextA( NULL, hinf, "ImNotThere", "ImNotThere", buf, bufsize, &retsize);
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupGetLineTextA( NULL, hinf, "Sectionname", "ImNotThere", buf, bufsize, &retsize);
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupGetLineTextA( NULL, hinf, "Sectionname", "Keyname1", buf, bufsize, &retsize);
|
||||
ok(retb, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS,
|
||||
"Expected ERROR_SUCCESS, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupGetLineByIndexA( hinf, "ImNotThere", 1, &context );
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupGetLineByIndexA( hinf, "Sectionname", 1, &context );
|
||||
ok(retb, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS,
|
||||
"Expected ERROR_SUCCESS, got %08x\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
retb = SetupGetLineByIndexA( hinf, "Sectionname", 3, &context );
|
||||
ok(!retb, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_LINE_NOT_FOUND,
|
||||
"Expected ERROR_LINE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
SetupCloseInfFile( hinf );
|
||||
}
|
||||
|
||||
START_TEST(parser)
|
||||
{
|
||||
init_function_pointers();
|
||||
test_invalid_files();
|
||||
test_section_names();
|
||||
test_key_names();
|
||||
test_SetupCloseInfFile();
|
||||
DeleteFileA( tmpfile );
|
||||
test_close_inf_file();
|
||||
test_pSetupGetField();
|
||||
test_SetupGetIntField();
|
||||
test_GLE();
|
||||
DeleteFileA( tmpfilename );
|
||||
}
|
||||
|
||||
@@ -23,29 +23,9 @@
|
||||
#include <setupapi.h>
|
||||
#include "wine/test.h"
|
||||
|
||||
/* function pointers */
|
||||
static HMODULE hSetupAPI;
|
||||
static void (WINAPI *pSetupCloseInfFile)(HINF);
|
||||
static BOOL (WINAPI *pSetupGetInfInformationA)(LPCVOID,DWORD,PSP_INF_INFORMATION,DWORD,PDWORD);
|
||||
static HINF (WINAPI *pSetupOpenInfFileA)(PCSTR,PCSTR,DWORD,PUINT);
|
||||
static BOOL (WINAPI *pSetupQueryInfFileInformationA)(PSP_INF_INFORMATION,UINT,PSTR,DWORD,PDWORD);
|
||||
|
||||
CHAR CURR_DIR[MAX_PATH];
|
||||
CHAR WIN_DIR[MAX_PATH];
|
||||
|
||||
static void init_function_pointers(void)
|
||||
{
|
||||
hSetupAPI = LoadLibraryA("setupapi.dll");
|
||||
|
||||
if (hSetupAPI)
|
||||
{
|
||||
pSetupCloseInfFile = (void *)GetProcAddress(hSetupAPI, "SetupCloseInfFile");
|
||||
pSetupGetInfInformationA = (void *)GetProcAddress(hSetupAPI, "SetupGetInfInformationA");
|
||||
pSetupOpenInfFileA = (void *)GetProcAddress(hSetupAPI, "SetupOpenInfFileA");
|
||||
pSetupQueryInfFileInformationA = (void *)GetProcAddress(hSetupAPI, "SetupQueryInfFileInformationA");
|
||||
}
|
||||
}
|
||||
|
||||
static void get_directories(void)
|
||||
{
|
||||
int len;
|
||||
@@ -80,6 +60,37 @@ static void create_inf_file(LPSTR filename)
|
||||
append_str(&ptr, "[Version]\n");
|
||||
append_str(&ptr, "Signature=\"$Chicago$\"\n");
|
||||
append_str(&ptr, "AdvancedINF=2.5\n");
|
||||
append_str(&ptr, "[SourceDisksNames]\n");
|
||||
append_str(&ptr, "2 = %%SrcDiskName%%, LANCOM\\LANtools\\lanconf.cab\n");
|
||||
append_str(&ptr, "[SourceDisksFiles]\n");
|
||||
append_str(&ptr, "lanconf.exe = 2\n");
|
||||
append_str(&ptr, "[DestinationDirs]\n");
|
||||
append_str(&ptr, "DefaultDestDir = 24, %%DefaultDest%%\n");
|
||||
append_str(&ptr, "[Strings]\n");
|
||||
append_str(&ptr, "LangDir = english\n");
|
||||
append_str(&ptr, "DefaultDest = LANCOM\n");
|
||||
append_str(&ptr, "SrcDiskName = \"LANCOM Software CD\"\n");
|
||||
|
||||
WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
|
||||
CloseHandle(hf);
|
||||
}
|
||||
|
||||
static void create_inf_file2(LPSTR filename)
|
||||
{
|
||||
char data[1024];
|
||||
char *ptr = data;
|
||||
DWORD dwNumberOfBytesWritten;
|
||||
HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
append_str(&ptr, "[SourceFileInfo]\n");
|
||||
append_str(&ptr, "sp1qfe\\bitsinst.exe=250B3702C7CCD7C2F9E4DAA1555C933E,000600060A28062C,27136,SP1QFE\n");
|
||||
append_str(&ptr, "sp1qfe\\bitsprx2.dll=4EBEA67F4BB4EB402E725CA7CA2857AE,000600060A280621,7680,SP1QFE\n");
|
||||
append_str(&ptr, "sp1qfe\\bitsprx3.dll=C788A1D9330DA011EF25E95D3BC7BDE5,000600060A280621,7168,SP1QFE\n");
|
||||
append_str(&ptr, "sp1qfe\\qmgr.dll=696AC82FB290A03F205901442E0E9589,000600060A280621,361984,SP1QFE\n");
|
||||
append_str(&ptr, "sp1qfe\\qmgrprxy.dll=8B5848144829E1BC985EA4C3D8CA7E3F,000600060A280621,17408,SP1QFE\n");
|
||||
append_str(&ptr, "sp1qfe\\winhttp.dll=3EC6F518114606CA59D4160322077437,000500010A280615,331776,SP1QFE\n");
|
||||
append_str(&ptr, "sp1qfe\\xpob2res.dll=DB83156B9F496F20D1EA70E4ABEC0166,000500010A280622,158720,SP1QFE\n");
|
||||
|
||||
WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
|
||||
CloseHandle(hf);
|
||||
@@ -91,14 +102,14 @@ static BOOL check_info_filename(PSP_INF_INFORMATION info, LPSTR test)
|
||||
DWORD size;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!pSetupQueryInfFileInformationA(info, 0, NULL, 0, &size))
|
||||
if (!SetupQueryInfFileInformationA(info, 0, NULL, 0, &size))
|
||||
return FALSE;
|
||||
|
||||
filename = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (!filename)
|
||||
return FALSE;
|
||||
|
||||
pSetupQueryInfFileInformationA(info, 0, filename, size, &size);
|
||||
SetupQueryInfFileInformationA(info, 0, filename, size, &size);
|
||||
|
||||
if (!lstrcmpiA(test, filename))
|
||||
ret = TRUE;
|
||||
@@ -107,12 +118,12 @@ static BOOL check_info_filename(PSP_INF_INFORMATION info, LPSTR test)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PSP_INF_INFORMATION alloc_inf_info(LPSTR filename, DWORD search, PDWORD size)
|
||||
static PSP_INF_INFORMATION alloc_inf_info(LPCSTR filename, DWORD search, PDWORD size)
|
||||
{
|
||||
PSP_INF_INFORMATION info;
|
||||
BOOL ret;
|
||||
|
||||
ret = pSetupGetInfInformationA(filename, search, NULL, 0, size);
|
||||
ret = SetupGetInfInformationA(filename, search, NULL, 0, size);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
@@ -136,19 +147,19 @@ static void test_SetupGetInfInformation(void)
|
||||
/* try an invalid inf handle */
|
||||
size = 0xdeadbeef;
|
||||
SetLastError(0xbeefcafe);
|
||||
ret = pSetupGetInfInformationA(NULL, INFINFO_INF_SPEC_IS_HINF, NULL, 0, &size);
|
||||
ret = SetupGetInfInformationA(NULL, INFINFO_INF_SPEC_IS_HINF, NULL, 0, &size);
|
||||
ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE,
|
||||
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
|
||||
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
|
||||
ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
|
||||
|
||||
/* try an invalid inf filename */
|
||||
size = 0xdeadbeef;
|
||||
SetLastError(0xbeefcafe);
|
||||
ret = pSetupGetInfInformationA(NULL, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
|
||||
ret = SetupGetInfInformationA(NULL, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
|
||||
ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
|
||||
|
||||
create_inf_file(inf_filename);
|
||||
@@ -156,57 +167,69 @@ static void test_SetupGetInfInformation(void)
|
||||
/* try an invalid search flag */
|
||||
size = 0xdeadbeef;
|
||||
SetLastError(0xbeefcafe);
|
||||
ret = pSetupGetInfInformationA(inf_filename, -1, NULL, 0, &size);
|
||||
ret = SetupGetInfInformationA(inf_filename, -1, NULL, 0, &size);
|
||||
ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
|
||||
|
||||
/* try a nonexistent inf file */
|
||||
size = 0xdeadbeef;
|
||||
SetLastError(0xbeefcafe);
|
||||
ret = pSetupGetInfInformationA("idontexist", INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
|
||||
ret = SetupGetInfInformationA("idontexist", INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
|
||||
ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
|
||||
|
||||
/* successfully open the inf file */
|
||||
size = 0xdeadbeef;
|
||||
ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
ok(size != 0xdeadbeef, "Expected a valid size on return\n");
|
||||
|
||||
/* set ReturnBuffer to NULL and ReturnBufferSize to non-zero */
|
||||
/* set ReturnBuffer to NULL and ReturnBufferSize to non-zero value 'size' */
|
||||
SetLastError(0xbeefcafe);
|
||||
ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, &size);
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, &size);
|
||||
ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
/* set ReturnBuffer to NULL and ReturnBufferSize to non-zero value 'size-1' */
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size-1, &size);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
|
||||
/* some tests for behaviour with a NULL RequiredSize pointer */
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, NULL);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size - 1, NULL);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, NULL);
|
||||
ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
|
||||
|
||||
info = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
|
||||
/* try valid ReturnBuffer but too small size */
|
||||
SetLastError(0xbeefcafe);
|
||||
ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size - 1, &size);
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size - 1, &size);
|
||||
ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
|
||||
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
|
||||
|
||||
/* successfully get the inf information */
|
||||
ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size, &size);
|
||||
ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size, &size);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, info);
|
||||
|
||||
/* try the INFINFO_INF_SPEC_IS_HINF search flag */
|
||||
hinf = pSetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
|
||||
hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
|
||||
info = alloc_inf_info(hinf, INFINFO_INF_SPEC_IS_HINF, &size);
|
||||
ret = pSetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, info, size, &size);
|
||||
ret = SetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, info, size, &size);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
|
||||
pSetupCloseInfFile(hinf);
|
||||
SetupCloseInfFile(hinf);
|
||||
|
||||
lstrcpyA(inf_one, WIN_DIR);
|
||||
lstrcatA(inf_one, "\\inf\\");
|
||||
@@ -222,7 +245,7 @@ static void test_SetupGetInfInformation(void)
|
||||
info = alloc_inf_info("test.inf", INFINFO_DEFAULT_SEARCH, &size);
|
||||
|
||||
/* test the INFINFO_DEFAULT_SEARCH search flag */
|
||||
ret = pSetupGetInfInformationA("test.inf", INFINFO_DEFAULT_SEARCH, info, size, &size);
|
||||
ret = SetupGetInfInformationA("test.inf", INFINFO_DEFAULT_SEARCH, info, size, &size);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
ok(check_info_filename(info, inf_one), "Expected returned filename to be equal\n");
|
||||
|
||||
@@ -230,7 +253,7 @@ static void test_SetupGetInfInformation(void)
|
||||
info = alloc_inf_info("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, &size);
|
||||
|
||||
/* test the INFINFO_REVERSE_DEFAULT_SEARCH search flag */
|
||||
ret = pSetupGetInfInformationA("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, info, size, &size);
|
||||
ret = SetupGetInfInformationA("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, info, size, &size);
|
||||
ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
|
||||
ok(check_info_filename(info, inf_two), "Expected returned filename to be equal\n");
|
||||
|
||||
@@ -239,10 +262,140 @@ static void test_SetupGetInfInformation(void)
|
||||
DeleteFileA(inf_two);
|
||||
}
|
||||
|
||||
static void test_SetupGetSourceFileLocation(void)
|
||||
{
|
||||
char buffer[MAX_PATH] = "not empty", inf_filename[MAX_PATH];
|
||||
UINT source_id;
|
||||
DWORD required, error;
|
||||
HINF hinf;
|
||||
BOOL ret;
|
||||
|
||||
lstrcpyA(inf_filename, CURR_DIR);
|
||||
lstrcatA(inf_filename, "\\");
|
||||
lstrcatA(inf_filename, "test.inf");
|
||||
|
||||
create_inf_file(inf_filename);
|
||||
|
||||
hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
|
||||
ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
|
||||
|
||||
required = 0;
|
||||
source_id = 0;
|
||||
|
||||
ret = SetupGetSourceFileLocationA(hinf, NULL, "lanconf.exe", &source_id, buffer, sizeof(buffer), &required);
|
||||
ok(ret, "SetupGetSourceFileLocation failed\n");
|
||||
|
||||
ok(required == 1, "unexpected required size: %d\n", required);
|
||||
ok(source_id == 2, "unexpected source id: %d\n", source_id);
|
||||
ok(!lstrcmpA("", buffer), "unexpected result string: %s\n", buffer);
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
DeleteFileA(inf_filename);
|
||||
|
||||
create_inf_file2(inf_filename);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
|
||||
error = GetLastError();
|
||||
ok(hinf == INVALID_HANDLE_VALUE, "could open inf file\n");
|
||||
ok(error == ERROR_WRONG_INF_STYLE, "got wrong error: %d\n", error);
|
||||
|
||||
hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_OLDNT, NULL);
|
||||
ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
|
||||
|
||||
ret = SetupGetSourceFileLocationA(hinf, NULL, "", &source_id, buffer, sizeof(buffer), &required);
|
||||
ok(!ret, "SetupGetSourceFileLocation succeeded\n");
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
DeleteFileA(inf_filename);
|
||||
}
|
||||
|
||||
static void test_SetupGetSourceInfo(void)
|
||||
{
|
||||
char buffer[MAX_PATH], inf_filename[MAX_PATH];
|
||||
DWORD required;
|
||||
HINF hinf;
|
||||
BOOL ret;
|
||||
|
||||
lstrcpyA(inf_filename, CURR_DIR);
|
||||
lstrcatA(inf_filename, "\\");
|
||||
lstrcatA(inf_filename, "test.inf");
|
||||
|
||||
create_inf_file(inf_filename);
|
||||
|
||||
hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
|
||||
ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
|
||||
|
||||
required = 0;
|
||||
|
||||
ret = SetupGetSourceInfoA(hinf, 2, SRCINFO_PATH, buffer, sizeof(buffer), &required);
|
||||
ok(ret, "SetupGetSourceInfoA failed\n");
|
||||
|
||||
ok(required == 1, "unexpected required size: %d\n", required);
|
||||
ok(!lstrcmpA("", buffer), "unexpected result string: %s\n", buffer);
|
||||
|
||||
required = 0;
|
||||
buffer[0] = 0;
|
||||
|
||||
ret = SetupGetSourceInfoA(hinf, 2, SRCINFO_TAGFILE, buffer, sizeof(buffer), &required);
|
||||
ok(ret, "SetupGetSourceInfoA failed\n");
|
||||
|
||||
ok(required == 28, "unexpected required size: %d\n", required);
|
||||
ok(!lstrcmpA("LANCOM\\LANtools\\lanconf.cab", buffer), "unexpected result string: %s\n", buffer);
|
||||
|
||||
required = 0;
|
||||
buffer[0] = 0;
|
||||
|
||||
ret = SetupGetSourceInfoA(hinf, 2, SRCINFO_DESCRIPTION, buffer, sizeof(buffer), &required);
|
||||
ok(ret, "SetupGetSourceInfoA failed\n");
|
||||
|
||||
ok(required == 19, "unexpected required size: %d\n", required);
|
||||
ok(!lstrcmpA("LANCOM Software CD", buffer), "unexpected result string: %s\n", buffer);
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
DeleteFileA(inf_filename);
|
||||
}
|
||||
|
||||
static void test_SetupGetTargetPath(void)
|
||||
{
|
||||
char buffer[MAX_PATH], inf_filename[MAX_PATH];
|
||||
DWORD required;
|
||||
HINF hinf;
|
||||
INFCONTEXT ctx;
|
||||
BOOL ret;
|
||||
|
||||
lstrcpyA(inf_filename, CURR_DIR);
|
||||
lstrcatA(inf_filename, "\\");
|
||||
lstrcatA(inf_filename, "test.inf");
|
||||
|
||||
create_inf_file(inf_filename);
|
||||
|
||||
hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
|
||||
ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
|
||||
|
||||
ctx.Inf = hinf;
|
||||
ctx.CurrentInf = hinf;
|
||||
ctx.Section = 7;
|
||||
ctx.Line = 0;
|
||||
|
||||
required = 0;
|
||||
|
||||
ret = SetupGetTargetPathA(hinf, &ctx, NULL, buffer, sizeof(buffer), &required);
|
||||
ok(ret, "SetupGetTargetPathA failed\n");
|
||||
|
||||
ok(required == 10, "unexpected required size: %d\n", required);
|
||||
ok(!lstrcmpiA("C:\\LANCOM", buffer), "unexpected result string: %s\n", buffer);
|
||||
|
||||
SetupCloseInfFile(hinf);
|
||||
DeleteFileA(inf_filename);
|
||||
}
|
||||
|
||||
START_TEST(query)
|
||||
{
|
||||
init_function_pointers();
|
||||
get_directories();
|
||||
|
||||
test_SetupGetInfInformation();
|
||||
test_SetupGetSourceFileLocation();
|
||||
test_SetupGetSourceInfo();
|
||||
test_SetupGetTargetPath();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="setupapi_winetest" type="win32cui" installbase="bin" installname="setupapi_winetest.exe" allowwarnings="true">
|
||||
<include base="setupapi_winetest">.</include>
|
||||
<define name="__USE_W32API" />
|
||||
@@ -5,10 +8,14 @@
|
||||
<library>kernel32</library>
|
||||
<library>advapi32</library>
|
||||
<library>setupapi</library>
|
||||
<library>user32</library>
|
||||
<file>devclass.c</file>
|
||||
<file>devinst.c</file>
|
||||
<file>install.c</file>
|
||||
<file>misc.c</file>
|
||||
<file>parser.c</file>
|
||||
<file>query.c</file>
|
||||
<file>stringtable.c</file>
|
||||
<file>testlist.c</file>
|
||||
</module>
|
||||
</group>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
/*
|
||||
/*
|
||||
* TODO:
|
||||
* Add test for StringTableStringFromIdEx
|
||||
*/
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
/* Flags for StringTableAddString and StringTableLookUpString */
|
||||
#define ST_CASE_SENSITIVE_COMPARE 0x00000001
|
||||
|
||||
static DWORD (WINAPI *pStringTableAddString)(HSTRING_TABLE, LPWSTR, DWORD);
|
||||
static VOID (WINAPI *pStringTableDestroy)(HSTRING_TABLE);
|
||||
@@ -54,9 +56,7 @@ HANDLE table, table2; /* Handles pointing to our tables */
|
||||
|
||||
static void load_it_up(void)
|
||||
{
|
||||
hdll = LoadLibraryA("setupapi.dll");
|
||||
if (!hdll)
|
||||
return;
|
||||
hdll = GetModuleHandleA("setupapi.dll");
|
||||
|
||||
pStringTableInitialize = (void*)GetProcAddress(hdll, "StringTableInitialize");
|
||||
if (!pStringTableInitialize)
|
||||
@@ -96,18 +96,18 @@ static void test_StringTableAddString(void)
|
||||
/* case insensitive */
|
||||
hstring=pStringTableAddString(table,string,0);
|
||||
ok(hstring!=-1,"Failed to add string to String Table\n");
|
||||
|
||||
|
||||
retval=pStringTableAddString(table,String,0);
|
||||
ok(retval!=-1,"Failed to add String to String Table\n");
|
||||
ok(hstring==retval,"string handle %lx != String handle %lx in String Table\n", hstring, retval);
|
||||
|
||||
ok(retval!=-1,"Failed to add String to String Table\n");
|
||||
ok(hstring==retval,"string handle %x != String handle %x in String Table\n", hstring, retval);
|
||||
|
||||
hfoo=pStringTableAddString(table,foo,0);
|
||||
ok(hfoo!=-1,"Failed to add foo to String Table\n");
|
||||
ok(hfoo!=hstring,"foo and string share the same ID %lx in String Table\n", hfoo);
|
||||
|
||||
/* case sensitive */
|
||||
ok(hfoo!=-1,"Failed to add foo to String Table\n");
|
||||
ok(hfoo!=hstring,"foo and string share the same ID %x in String Table\n", hfoo);
|
||||
|
||||
/* case sensitive */
|
||||
hString=pStringTableAddString(table,String,ST_CASE_SENSITIVE_COMPARE);
|
||||
ok(hstring!=hString,"String handle and string share same ID %lx in Table\n", hstring);
|
||||
ok(hstring!=hString,"String handle and string share same ID %x in Table\n", hstring);
|
||||
}
|
||||
|
||||
static void test_StringTableDuplicate(void)
|
||||
@@ -117,41 +117,41 @@ static void test_StringTableDuplicate(void)
|
||||
}
|
||||
|
||||
static void test_StringTableLookUpString(void)
|
||||
{
|
||||
{
|
||||
DWORD retval, retval2;
|
||||
|
||||
|
||||
/* case insensitive */
|
||||
retval=pStringTableLookUpString(table,string,0);
|
||||
ok(retval!=-1,"Failed find string in String Table 1\n");
|
||||
ok(retval==hstring,
|
||||
"Lookup for string (%lx) does not match previous handle (%lx) in String Table 1\n",
|
||||
retval, hstring);
|
||||
"Lookup for string (%x) does not match previous handle (%x) in String Table 1\n",
|
||||
retval, hstring);
|
||||
|
||||
retval=pStringTableLookUpString(table2,string,0);
|
||||
ok(retval!=-1,"Failed find string in String Table 2\n");
|
||||
|
||||
|
||||
retval=pStringTableLookUpString(table,String,0);
|
||||
ok(retval!=-1,"Failed find String in String Table 1\n");
|
||||
|
||||
retval=pStringTableLookUpString(table2,String,0);
|
||||
ok(retval!=-1,"Failed find String in String Table 2\n");
|
||||
|
||||
ok(retval!=-1,"Failed find String in String Table 2\n");
|
||||
|
||||
retval=pStringTableLookUpString(table,foo,0);
|
||||
ok(retval!=-1,"Failed find foo in String Table 1\n");
|
||||
ok(retval!=-1,"Failed find foo in String Table 1\n");
|
||||
ok(retval==hfoo,
|
||||
"Lookup for foo (%lx) does not match previous handle (%lx) in String Table 1\n",
|
||||
retval, hfoo);
|
||||
|
||||
"Lookup for foo (%x) does not match previous handle (%x) in String Table 1\n",
|
||||
retval, hfoo);
|
||||
|
||||
retval=pStringTableLookUpString(table2,foo,0);
|
||||
ok(retval!=-1,"Failed find foo in String Table 2\n");
|
||||
|
||||
ok(retval!=-1,"Failed find foo in String Table 2\n");
|
||||
|
||||
/* case sensitive */
|
||||
retval=pStringTableLookUpString(table,string,ST_CASE_SENSITIVE_COMPARE);
|
||||
retval2=pStringTableLookUpString(table,String,ST_CASE_SENSITIVE_COMPARE);
|
||||
retval2=pStringTableLookUpString(table,String,ST_CASE_SENSITIVE_COMPARE);
|
||||
ok(retval!=retval2,"Lookup of string equals String in Table 1\n");
|
||||
ok(retval2==hString,
|
||||
"Lookup for String (%lx) does not match previous handle (%lx) in String Table 1\n",
|
||||
retval, hString);
|
||||
"Lookup for String (%x) does not match previous handle (%x) in String Table 1\n",
|
||||
retval, hString);
|
||||
}
|
||||
|
||||
static void test_StringTableStringFromId(void)
|
||||
@@ -162,7 +162,7 @@ static void test_StringTableStringFromId(void)
|
||||
/* correct */
|
||||
string2=pStringTableStringFromId(table,pStringTableLookUpString(table,string,0));
|
||||
ok(string2!=NULL,"Failed to look up string by ID from String Table\n");
|
||||
|
||||
|
||||
result=lstrcmpiW(string, string2);
|
||||
ok(result==0,"StringID %p does not match requested StringID %p\n",string,string2);
|
||||
|
||||
@@ -184,9 +184,7 @@ START_TEST(stringtable)
|
||||
test_StringTableLookUpString();
|
||||
test_StringTableStringFromId();
|
||||
|
||||
/* assume we can always distroy */
|
||||
/* assume we can always destroy */
|
||||
pStringTableDestroy(table);
|
||||
pStringTableDestroy(table2);
|
||||
|
||||
FreeLibrary(hdll);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include "wine/test.h"
|
||||
|
||||
extern void func_devclass(void);
|
||||
extern void func_devinst(void);
|
||||
extern void func_install(void);
|
||||
extern void func_misc(void);
|
||||
extern void func_parser(void);
|
||||
extern void func_query(void);
|
||||
extern void func_stringtable(void);
|
||||
@@ -15,7 +17,9 @@ extern void func_stringtable(void);
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "devclass", func_devclass },
|
||||
{ "devinst", func_devinst },
|
||||
{ "install", func_install },
|
||||
{ "misc", func_misc },
|
||||
{ "parser", func_parser },
|
||||
{ "query", func_query },
|
||||
{ "stringtable", func_stringtable },
|
||||
|
||||
@@ -76,35 +76,40 @@ static void test_IStream_invalid_operations(IStream * stream, DWORD mode)
|
||||
|
||||
ret = stream->lpVtbl->Write(stream, NULL, 0, &count);
|
||||
if (mode == STGM_READ)
|
||||
ok(ret == STG_E_ACCESSDENIED, "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
|
||||
ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
|
||||
"expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
|
||||
else
|
||||
ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
|
||||
|
||||
strcpy(data, "Hello");
|
||||
ret = stream->lpVtbl->Write(stream, data, 5, NULL);
|
||||
if (mode == STGM_READ)
|
||||
ok(ret == STG_E_ACCESSDENIED, "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
|
||||
ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
|
||||
"expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
|
||||
else
|
||||
ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
|
||||
|
||||
strcpy(data, "Hello");
|
||||
ret = stream->lpVtbl->Write(stream, data, 0, NULL);
|
||||
if (mode == STGM_READ)
|
||||
ok(ret == STG_E_ACCESSDENIED, "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
|
||||
ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
|
||||
"expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
|
||||
else
|
||||
ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
|
||||
|
||||
strcpy(data, "Hello");
|
||||
ret = stream->lpVtbl->Write(stream, data, 0, &count);
|
||||
if (mode == STGM_READ)
|
||||
ok(ret == STG_E_ACCESSDENIED, "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
|
||||
ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
|
||||
"expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
|
||||
else
|
||||
ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
|
||||
|
||||
strcpy(data, "Hello");
|
||||
ret = stream->lpVtbl->Write(stream, data, 3, &count);
|
||||
if (mode == STGM_READ)
|
||||
ok(ret == STG_E_ACCESSDENIED, "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
|
||||
ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
|
||||
"expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
|
||||
else
|
||||
ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
|
||||
|
||||
@@ -114,7 +119,8 @@ static void test_IStream_invalid_operations(IStream * stream, DWORD mode)
|
||||
ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
|
||||
|
||||
ret = IStream_Seek(stream, zero, 20, NULL);
|
||||
ok(ret == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(ret == E_INVALIDARG /* XP */ || ret == S_OK /* 2000 */,
|
||||
"expected E_INVALIDARG or S_OK, got 0x%08x\n", ret);
|
||||
|
||||
/* IStream::CopyTo */
|
||||
|
||||
@@ -166,7 +172,8 @@ static void test_IStream_invalid_operations(IStream * stream, DWORD mode)
|
||||
/* IStream::Stat */
|
||||
|
||||
ret = IStream_Stat(stream, NULL, 0);
|
||||
ok(ret == STG_E_INVALIDPOINTER, "expected STG_E_INVALIDPOINTER, got 0x%08x\n", ret);
|
||||
ok(ret == STG_E_INVALIDPOINTER /* XP */ || ret == E_NOTIMPL /* 2000 */,
|
||||
"expected STG_E_INVALIDPOINTER or E_NOTIMPL, got 0x%08x\n", ret);
|
||||
|
||||
/* IStream::Clone */
|
||||
|
||||
@@ -185,56 +192,52 @@ static void test_IStream_invalid_operations(IStream * stream, DWORD mode)
|
||||
}
|
||||
|
||||
|
||||
static void test_SHCreateStreamOnFileA(DWORD mode)
|
||||
static void test_SHCreateStreamOnFileA(DWORD mode, DWORD stgm)
|
||||
{
|
||||
IStream * stream;
|
||||
HRESULT ret;
|
||||
ULONG refcount;
|
||||
static const char * test_file = "c:\\test.txt";
|
||||
|
||||
trace("SHCreateStreamOnFileA: testing mode %d\n", mode);
|
||||
trace("SHCreateStreamOnFileA: testing mode %d, STGM flags %08x\n", mode, stgm);
|
||||
|
||||
/* invalid arguments */
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(NULL, mode, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileA)(NULL, mode | stgm, &stream);
|
||||
ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
#if 0 /* This test crashes on WinXP SP2 */
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode, NULL);
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | stgm, NULL);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
#endif
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CONVERT, &stream);
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CONVERT | stgm, &stream);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_DELETEONRELEASE, &stream);
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_TRANSACTED, &stream);
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_TRANSACTED | stgm, &stream);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
/* file does not exist */
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
|
||||
ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE | stgm, &stream);
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -249,10 +252,8 @@ static void test_SHCreateStreamOnFileA(DWORD mode)
|
||||
/* file exists */
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -263,10 +264,8 @@ static void test_SHCreateStreamOnFileA(DWORD mode)
|
||||
}
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE | stgm, &stream);
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -280,57 +279,54 @@ static void test_SHCreateStreamOnFileA(DWORD mode)
|
||||
}
|
||||
|
||||
|
||||
static void test_SHCreateStreamOnFileW(DWORD mode)
|
||||
static void test_SHCreateStreamOnFileW(DWORD mode, DWORD stgm)
|
||||
{
|
||||
IStream * stream;
|
||||
HRESULT ret;
|
||||
ULONG refcount;
|
||||
static const WCHAR test_file[] = { 'c', ':', '\\', 't', 'e', 's', 't', '.', 't', 'x', 't', '\0' };
|
||||
|
||||
trace("SHCreateStreamOnFileW: testing mode %d\n", mode);
|
||||
trace("SHCreateStreamOnFileW: testing mode %d, STGM flags %08x\n", mode, stgm);
|
||||
|
||||
/* invalid arguments */
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(NULL, mode, &stream);
|
||||
ret = (*pSHCreateStreamOnFileW)(NULL, mode | stgm, &stream);
|
||||
ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
|
||||
ret == E_INVALIDARG /* Vista */,
|
||||
"SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
#if 0 /* This test crashes on WinXP SP2 */
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode, NULL);
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | stgm, NULL);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
#endif
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CONVERT, &stream);
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CONVERT | stgm, &stream);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_DELETEONRELEASE, &stream);
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_TRANSACTED, &stream);
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_TRANSACTED | stgm, &stream);
|
||||
ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
/* file does not exist */
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
|
||||
ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE | stgm, &stream);
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -345,10 +341,8 @@ static void test_SHCreateStreamOnFileW(DWORD mode)
|
||||
/* file exists */
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -359,10 +353,8 @@ static void test_SHCreateStreamOnFileW(DWORD mode)
|
||||
}
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE, &stream);
|
||||
todo_wine
|
||||
ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE | stgm, &stream);
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -397,7 +389,6 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, template, &stream);
|
||||
todo_wine
|
||||
ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
@@ -419,16 +410,13 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
todo_wine
|
||||
ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
|
||||
}
|
||||
ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
|
||||
todo_wine
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -442,9 +430,7 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
|
||||
todo_wine
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -458,9 +444,7 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
|
||||
todo_wine
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -476,9 +460,7 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
|
||||
todo_wine
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -490,15 +472,12 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
|
||||
todo_wine
|
||||
ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), got 0x%08x\n", ret);
|
||||
ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
|
||||
todo_wine
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -510,9 +489,7 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
|
||||
stream = NULL;
|
||||
ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
|
||||
todo_wine
|
||||
ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
|
||||
todo_wine
|
||||
ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
|
||||
|
||||
if (stream) {
|
||||
@@ -522,7 +499,6 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
|
||||
ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
|
||||
}
|
||||
|
||||
todo_wine
|
||||
ok(DeleteFileW(test_file), "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n", GetLastError());
|
||||
}
|
||||
|
||||
@@ -535,6 +511,14 @@ START_TEST(istream)
|
||||
STGM_READWRITE
|
||||
};
|
||||
|
||||
static const DWORD stgm_sharing[] = {
|
||||
0,
|
||||
STGM_SHARE_DENY_NONE,
|
||||
STGM_SHARE_DENY_READ,
|
||||
STGM_SHARE_DENY_WRITE,
|
||||
STGM_SHARE_EXCLUSIVE
|
||||
};
|
||||
|
||||
static const DWORD stgm_flags[] = {
|
||||
0,
|
||||
STGM_CONVERT,
|
||||
@@ -545,7 +529,7 @@ START_TEST(istream)
|
||||
STGM_TRANSACTED | STGM_CONVERT | STGM_DELETEONRELEASE
|
||||
};
|
||||
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
|
||||
hShlwapi = GetModuleHandleA("shlwapi.dll");
|
||||
|
||||
@@ -563,15 +547,17 @@ START_TEST(istream)
|
||||
skip("SHCreateStreamOnFileEx not found.\n");
|
||||
|
||||
for (i = 0; i != sizeof(stgm_access)/sizeof(stgm_access[0]); i++) {
|
||||
if (pSHCreateStreamOnFileA)
|
||||
test_SHCreateStreamOnFileA(stgm_access[i]);
|
||||
for (j = 0; j != sizeof(stgm_sharing)/sizeof(stgm_sharing[0]); j ++) {
|
||||
if (pSHCreateStreamOnFileA)
|
||||
test_SHCreateStreamOnFileA(stgm_access[i], stgm_sharing[j]);
|
||||
|
||||
if (pSHCreateStreamOnFileW)
|
||||
test_SHCreateStreamOnFileW(stgm_access[i]);
|
||||
if (pSHCreateStreamOnFileW)
|
||||
test_SHCreateStreamOnFileW(stgm_access[i], stgm_sharing[j]);
|
||||
|
||||
if (pSHCreateStreamOnFileEx) {
|
||||
for (j = 0; j != sizeof(stgm_flags)/sizeof(stgm_flags[0]); j++)
|
||||
test_SHCreateStreamOnFileEx(stgm_access[i], stgm_flags[j]);
|
||||
if (pSHCreateStreamOnFileEx) {
|
||||
for (k = 0; k != sizeof(stgm_flags)/sizeof(stgm_flags[0]); k++)
|
||||
test_SHCreateStreamOnFileEx(stgm_access[i], stgm_sharing[j] | stgm_flags[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="shlwapi_winetest" type="win32cui" installbase="bin" installname="shlwapi_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="shlwapi_winetest" type="win32cui" installbase="bin" installname="shlwapi_winetest.exe" allowwarnings="true">
|
||||
<include base="shlwapi_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -45,49 +45,61 @@ typedef struct _TEST_URL_CANONICALIZE {
|
||||
DWORD flags;
|
||||
HRESULT expectret;
|
||||
const char *expecturl;
|
||||
BOOL todo;
|
||||
} TEST_URL_CANONICALIZE;
|
||||
|
||||
static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
|
||||
/*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
|
||||
{"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
|
||||
{"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
|
||||
{"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
|
||||
{"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
|
||||
{"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
|
||||
{"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
|
||||
{"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
|
||||
{"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/"},
|
||||
{"http://www.winehq.org/tests/..", 0, S_OK, "http://www.winehq.org/"},
|
||||
{"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/"},
|
||||
{"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
|
||||
{"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
|
||||
{"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example"},
|
||||
{"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
|
||||
{"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example"},
|
||||
{"http://www.winehq.org/tests/..\\#example", 0, S_OK, "http://www.winehq.org/#example"},
|
||||
{"http://www.winehq.org\\tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
|
||||
{"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
|
||||
{"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar"},
|
||||
{"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"},
|
||||
{"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
|
||||
{"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
|
||||
{"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
|
||||
{"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
|
||||
{"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
|
||||
{"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
|
||||
{"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
|
||||
{"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar"},
|
||||
{"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"},
|
||||
{"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"},
|
||||
{"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about"},
|
||||
{"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about"},
|
||||
{"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
|
||||
{"file:///c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
|
||||
{"c:dir\\file", 0, S_OK, "file:///c:dir/file"},
|
||||
{"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
|
||||
{"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
|
||||
{"A", 0, S_OK, "A"},
|
||||
{"", 0, S_OK, ""}
|
||||
{"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/", TRUE},
|
||||
{"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests", FALSE},
|
||||
{"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests", FALSE},
|
||||
{"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests", FALSE},
|
||||
{"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests", FALSE},
|
||||
{"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests", FALSE},
|
||||
{"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/", FALSE},
|
||||
{"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/", FALSE},
|
||||
{"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/", FALSE},
|
||||
{"http://www.winehq.org/tests/..", 0, S_OK, "http://www.winehq.org/", FALSE},
|
||||
{"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/", FALSE},
|
||||
{"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
|
||||
{"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
|
||||
{"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
|
||||
{"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
|
||||
{"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
|
||||
{"http://www.winehq.org/tests/..\\#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
|
||||
{"http://www.winehq.org\\tests/../#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
|
||||
{"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example", FALSE},
|
||||
{"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar", FALSE},
|
||||
{"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar", FALSE},
|
||||
{"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar", FALSE},
|
||||
{"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar", FALSE},
|
||||
{"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
|
||||
{"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE},
|
||||
{"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE},
|
||||
{"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE},
|
||||
{"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE},
|
||||
{"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar", FALSE},
|
||||
{"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar", FALSE},
|
||||
{"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar", FALSE},
|
||||
{"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about", FALSE},
|
||||
{"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about", FALSE},
|
||||
{"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file", FALSE},
|
||||
{"file:///c:\\dir\\file", 0, S_OK, "file:///c:/dir/file", FALSE},
|
||||
{"c:dir\\file", 0, S_OK, "file:///c:dir/file", FALSE},
|
||||
{"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE},
|
||||
{"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
|
||||
{"res:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "res:///c:/tests/foo bar", FALSE},
|
||||
{"res:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "res:///c:/tests\\foo bar", TRUE},
|
||||
{"res:///c:/tests/foo%20bar", 0, S_OK, "res:///c:/tests/foo%20bar", FALSE},
|
||||
{"res:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "res:///c:/tests/foo%20bar", TRUE},
|
||||
{"res://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "res://c:/tests/foo%20bar", TRUE},
|
||||
{"res://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "res://c:/tests/foo%20bar", TRUE},
|
||||
{"res://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "res://c:/tests/foo%20bar", TRUE},
|
||||
{"res:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "res:///c://tests/foo%20bar", TRUE},
|
||||
{"res:///c:\\tests\\foo bar", 0, S_OK, "res:///c:\\tests\\foo bar", TRUE},
|
||||
{"res:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "res:///c:\\tests\\foo bar", TRUE},
|
||||
{"A", 0, S_OK, "A", FALSE},
|
||||
{"/uri-res/N2R?urn:sha1:B3K", URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/, S_OK, "/uri-res/N2R?urn:sha1:B3K", TRUE} /*LimeWire online installer calls this*/,
|
||||
{"", 0, S_OK, "", FALSE}
|
||||
};
|
||||
|
||||
/* ################ */
|
||||
@@ -425,7 +437,7 @@ static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectRe
|
||||
|
||||
}
|
||||
|
||||
static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
|
||||
static void test_url_canonicalize(int index, const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl, BOOL todo)
|
||||
{
|
||||
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
|
||||
WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
|
||||
@@ -436,15 +448,19 @@ static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwEx
|
||||
DWORD dwSize;
|
||||
|
||||
dwSize = INTERNET_MAX_URL_LENGTH;
|
||||
ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
|
||||
ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08x\n", dwExpectReturn);
|
||||
ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x Expected \"%s\", but got \"%s\"\n", dwFlags, szExpectUrl, szReturnUrl);
|
||||
ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer, index %d\n", index);
|
||||
ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08x, index %d\n", dwExpectReturn, index);
|
||||
if (todo)
|
||||
todo_wine
|
||||
ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x url '%s' Expected \"%s\", but got \"%s\", index %d\n", dwFlags, szUrl, szExpectUrl, szReturnUrl, index);
|
||||
else
|
||||
ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x url '%s' Expected \"%s\", but got \"%s\", index %d\n", dwFlags, szUrl, szExpectUrl, szReturnUrl, index);
|
||||
|
||||
dwSize = INTERNET_MAX_URL_LENGTH;
|
||||
ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
|
||||
ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08x\n", dwExpectReturn);
|
||||
ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer, index %d\n", index);
|
||||
ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08x, index %d\n", dwExpectReturn, index);
|
||||
wszConvertedUrl = GetWideString(szReturnUrl);
|
||||
ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
|
||||
ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize, index %d!\n", index);
|
||||
FreeWideString(wszConvertedUrl);
|
||||
|
||||
|
||||
@@ -545,19 +561,10 @@ static void test_UrlCanonicalizeA(void)
|
||||
|
||||
/* test url-modification */
|
||||
for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
|
||||
test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
|
||||
TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
|
||||
test_url_canonicalize(i, TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
|
||||
TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl,
|
||||
TEST_CANONICALIZE[i].todo);
|
||||
}
|
||||
|
||||
/* move to TEST_CANONICALIZE when fixed */
|
||||
dwSize = sizeof szReturnUrl;
|
||||
/*LimeWire online installer calls this*/
|
||||
hr = UrlCanonicalizeA("/uri-res/N2R?urn:sha1:B3K", szReturnUrl, &dwSize,URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/);
|
||||
ok(hr==S_OK,"UrlCanonicalizeA returned 0x%08x instead of S_OK\n", hr);
|
||||
todo_wine {
|
||||
ok(strcmp(szReturnUrl,"/uri-res/N2R?urn:sha1:B3K")==0, "UrlCanonicalizeA got \"%s\" instead of \"/uri-res/N2R?urn:sha1:B3K\"\n", szReturnUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ########################### */
|
||||
|
||||
@@ -721,6 +721,8 @@ static const BYTE secid7[] = {'f','t','p',':','w','i','n','e','h','q','.','o','r
|
||||
3,0,0,0};
|
||||
static const BYTE secid10[] =
|
||||
{'f','i','l','e',':','s','o','m','e','%','2','0','f','i','l','e','.','j','p','g',3,0,0,0};
|
||||
static const BYTE secid10_2[] =
|
||||
{'f','i','l','e',':','s','o','m','e',' ','f','i','l','e','.','j','p','g',3,0,0,0};
|
||||
|
||||
static struct secmgr_test {
|
||||
LPCWSTR url;
|
||||
@@ -733,7 +735,6 @@ static struct secmgr_test {
|
||||
{url1, 0, S_OK, sizeof(secid1), secid1, S_OK},
|
||||
{url2, 100, 0x80041001, 0, NULL, E_INVALIDARG},
|
||||
{url3, 0, S_OK, sizeof(secid1), secid1, S_OK},
|
||||
{url10,3, S_OK, sizeof(secid10),secid10,S_OK},
|
||||
{url5, 3, S_OK, sizeof(secid5), secid5, S_OK},
|
||||
{url6, 3, S_OK, sizeof(secid6), secid6, S_OK},
|
||||
{url7, 3, S_OK, sizeof(secid7), secid7, S_OK}
|
||||
@@ -780,6 +781,23 @@ static void test_SecurityManager(void)
|
||||
}
|
||||
}
|
||||
|
||||
zone = 100;
|
||||
hres = IInternetSecurityManager_MapUrlToZone(secmgr, url10, &zone, 0);
|
||||
ok(hres == S_OK, "MapUrlToZone failed: %08x, expected S_OK\n", hres);
|
||||
ok(zone == 3, "zone=%d, expected 3\n", zone);
|
||||
|
||||
/* win2k3 translates %20 into a space */
|
||||
size = sizeof(buf);
|
||||
memset(buf, 0xf0, sizeof(buf));
|
||||
hres = IInternetSecurityManager_GetSecurityId(secmgr, url10, buf, &size, 0);
|
||||
ok(hres == S_OK, "GetSecurityId failed: %08x, expected S_OK\n", hres);
|
||||
ok(size == sizeof(secid10) ||
|
||||
size == sizeof(secid10_2), /* win2k3 */
|
||||
"size=%d\n", size);
|
||||
ok(!memcmp(buf, secid10, size) ||
|
||||
!memcmp(buf, secid10_2, size), /* win2k3 */
|
||||
"wrong secid\n");
|
||||
|
||||
zone = 100;
|
||||
hres = IInternetSecurityManager_MapUrlToZone(secmgr, NULL, &zone, 0);
|
||||
ok(hres == E_INVALIDARG, "MapUrlToZone failed: %08x, expected E_INVALIDARG\n", hres);
|
||||
|
||||
@@ -449,6 +449,7 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
|
||||
LPWSTR additional_headers = (LPWSTR)0xdeadbeef;
|
||||
BYTE sec_id[100];
|
||||
DWORD fetched = 256, size = 100;
|
||||
DWORD tid;
|
||||
|
||||
static const WCHAR wszMimes[] = {'*','/','*',0};
|
||||
|
||||
@@ -518,7 +519,7 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
|
||||
|
||||
IInternetProtocolSink_AddRef(pOIProtSink);
|
||||
protocol_sink = pOIProtSink;
|
||||
CreateThread(NULL, 0, thread_proc, NULL, 0, NULL);
|
||||
CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="urlmon_winetest" type="win32cui" installbase="bin" installname="urlmon_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="urlmon_winetest" type="win32cui" installbase="bin" installname="urlmon_winetest.exe" allowwarnings="true">
|
||||
<include base="urlmon_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -23,24 +23,60 @@
|
||||
* and filtering characters and bi-directional text with custom line breaks.
|
||||
*/
|
||||
|
||||
//#include <assert.h>
|
||||
//#include <stdio.h>
|
||||
//#include <windows.h>
|
||||
//#include <wine/test.h>
|
||||
//#include <winbase.h>
|
||||
//#include <wingdi.h>
|
||||
//#include <winuser.h>
|
||||
//#include <winerror.h>
|
||||
//#include <winnls.h>
|
||||
//#include <usp10.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include "usp10.h"
|
||||
#include "wine/test.h"
|
||||
#include "wine/windef.h"
|
||||
|
||||
BOOL WINAPI ShowWindow(HWND,int);
|
||||
#include <wine/test.h>
|
||||
#include <winbase.h>
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <winerror.h>
|
||||
#include <winnls.h>
|
||||
#include <usp10.h>
|
||||
|
||||
static void test_ScriptShape(HDC hdc)
|
||||
{
|
||||
static const WCHAR test1[] = {'t', 'e', 's', 't',0};
|
||||
BOOL ret;
|
||||
HRESULT hr;
|
||||
SCRIPT_CACHE sc = NULL;
|
||||
WORD glyphs[4];
|
||||
SCRIPT_VISATTR attrs[4];
|
||||
SCRIPT_ITEM items[2];
|
||||
int nb, widths[4];
|
||||
|
||||
hr = ScriptItemize(NULL, 4, 2, NULL, NULL, items, NULL);
|
||||
ok(hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG not %08x\n", hr);
|
||||
|
||||
hr = ScriptItemize(test1, 4, 2, NULL, NULL, NULL, NULL);
|
||||
ok(hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG not %08x\n", hr);
|
||||
|
||||
hr = ScriptItemize(test1, 4, 2, NULL, NULL, items, NULL);
|
||||
ok(!hr, "ScriptItemize should return S_OK not %08x\n", hr);
|
||||
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
|
||||
|
||||
hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, NULL, &nb);
|
||||
ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr);
|
||||
|
||||
hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, NULL);
|
||||
ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr);
|
||||
|
||||
hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb);
|
||||
ok(!hr, "ScriptShape should return S_OK not %08x\n", hr);
|
||||
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
|
||||
|
||||
hr = ScriptPlace(hdc, &sc, glyphs, 4, NULL, &items[0].a, widths, NULL, NULL);
|
||||
ok(hr == E_INVALIDARG, "ScriptPlace should return E_INVALIDARG not %08x\n", hr);
|
||||
|
||||
hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, NULL);
|
||||
ok(!hr, "ScriptPlace should return S_OK not %08x\n", hr);
|
||||
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
|
||||
|
||||
ret = ExtTextOutW(hdc, 1, 1, 0, NULL, glyphs, 4, widths);
|
||||
ok(ret, "ExtTextOutW should return TRUE\n");
|
||||
|
||||
ScriptFreeCache(&sc);
|
||||
}
|
||||
|
||||
static void test_ScriptItemIzeShapePlace(HDC hdc, unsigned short pwOutGlyphs[256])
|
||||
{
|
||||
@@ -52,11 +88,11 @@ static void test_ScriptItemIzeShapePlace(HDC hdc, unsigned short pwOutGlyphs[256
|
||||
int cMaxItems;
|
||||
SCRIPT_ITEM pItem[255];
|
||||
int pcItems;
|
||||
WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0};
|
||||
WCHAR TestItem2[] = {'T', 'e', 's', 't', 'b', 0};
|
||||
WCHAR TestItem3[] = {'T', 'e', 's', 't', 'c',' ','1','2','3',' ',' ','e','n','d',0};
|
||||
WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0};
|
||||
WCHAR TestItem2[] = {'T', 'e', 's', 't', 'b', 0};
|
||||
WCHAR TestItem3[] = {'T', 'e', 's', 't', 'c',' ','1','2','3',' ',' ','e','n','d',0};
|
||||
WCHAR TestItem4[] = {'T', 'e', 's', 't', 'c',' ',0x0684,0x0694,0x06a4,' ',' ','e','n','d',0};
|
||||
WCHAR TestItem5[] = {0x0684,'T','e','s','t','c',' ',0x0684,0x0694,0x06a4,' ',' ','e','n','d',0};
|
||||
WCHAR TestItem5[] = {0x0684,'T','e','s','t','c',' ',0x0684,0x0694,0x06a4,' ',' ','e','n','d',0};
|
||||
|
||||
SCRIPT_CACHE psc;
|
||||
int cChars;
|
||||
@@ -76,7 +112,7 @@ static void test_ScriptItemIzeShapePlace(HDC hdc, unsigned short pwOutGlyphs[256
|
||||
* by checking a known value in the table */
|
||||
hr = ScriptGetProperties(&ppSp, &iMaxProps);
|
||||
trace("number of script properties %d\n", iMaxProps);
|
||||
ok (iMaxProps > 0, "Number of scripts returned should not be 0\n");
|
||||
ok (iMaxProps > 0, "Number of scripts returned should not be 0\n");
|
||||
if (iMaxProps > 0)
|
||||
ok( ppSp[5]->langid == 9, "Langid[5] not = to 9\n"); /* Check a known value to ensure */
|
||||
/* ptrs work */
|
||||
@@ -160,7 +196,7 @@ static void test_ScriptItemIzeShapePlace(HDC hdc, unsigned short pwOutGlyphs[256
|
||||
cMaxItems = 255;
|
||||
hr = ScriptItemize(TestItem2, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
|
||||
ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", hr);
|
||||
/* This test is for the intertrim operation of ScriptItemize where only one SCRIPT_ITEM is *
|
||||
/* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
|
||||
* returned. */
|
||||
ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
|
||||
"Start pos not = 0 (%d) or end pos not = %d (%d)\n",
|
||||
@@ -241,12 +277,12 @@ static void test_ScriptItemIzeShapePlace(HDC hdc, unsigned short pwOutGlyphs[256
|
||||
|
||||
/*
|
||||
* This test is for when the first unicode character requires bidi support
|
||||
*/
|
||||
*/
|
||||
cInChars = (sizeof(TestItem5)-1)/sizeof(WCHAR);
|
||||
hr = ScriptItemize(TestItem5, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
|
||||
ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", hr);
|
||||
ok (pcItems == 4, "There should have been 4 items, found %d\n", pcItems);
|
||||
ok (pItem[0].a.s.uBidiLevel == 1, "The first character should have been bidi=1 not %d\n",
|
||||
ok (pItem[0].a.s.uBidiLevel == 1, "The first character should have been bidi=1 not %d\n",
|
||||
pItem[0].a.s.uBidiLevel);
|
||||
}
|
||||
|
||||
@@ -257,7 +293,7 @@ static void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256])
|
||||
int cInChars;
|
||||
int cChars;
|
||||
unsigned short pwOutGlyphs3[256];
|
||||
WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0};
|
||||
WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0};
|
||||
DWORD dwFlags;
|
||||
int cnt;
|
||||
|
||||
@@ -287,6 +323,7 @@ static void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256])
|
||||
ok( hr == S_OK, "ScriptGetCMap(NULL,&psc,NULL,0,0,NULL), expected S_OK, "
|
||||
"got %08x\n", hr);
|
||||
ok( psc != NULL, "ScritpGetCMap expected psc to be not NULL\n");
|
||||
ScriptFreeCache( &psc);
|
||||
|
||||
/* Set psc to NULL, to be able to check if a pointer is returned in psc */
|
||||
psc = NULL;
|
||||
@@ -300,7 +337,7 @@ static void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256])
|
||||
for (cnt=0; cnt < cChars && pwOutGlyphs[cnt] == pwOutGlyphs3[cnt]; cnt++) {}
|
||||
ok (cnt == cInChars, "Translation not correct. WCHAR %d - %04x != %04x\n",
|
||||
cnt, pwOutGlyphs[cnt], pwOutGlyphs3[cnt]);
|
||||
|
||||
|
||||
hr = ScriptFreeCache( &psc);
|
||||
ok (!psc, "psc is not null after ScriptFreeCache\n");
|
||||
|
||||
@@ -344,10 +381,11 @@ static void test_ScriptGetFontProperties(HDC hdc)
|
||||
ok( hr == E_INVALIDARG, "(hdc,&psc,NULL), expected E_INVALIDARG, got %08x\n", hr);
|
||||
ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
|
||||
|
||||
/* Pass an uninitialized sfp */
|
||||
/* Pass an invalid sfp */
|
||||
psc = NULL;
|
||||
sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES) - 1;
|
||||
hr = ScriptGetFontProperties(hdc,&psc,&sfp);
|
||||
ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) partly uninitialized, expected E_INVALIDARG, got %08x\n", hr);
|
||||
ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) invalid, expected E_INVALIDARG, got %08x\n", hr);
|
||||
ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
|
||||
ScriptFreeCache(&psc);
|
||||
ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
|
||||
@@ -377,7 +415,7 @@ static void test_ScriptTextOut(HDC hdc)
|
||||
int cMaxItems;
|
||||
SCRIPT_ITEM pItem[255];
|
||||
int pcItems;
|
||||
WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0};
|
||||
WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0};
|
||||
|
||||
SCRIPT_CACHE psc;
|
||||
int cChars;
|
||||
@@ -460,7 +498,7 @@ static void test_ScriptTextOut(HDC hdc)
|
||||
hr = ScriptTextOut(hdc, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
|
||||
piAdvance, NULL, pGoffset);
|
||||
ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", hr);
|
||||
ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
|
||||
ok (psc == NULL, "psc should be null\n");
|
||||
|
||||
/* Test Rect Rgn is acceptable */
|
||||
rect.top = 10;
|
||||
@@ -470,7 +508,7 @@ static void test_ScriptTextOut(HDC hdc)
|
||||
hr = ScriptTextOut(hdc, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
|
||||
piAdvance, NULL, pGoffset);
|
||||
ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", hr);
|
||||
ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
|
||||
ok (psc == NULL, "psc should be null\n");
|
||||
|
||||
iCP = 1;
|
||||
hr = ScriptCPtoX(iCP, fTrailing, cChars, pcGlyphs, (const WORD *) &pwLogClust,
|
||||
@@ -488,6 +526,93 @@ static void test_ScriptTextOut(HDC hdc)
|
||||
}
|
||||
}
|
||||
|
||||
static void test_ScriptTextOut2(HDC hdc)
|
||||
{
|
||||
/* Intent is to validate that the HDC passed into ScriptTextOut is
|
||||
* used instead of the (possibly) invalid cached one
|
||||
*/
|
||||
HRESULT hr;
|
||||
|
||||
HDC hdc1, hdc2;
|
||||
int cInChars;
|
||||
int cMaxItems;
|
||||
SCRIPT_ITEM pItem[255];
|
||||
int pcItems;
|
||||
WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0};
|
||||
|
||||
SCRIPT_CACHE psc;
|
||||
int cChars;
|
||||
int cMaxGlyphs;
|
||||
unsigned short pwOutGlyphs1[256];
|
||||
WORD pwLogClust[256];
|
||||
SCRIPT_VISATTR psva[256];
|
||||
int pcGlyphs;
|
||||
int piAdvance[256];
|
||||
GOFFSET pGoffset[256];
|
||||
ABC pABC[256];
|
||||
|
||||
/* Create an extra DC that will be used until the ScriptTextOut */
|
||||
hdc1 = CreateCompatibleDC(hdc);
|
||||
ok (hdc1 != 0, "CreateCompatibleDC failed to create a DC\n");
|
||||
hdc2 = CreateCompatibleDC(hdc);
|
||||
ok (hdc2 != 0, "CreateCompatibleDC failed to create a DC\n");
|
||||
|
||||
/* This is a valid test that will cause parsing to take place */
|
||||
cInChars = 5;
|
||||
cMaxItems = 255;
|
||||
hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
|
||||
ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", hr);
|
||||
/* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
|
||||
* returned. */
|
||||
ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
|
||||
if (pcItems > 0)
|
||||
ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
|
||||
"Start pos not = 0 (%d) or end pos not = %d (%d)\n",
|
||||
pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
|
||||
|
||||
/* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
|
||||
* ie. ScriptItemize has succeeded and that pItem has been set */
|
||||
cInChars = 5;
|
||||
cMaxItems = 255;
|
||||
if (hr == 0) {
|
||||
psc = NULL; /* must be null on first call */
|
||||
cChars = cInChars;
|
||||
cMaxGlyphs = cInChars;
|
||||
cMaxGlyphs = 256;
|
||||
hr = ScriptShape(hdc2, &psc, TestItem1, cChars,
|
||||
cMaxGlyphs, &pItem[0].a,
|
||||
pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
|
||||
ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", hr);
|
||||
ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
|
||||
ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
|
||||
if (hr ==0) {
|
||||
/* Note hdc is needed as glyph info is not yet in psc */
|
||||
hr = ScriptPlace(hdc2, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
|
||||
pGoffset, pABC);
|
||||
ok (hr == 0, "Should return 0 not (%08x)\n", hr);
|
||||
|
||||
/* key part!!! cached dc is being deleted */
|
||||
hr = DeleteDC(hdc2);
|
||||
ok(hr == 1, "DeleteDC should return 1 not %08x\n", hr);
|
||||
|
||||
/* At this point the cached hdc (hdc2) has been destroyed,
|
||||
* however, we are passing in a *real* hdc (the original hdc).
|
||||
* The text should be written to that DC
|
||||
*/
|
||||
hr = ScriptTextOut(hdc1, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
|
||||
piAdvance, NULL, pGoffset);
|
||||
ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", hr);
|
||||
ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
|
||||
|
||||
DeleteDC(hdc1);
|
||||
|
||||
/* Clean up and go */
|
||||
ScriptFreeCache(&psc);
|
||||
ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_ScriptXtoX(void)
|
||||
/****************************************************************************************
|
||||
* This routine tests the ScriptXtoCP and ScriptCPtoX functions using static variables *
|
||||
@@ -572,7 +697,7 @@ static void test_ScriptXtoX(void)
|
||||
cGlyphs = 10;
|
||||
hr = ScriptCPtoX(iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piX);
|
||||
ok(hr == S_OK, "ScriptCPtoX should return S_OK not %08x\n", hr);
|
||||
ok(piX == 1171, "iCP=%d should return piX=1171 not %d\n", iCP, piX);
|
||||
ok(piX == 1171, "iCP=%d should return piX=1171 not %d\n", iCP, piX);
|
||||
iCP=6;
|
||||
fTrailing = FALSE;
|
||||
cChars = 10;
|
||||
@@ -593,7 +718,7 @@ static void test_ScriptXtoX(void)
|
||||
cGlyphs = 10;
|
||||
hr = ScriptCPtoX(iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piX);
|
||||
ok(hr == S_OK, "ScriptCPtoX should return S_OK not %08x\n", hr);
|
||||
ok(piX == 1953, "iCP=%d should return piX=1953 not %d\n", iCP, piX);
|
||||
ok(piX == 1953, "iCP=%d should return piX=1953 not %d\n", iCP, piX);
|
||||
|
||||
}
|
||||
|
||||
@@ -622,15 +747,16 @@ static void test_ScriptString(HDC hdc)
|
||||
const BYTE InClass = 0;
|
||||
SCRIPT_STRING_ANALYSIS ssa = NULL;
|
||||
|
||||
int X = 10;
|
||||
int X = 10;
|
||||
int Y = 100;
|
||||
UINT Options = 0;
|
||||
const RECT rc = {0, 50, 100, 100};
|
||||
UINT Options = 0;
|
||||
const RECT rc = {0, 50, 100, 100};
|
||||
int MinSel = 0;
|
||||
int MaxSel = 0;
|
||||
BOOL Disabled = FALSE;
|
||||
const int *clip_len;
|
||||
UINT *order, i;
|
||||
int i;
|
||||
UINT *order;
|
||||
|
||||
|
||||
Charset = -1; /* this flag indicates unicode input */
|
||||
@@ -645,6 +771,7 @@ static void test_ScriptString(HDC hdc)
|
||||
ReqWidth, &Control, &State, Dx, &Tabdef,
|
||||
&InClass, &ssa);
|
||||
ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr);
|
||||
ScriptStringFree(&ssa);
|
||||
|
||||
/* test makes sure that a call with a valid pssa still works */
|
||||
hr = ScriptStringAnalyse( hdc, teststr, len, Glyphs, Charset, Flags,
|
||||
@@ -705,7 +832,7 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
BOOL fTrailing;
|
||||
|
||||
/* Test with hdc, this should be a valid test
|
||||
* Here we generrate an SCRIPT_STRING_ANALYSIS that will be used as input to the
|
||||
* Here we generate an SCRIPT_STRING_ANALYSIS that will be used as input to the
|
||||
* following character positions to X and X to character position functions.
|
||||
*/
|
||||
hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags,
|
||||
@@ -733,7 +860,7 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing);
|
||||
ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr);
|
||||
ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, X);
|
||||
ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
|
||||
ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
|
||||
iTrailing, X);
|
||||
fTrailing = TRUE;
|
||||
hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X);
|
||||
@@ -747,7 +874,7 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
* again works
|
||||
*/
|
||||
ok(Cp + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp + 1, Ch, X);
|
||||
ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
|
||||
ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
|
||||
iTrailing, X);
|
||||
}
|
||||
/*
|
||||
@@ -762,13 +889,13 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing);
|
||||
ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr);
|
||||
ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, X);
|
||||
ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
|
||||
ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
|
||||
iTrailing, X);
|
||||
|
||||
/*
|
||||
* This test is to check that if the X position is just outside the trailing edge of the
|
||||
* character then iTrailing will indicate the leading edge, ie. FALSE, and Ch will indicate
|
||||
* the next character, ie. Cp + 1
|
||||
* the next character, ie. Cp + 1
|
||||
*/
|
||||
fTrailing = TRUE;
|
||||
Cp = 3;
|
||||
@@ -778,13 +905,13 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing);
|
||||
ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr);
|
||||
ok(Cp + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp + 1, Ch, X);
|
||||
ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
|
||||
ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
|
||||
iTrailing, X);
|
||||
|
||||
/*
|
||||
* This test is to check that if the X position is just outside the leading edge of the
|
||||
* character then iTrailing will indicate the trailing edge, ie. TRUE, and Ch will indicate
|
||||
* the next character down , ie. Cp - 1
|
||||
* the next character down , ie. Cp - 1
|
||||
*/
|
||||
fTrailing = FALSE;
|
||||
Cp = 3;
|
||||
@@ -794,11 +921,11 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing);
|
||||
ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr);
|
||||
ok(Cp - 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp - 1, Ch, X);
|
||||
ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
|
||||
ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
|
||||
iTrailing, X);
|
||||
|
||||
/*
|
||||
* Cleanup the the SSA for the next round of tests
|
||||
* Cleanup the SSA for the next round of tests
|
||||
*/
|
||||
hr = ScriptStringFree(&ssa);
|
||||
ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr);
|
||||
@@ -814,11 +941,11 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
|
||||
/*
|
||||
* When ScriptStringCPtoX is called with a character position Cp that exceeds the
|
||||
* string length, return E_INVALIDARG. This also invalidates the ssa so a
|
||||
* string length, return E_INVALIDARG. This also invalidates the ssa so a
|
||||
* ScriptStringFree should also fail.
|
||||
*/
|
||||
fTrailing = FALSE;
|
||||
Cp = String_len + 1;
|
||||
Cp = String_len + 1;
|
||||
hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X);
|
||||
ok(hr == E_INVALIDARG, "ScriptStringCPtoX should return E_INVALIDARG not %08x\n", hr);
|
||||
|
||||
@@ -826,7 +953,9 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
|
||||
/*
|
||||
* ScriptStringCPtoX should free ssa, hence ScriptStringFree should fail
|
||||
*/
|
||||
ok(hr == E_INVALIDARG, "ScriptStringFree should return E_INVALIDARG not %08x\n", hr);
|
||||
ok(hr == E_INVALIDARG ||
|
||||
hr == E_FAIL, /* win2k3 */
|
||||
"ScriptStringFree should return E_INVALIDARG or E_FAIL not %08x\n", hr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,8 +978,9 @@ static void test_ScriptCacheGetHeight(HDC hdc)
|
||||
|
||||
hr = ScriptCacheGetHeight(hdc, &sc, &height);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
|
||||
ok(height > 0, "expected height > 0\n");
|
||||
|
||||
ScriptFreeCache(&sc);
|
||||
}
|
||||
|
||||
static void test_ScriptGetGlyphABCWidth(HDC hdc)
|
||||
@@ -872,6 +1002,8 @@ static void test_ScriptGetGlyphABCWidth(HDC hdc)
|
||||
|
||||
hr = ScriptGetGlyphABCWidth(hdc, &sc, 'a', &abc);
|
||||
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
|
||||
|
||||
ScriptFreeCache(&sc);
|
||||
}
|
||||
|
||||
static void test_ScriptLayout(void)
|
||||
@@ -1216,15 +1348,14 @@ START_TEST(usp10)
|
||||
* to set up for the tests. */
|
||||
hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
|
||||
0, 0, 0, NULL);
|
||||
// FIXME do wine assert
|
||||
//assert(hwnd != 0);
|
||||
assert(hwnd != 0);
|
||||
ShowWindow(hwnd, SW_SHOW);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
hdc = GetDC(hwnd); /* We now have a hdc */
|
||||
ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
|
||||
|
||||
memset(&lf, 0, sizeof(HFONT));
|
||||
memset(&lf, 0, sizeof(LOGFONTA));
|
||||
lstrcpyA(lf.lfFaceName, "Symbol");
|
||||
lf.lfHeight = 10;
|
||||
lf.lfWeight = 3;
|
||||
@@ -1236,9 +1367,11 @@ START_TEST(usp10)
|
||||
test_ScriptGetCMap(hdc, pwOutGlyphs);
|
||||
test_ScriptCacheGetHeight(hdc);
|
||||
test_ScriptGetGlyphABCWidth(hdc);
|
||||
test_ScriptShape(hdc);
|
||||
|
||||
test_ScriptGetFontProperties(hdc);
|
||||
test_ScriptTextOut(hdc);
|
||||
test_ScriptTextOut2(hdc);
|
||||
test_ScriptXtoX();
|
||||
test_ScriptString(hdc);
|
||||
test_ScriptStringXtoCP_CPtoX(hdc);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="usp10_winetest" type="win32cui" installbase="bin" installname="usp10_winetest.exe" allowwarnings="true">
|
||||
<include base="usp10_winetest">.</include>
|
||||
<define name="__USE_W32API" />
|
||||
@@ -9,3 +12,4 @@
|
||||
<file>usp10.c</file>
|
||||
<file>testlist.c</file>
|
||||
</module>
|
||||
</group>
|
||||
|
||||
@@ -420,7 +420,9 @@ static void test_GetCurrentThemeName(void)
|
||||
if (bThemeActive)
|
||||
ok( hRes == E_POINTER || hRes == S_OK, "Expected E_POINTER or S_OK, got 0x%08x\n", hRes);
|
||||
else
|
||||
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
|
||||
ok( hRes == E_PROP_ID_UNSUPPORTED ||
|
||||
hRes == E_POINTER, /* win2k3 */
|
||||
"Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
|
||||
ok( GetLastError() == 0xdeadbeef,
|
||||
"Expected 0xdeadbeef, got 0x%08x\n",
|
||||
GetLastError());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="uxtheme_winetest" type="win32cui" installbase="bin" installname="uxtheme_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="uxtheme_winetest" type="win32cui" installbase="bin" installname="uxtheme_winetest.exe" allowwarnings="true">
|
||||
<include base="uxtheme_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -31,18 +31,20 @@
|
||||
ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
|
||||
(ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
|
||||
(ERROR_FILE_NOT_FOUND == GetLastError()) || \
|
||||
(ERROR_BAD_PATHNAME == GetLastError()), \
|
||||
(ERROR_BAD_PATHNAME == GetLastError()) || \
|
||||
(ERROR_SUCCESS == GetLastError()), \
|
||||
"Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_BAD_PATHNAME (98)/" \
|
||||
"ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
|
||||
"expected, got %u\n", GetLastError());
|
||||
"ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3) " \
|
||||
"ERROR_SUCCESS (2k) expected, got %u\n", GetLastError());
|
||||
#define EXPECT_INVALID__NOT_FOUND \
|
||||
ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
|
||||
(ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
|
||||
(ERROR_FILE_NOT_FOUND == GetLastError()) || \
|
||||
(ERROR_INVALID_PARAMETER == GetLastError()), \
|
||||
(ERROR_INVALID_PARAMETER == GetLastError()) || \
|
||||
(ERROR_SUCCESS == GetLastError()), \
|
||||
"Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_INVALID_PARAMETER (98)/" \
|
||||
"ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
|
||||
"expected, got %u\n", GetLastError());
|
||||
"ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3) " \
|
||||
"ERROR_SUCCESS (2k) expected, got %u\n", GetLastError());
|
||||
|
||||
static void create_file(const CHAR *name)
|
||||
{
|
||||
@@ -122,7 +124,8 @@ static void test_info_size(void)
|
||||
retval);
|
||||
ok( (ERROR_FILE_NOT_FOUND == GetLastError()) ||
|
||||
(ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) ||
|
||||
(MY_LAST_ERROR == GetLastError()),
|
||||
(MY_LAST_ERROR == GetLastError()) ||
|
||||
(ERROR_SUCCESS == GetLastError()), /* win2k */
|
||||
"Last error wrong! ERROR_FILE_NOT_FOUND/ERROR_RESOURCE_DATA_NOT_FOUND "
|
||||
"(XP)/0x%08x (NT4) expected, got %u\n", MY_LAST_ERROR, GetLastError());
|
||||
|
||||
@@ -174,7 +177,9 @@ static void test_info_size(void)
|
||||
retval = GetFileVersionInfoSizeA("test.txt", &hdl);
|
||||
ok(retval == 0, "Expected 0, got %d\n", retval);
|
||||
ok(hdl == 0, "Expected 0, got %d\n", hdl);
|
||||
ok(GetLastError() == ERROR_RESOURCE_DATA_NOT_FOUND,
|
||||
ok(GetLastError() == ERROR_RESOURCE_DATA_NOT_FOUND ||
|
||||
GetLastError() == ERROR_BAD_FORMAT || /* win9x */
|
||||
GetLastError() == ERROR_SUCCESS, /* win2k */
|
||||
"Expected ERROR_RESOURCE_DATA_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
DeleteFileA("test.txt");
|
||||
@@ -480,7 +485,9 @@ static void test_VerQueryValue(void)
|
||||
GetLastError() == 0xdeadbeef /* Win9x, NT4, W2K */,
|
||||
"VerQueryValue returned %u\n", GetLastError());
|
||||
ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
|
||||
ok(len == 0, "expected 0 got %x\n", len);
|
||||
ok(len == 0 ||
|
||||
len == 0xbeef, /* win9x */
|
||||
"expected 0 got %x\n", len);
|
||||
|
||||
p = (char *)0xdeadbeef;
|
||||
len = 0xdeadbeef;
|
||||
@@ -547,7 +554,9 @@ todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
|
||||
GetLastError() == 0xdeadbeef /* Win9x, NT4, W2K */,
|
||||
"VerQueryValue returned %u\n", GetLastError());
|
||||
ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
|
||||
ok(len == 0, "expected 0 got %x\n", len);
|
||||
ok(len == 0 ||
|
||||
len == 0xbeef, /* win9x */
|
||||
"expected 0 or 0xbeef, got %x\n", len);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, ver);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="version_winetest" type="win32cui" installbase="bin" installname="version_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="version_winetest" type="win32cui" installbase="bin" installname="version_winetest.exe" allowwarnings="true">
|
||||
<include base="version_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
* Add W-function tests.
|
||||
* Add missing function tests:
|
||||
* FtpFindFirstFile
|
||||
* FtpGetCurrentDirectory
|
||||
* FtpGetFileSize
|
||||
* FtpSetCurrentDirectory
|
||||
*/
|
||||
@@ -42,6 +41,10 @@
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
|
||||
static BOOL (WINAPI *pFtpCommandA)(HINTERNET,BOOL,DWORD,LPCSTR,DWORD_PTR,HINTERNET*);
|
||||
|
||||
|
||||
static void test_getfile_no_open(void)
|
||||
{
|
||||
BOOL bRet;
|
||||
@@ -680,10 +683,16 @@ static void test_command(HINTERNET hFtp, HINTERNET hConnect)
|
||||
{ TRUE, ERROR_SUCCESS, "PWD\r\n" }
|
||||
};
|
||||
|
||||
if (!pFtpCommandA)
|
||||
{
|
||||
skip("FtpCommandA() is not available. Skipping the Ftp command tests\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(command_test) / sizeof(command_test[0]); i++)
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = FtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL);
|
||||
ret = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL);
|
||||
error = GetLastError();
|
||||
|
||||
ok(ret == command_test[i].ret, "%d: expected FtpCommandA to %s\n", i, command_test[i].ret ? "succeed" : "fail");
|
||||
@@ -697,8 +706,14 @@ static void test_get_current_dir(HINTERNET hFtp, HINTERNET hConnect)
|
||||
DWORD dwCurrentDirectoryLen = MAX_PATH;
|
||||
CHAR lpszCurrentDirectory[MAX_PATH];
|
||||
|
||||
if (!pFtpCommandA)
|
||||
{
|
||||
skip("FtpCommandA() is not available. Skipping the Ftp get_current_dir tests\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* change directories to get a more interesting pwd */
|
||||
bRet = FtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, "CWD pub/", 0, NULL);
|
||||
bRet = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, "CWD pub/", 0, NULL);
|
||||
if(bRet == FALSE)
|
||||
{
|
||||
skip("Failed to change directories in test_get_current_dir(HINTERNET hFtp).\n");
|
||||
@@ -771,8 +786,12 @@ static void test_get_current_dir(HINTERNET hFtp, HINTERNET hConnect)
|
||||
|
||||
START_TEST(ftp)
|
||||
{
|
||||
HMODULE hWininet;
|
||||
HANDLE hInternet, hFtp, hHttp;
|
||||
|
||||
hWininet = GetModuleHandleA("wininet.dll");
|
||||
pFtpCommandA = (void*)GetProcAddress(hWininet, "FtpCommandA");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hInternet = InternetOpen("winetest", 0, NULL, NULL, 0);
|
||||
ok(hInternet != NULL, "InternetOpen failed: %u\n", GetLastError());
|
||||
|
||||
@@ -192,6 +192,8 @@ static VOID WINAPI callback(
|
||||
trace("%04x:Callback %p 0x%lx INTERNET_STATUS_HANDLE_CREATED %p %d\n",
|
||||
GetCurrentThreadId(), hInternet, dwContext,
|
||||
*(HINTERNET *)lpvStatusInformation,dwStatusInformationLength);
|
||||
CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
|
||||
SET_EXPECT(INTERNET_STATUS_DETECTING_PROXY);
|
||||
break;
|
||||
case INTERNET_STATUS_HANDLE_CLOSING:
|
||||
ok(dwStatusInformationLength == sizeof(HINTERNET),
|
||||
@@ -218,6 +220,8 @@ static VOID WINAPI callback(
|
||||
GetCurrentThreadId(), hInternet, dwContext,
|
||||
(LPCSTR)lpvStatusInformation, dwStatusInformationLength);
|
||||
*(LPSTR)lpvStatusInformation = '\0';
|
||||
CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
|
||||
SET_EXPECT(INTERNET_STATUS_DETECTING_PROXY);
|
||||
break;
|
||||
case INTERNET_STATUS_INTERMEDIATE_RESPONSE:
|
||||
trace("%04x:Callback %p 0x%lx INTERNET_STATUS_INTERMEDIATE_RESPONSE %p %d\n",
|
||||
@@ -233,6 +237,7 @@ static VOID WINAPI callback(
|
||||
|
||||
static void InternetReadFile_test(int flags)
|
||||
{
|
||||
BOOL res;
|
||||
DWORD rc;
|
||||
CHAR buffer[4000];
|
||||
DWORD length;
|
||||
@@ -286,6 +291,11 @@ static void InternetReadFile_test(int flags)
|
||||
|
||||
if (hor == 0x0) goto abort;
|
||||
|
||||
length = sizeof(buffer);
|
||||
res = InternetQueryOptionA(hor, INTERNET_OPTION_URL, buffer, &length);
|
||||
ok(res, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
|
||||
ok(!strcmp(buffer, "http://www.winehq.org/about/"), "Wrong URL %s\n", buffer);
|
||||
|
||||
CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
|
||||
todo_wine
|
||||
{
|
||||
@@ -366,10 +376,10 @@ static void InternetReadFile_test(int flags)
|
||||
buffer[length]=0;
|
||||
trace("Option 0x16 -> %i %s\n",rc,buffer);
|
||||
|
||||
length = 4000;
|
||||
rc = InternetQueryOptionA(hor,INTERNET_OPTION_URL,buffer,&length);
|
||||
buffer[length]=0;
|
||||
trace("Option 0x22 -> %i %s\n",rc,buffer);
|
||||
length = sizeof(buffer);
|
||||
res = InternetQueryOptionA(hor, INTERNET_OPTION_URL, buffer, &length);
|
||||
ok(res, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
|
||||
ok(!strcmp(buffer, "http://www.winehq.org/site/about"), "Wrong URL %s\n", buffer);
|
||||
|
||||
length = 16;
|
||||
rc = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_LENGTH,&buffer,&length,0x0);
|
||||
@@ -653,6 +663,8 @@ static void InternetReadFileExA_test(int flags)
|
||||
if (GetLastError() == ERROR_IO_PENDING)
|
||||
{
|
||||
trace("InternetReadFileEx -> PENDING\n");
|
||||
ok(flags & INTERNET_FLAG_ASYNC,
|
||||
"Should not get ERROR_IO_PENDING without INTERNET_FLAG_ASYNC\n");
|
||||
CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
|
||||
WaitForSingleObject(hCompleteEvent, INFINITE);
|
||||
CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
|
||||
@@ -888,8 +900,8 @@ static void HttpSendRequestEx_test(void)
|
||||
BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS);
|
||||
BufferIn.Next = (LPINTERNET_BUFFERS)0xdeadcab;
|
||||
BufferIn.lpcszHeader = szContentType;
|
||||
BufferIn.dwHeadersLength = sizeof(szContentType);
|
||||
BufferIn.dwHeadersTotal = sizeof(szContentType);
|
||||
BufferIn.dwHeadersLength = sizeof(szContentType)-1;
|
||||
BufferIn.dwHeadersTotal = sizeof(szContentType)-1;
|
||||
BufferIn.lpvBuffer = szPostData;
|
||||
BufferIn.dwBufferLength = 3;
|
||||
BufferIn.dwBufferTotal = sizeof(szPostData)-1;
|
||||
@@ -929,9 +941,19 @@ static void InternetOpenRequest_test(void)
|
||||
session = InternetOpenA("Wine Regression Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
||||
ok(session != NULL ,"Unable to open Internet session\n");
|
||||
|
||||
connect = InternetConnectA(session, NULL, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
|
||||
INTERNET_SERVICE_HTTP, 0, 0);
|
||||
ok(connect == NULL, "InternetConnectA should have failed\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with NULL server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
|
||||
|
||||
connect = InternetConnectA(session, "", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
|
||||
INTERNET_SERVICE_HTTP, 0, 0);
|
||||
ok(connect == NULL, "InternetConnectA should have failed\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with blank server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
|
||||
|
||||
connect = InternetConnectA(session, "winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
|
||||
INTERNET_SERVICE_HTTP, 0, 0);
|
||||
ok(connect != NULL, "Unable to connect to http://winehq.org\n");
|
||||
ok(connect != NULL, "Unable to connect to http://winehq.org with error %d\n", GetLastError());
|
||||
|
||||
request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, types, INTERNET_FLAG_NO_CACHE_WRITE, 0);
|
||||
if (!request && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
|
||||
@@ -957,6 +979,103 @@ done:
|
||||
ok(InternetCloseHandle(session), "Close session handle failed\n");
|
||||
}
|
||||
|
||||
static void test_http_cache(void)
|
||||
{
|
||||
HINTERNET session, connect, request;
|
||||
char file_name[MAX_PATH], url[INTERNET_MAX_URL_LENGTH];
|
||||
DWORD size, file_size;
|
||||
BYTE buf[100];
|
||||
HANDLE file;
|
||||
BOOL ret;
|
||||
|
||||
static const char *types[] = { "*", "", NULL };
|
||||
|
||||
session = InternetOpenA("Wine Regression Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
||||
ok(session != NULL ,"Unable to open Internet session\n");
|
||||
|
||||
connect = InternetConnectA(session, "www.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
|
||||
INTERNET_SERVICE_HTTP, 0, 0);
|
||||
ok(connect != NULL, "Unable to connect to http://winehq.org with error %d\n", GetLastError());
|
||||
|
||||
request = HttpOpenRequestA(connect, NULL, "/site/about", NULL, NULL, types, INTERNET_FLAG_NEED_FILE, 0);
|
||||
if (!request && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
|
||||
{
|
||||
trace( "Network unreachable, skipping test\n" );
|
||||
|
||||
ok(InternetCloseHandle(connect), "Close connect handle failed\n");
|
||||
ok(InternetCloseHandle(session), "Close session handle failed\n");
|
||||
|
||||
return;
|
||||
}
|
||||
ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
|
||||
|
||||
size = sizeof(url);
|
||||
ret = InternetQueryOptionA(request, INTERNET_OPTION_URL, url, &size);
|
||||
ok(ret, "InternetQueryOptionA(INTERNET_OPTION_url) failed: %u\n", GetLastError());
|
||||
ok(!strcmp(url, "http://www.winehq.org/site/about"), "Wrong URL %s\n", url);
|
||||
|
||||
size = sizeof(file_name);
|
||||
ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
|
||||
ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
|
||||
ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
|
||||
ok(!size, "size = %d\n", size);
|
||||
|
||||
ret = HttpSendRequest(request, NULL, 0, NULL, 0);
|
||||
ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
|
||||
|
||||
size = sizeof(file_name);
|
||||
ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
|
||||
ok(ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) failed: %u\n", GetLastError());
|
||||
|
||||
file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
|
||||
file_size = GetFileSize(file, NULL);
|
||||
ok(file_size == 0, "file size=%d\n", file_size);
|
||||
|
||||
ret = InternetReadFile(request, buf, sizeof(buf), &size);
|
||||
ok(ret, "InternetReadFile failed: %u\n", GetLastError());
|
||||
ok(size == sizeof(buf), "size=%d\n", size);
|
||||
|
||||
file_size = GetFileSize(file, NULL);
|
||||
ok(file_size == sizeof(buf), "file size=%d\n", file_size);
|
||||
CloseHandle(file);
|
||||
|
||||
ok(InternetCloseHandle(request), "Close request handle failed\n");
|
||||
|
||||
file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(file == INVALID_HANDLE_VALUE, "CreateFile succeeded\n");
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError()=%u, expected ERROR_FILE_NOT_FOUND\n", GetLastError());
|
||||
|
||||
request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, types, INTERNET_FLAG_NO_CACHE_WRITE, 0);
|
||||
ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
|
||||
|
||||
ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
|
||||
ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
|
||||
ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
|
||||
ok(!size, "size = %d\n", size);
|
||||
|
||||
ret = HttpSendRequest(request, NULL, 0, NULL, 0);
|
||||
ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
|
||||
|
||||
size = sizeof(file_name);
|
||||
ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
|
||||
ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
|
||||
ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
|
||||
ok(!size, "size = %d\n", size);
|
||||
|
||||
file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(file == INVALID_HANDLE_VALUE, "CreateFile succeeded\n");
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError()=%u, expected ERROR_FILE_NOT_FOUND\n", GetLastError());
|
||||
|
||||
ok(InternetCloseHandle(request), "Close request handle failed\n");
|
||||
|
||||
ok(InternetCloseHandle(connect), "Close connect handle failed\n");
|
||||
ok(InternetCloseHandle(session), "Close session handle failed\n");
|
||||
}
|
||||
|
||||
static void HttpHeaders_test(void)
|
||||
{
|
||||
HINTERNET hSession;
|
||||
@@ -999,7 +1118,7 @@ static void HttpHeaders_test(void)
|
||||
ok(index == 1, "Index was not incremented\n");
|
||||
ok(strcmp(buffer,"test1")==0, "incorrect string was returned(%s)\n",buffer);
|
||||
ok(len == 5, "Invalid length (exp. 5, got %d)\n", len);
|
||||
ok(buffer[len] == 0, "Buffer not NULL-terminated\n"); /* len show only 5 characters but the buffer is NULL-terminated*/
|
||||
ok((len < sizeof(buffer)) && (buffer[len] == 0), "Buffer not NULL-terminated\n"); /* len show only 5 characters but the buffer is NULL-terminated*/
|
||||
len = sizeof(buffer);
|
||||
strcpy(buffer,"Warning");
|
||||
ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
|
||||
@@ -1192,18 +1311,21 @@ done:
|
||||
ok(InternetCloseHandle(hSession), "Close session handle failed\n");
|
||||
}
|
||||
|
||||
static const char contmsg[] =
|
||||
"HTTP/1.1 100 Continue\r\n";
|
||||
|
||||
static const char okmsg[] =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: winetest\r\n"
|
||||
"\r\n";
|
||||
|
||||
static const char notokmsg[] =
|
||||
"HTTP/1.0 400 Bad Request\r\n"
|
||||
"HTTP/1.1 400 Bad Request\r\n"
|
||||
"Server: winetest\r\n"
|
||||
"\r\n";
|
||||
|
||||
static const char noauthmsg[] =
|
||||
"HTTP/1.0 401 Unauthorized\r\n"
|
||||
"HTTP/1.1 401 Unauthorized\r\n"
|
||||
"Server: winetest\r\n"
|
||||
"\r\n";
|
||||
|
||||
@@ -1275,8 +1397,13 @@ static DWORD CALLBACK server_thread(LPVOID param)
|
||||
|
||||
if (strstr(buffer, "GET /test1"))
|
||||
{
|
||||
send(c, okmsg, sizeof okmsg-1, 0);
|
||||
send(c, page1, sizeof page1-1, 0);
|
||||
if (!strstr(buffer, "Content-Length: 0"))
|
||||
{
|
||||
send(c, okmsg, sizeof okmsg-1, 0);
|
||||
send(c, page1, sizeof page1-1, 0);
|
||||
}
|
||||
else
|
||||
send(c, notokmsg, sizeof notokmsg-1, 0);
|
||||
}
|
||||
|
||||
if (strstr(buffer, "/test2"))
|
||||
@@ -1306,7 +1433,7 @@ static DWORD CALLBACK server_thread(LPVOID param)
|
||||
send(c, notokmsg, sizeof notokmsg-1, 0);
|
||||
}
|
||||
|
||||
if (strstr(buffer, "/test5"))
|
||||
if (strstr(buffer, "POST /test5"))
|
||||
{
|
||||
if (strstr(buffer, "Content-Length: 0"))
|
||||
{
|
||||
@@ -1317,7 +1444,15 @@ static DWORD CALLBACK server_thread(LPVOID param)
|
||||
send(c, notokmsg, sizeof notokmsg-1, 0);
|
||||
}
|
||||
|
||||
if (strstr(buffer, "/quit"))
|
||||
if (strstr(buffer, "GET /test6"))
|
||||
{
|
||||
send(c, contmsg, sizeof contmsg-1, 0);
|
||||
send(c, contmsg, sizeof contmsg-1, 0);
|
||||
send(c, okmsg, sizeof okmsg-1, 0);
|
||||
send(c, page1, sizeof page1-1, 0);
|
||||
}
|
||||
|
||||
if (strstr(buffer, "GET /quit"))
|
||||
{
|
||||
send(c, okmsg, sizeof okmsg-1, 0);
|
||||
send(c, page1, sizeof page1-1, 0);
|
||||
@@ -1333,19 +1468,19 @@ static DWORD CALLBACK server_thread(LPVOID param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_basic_request(int port, const char *url)
|
||||
static void test_basic_request(int port, const char *verb, const char *url)
|
||||
{
|
||||
HINTERNET hi, hc, hr;
|
||||
DWORD r, count;
|
||||
char buffer[0x100];
|
||||
|
||||
hi = InternetOpen(NULL, 0, NULL, NULL, 0);
|
||||
hi = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
||||
ok(hi != NULL, "open failed\n");
|
||||
|
||||
hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
|
||||
ok(hc != NULL, "connect failed\n");
|
||||
|
||||
hr = HttpOpenRequest(hc, NULL, url, NULL, NULL, NULL, 0, 0);
|
||||
hr = HttpOpenRequest(hc, verb, url, NULL, NULL, NULL, 0, 0);
|
||||
ok(hr != NULL, "HttpOpenRequest failed\n");
|
||||
|
||||
r = HttpSendRequest(hr, NULL, 0, NULL, 0);
|
||||
@@ -1492,7 +1627,10 @@ static void test_header_handling_order(int port)
|
||||
request = HttpOpenRequest(connect, NULL, "/test3", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
|
||||
ok(request != NULL, "HttpOpenRequest failed\n");
|
||||
|
||||
ret = HttpSendRequest(request, authorization, ~0UL, NULL, 0);
|
||||
ret = HttpAddRequestHeaders(request, authorization, ~0UL, HTTP_ADDREQ_FLAG_ADD);
|
||||
ok(ret, "HttpAddRequestHeaders failed\n");
|
||||
|
||||
ret = HttpSendRequest(request, NULL, 0, NULL, 0);
|
||||
ok(ret, "HttpSendRequest failed\n");
|
||||
|
||||
status = 0;
|
||||
@@ -1537,20 +1675,102 @@ static void test_http_connection(void)
|
||||
if (r != WAIT_OBJECT_0)
|
||||
return;
|
||||
|
||||
test_basic_request(si.port, "/test1");
|
||||
test_basic_request(si.port, "GET", "/test1");
|
||||
test_proxy_indirect(si.port);
|
||||
test_proxy_direct(si.port);
|
||||
test_header_handling_order(si.port);
|
||||
test_basic_request(si.port, "/test5");
|
||||
test_basic_request(si.port, "POST", "/test5");
|
||||
test_basic_request(si.port, "GET", "/test6");
|
||||
|
||||
/* send the basic request again to shutdown the server thread */
|
||||
test_basic_request(si.port, "/quit");
|
||||
test_basic_request(si.port, "GET", "/quit");
|
||||
|
||||
r = WaitForSingleObject(hThread, 3000);
|
||||
ok( r == WAIT_OBJECT_0, "thread wait failed\n");
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
||||
static void test_user_agent_header(void)
|
||||
{
|
||||
HINTERNET ses, con, req;
|
||||
DWORD size, err;
|
||||
char buffer[64];
|
||||
BOOL ret;
|
||||
|
||||
ses = InternetOpen("Gizmo5", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
||||
ok(ses != NULL, "InternetOpen failed\n");
|
||||
|
||||
con = InternetConnect(ses, "www.winehq.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
|
||||
ok(con != NULL, "InternetConnect failed\n");
|
||||
|
||||
req = HttpOpenRequest(con, "GET", "/", "HTTP/1.0", NULL, NULL, 0, 0);
|
||||
ok(req != NULL, "HttpOpenRequest failed\n");
|
||||
|
||||
size = sizeof(buffer);
|
||||
ret = HttpQueryInfo(req, HTTP_QUERY_USER_AGENT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
|
||||
err = GetLastError();
|
||||
ok(!ret, "HttpQueryInfo succeeded\n");
|
||||
ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
|
||||
|
||||
ret = HttpAddRequestHeaders(req, "User-Agent: Gizmo Project\r\n", ~0UL, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
|
||||
ok(ret, "HttpAddRequestHeaders succeeded\n");
|
||||
|
||||
size = sizeof(buffer);
|
||||
ret = HttpQueryInfo(req, HTTP_QUERY_USER_AGENT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
|
||||
err = GetLastError();
|
||||
ok(ret, "HttpQueryInfo failed\n");
|
||||
ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
|
||||
|
||||
InternetCloseHandle(req);
|
||||
|
||||
req = HttpOpenRequest(con, "GET", "/", "HTTP/1.0", NULL, NULL, 0, 0);
|
||||
ok(req != NULL, "HttpOpenRequest failed\n");
|
||||
|
||||
size = sizeof(buffer);
|
||||
ret = HttpQueryInfo(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
|
||||
err = GetLastError();
|
||||
ok(!ret, "HttpQueryInfo succeeded\n");
|
||||
ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
|
||||
|
||||
ret = HttpAddRequestHeaders(req, "Accept: audio/*, image/*, text/*\r\nUser-Agent: Gizmo Project\r\n", ~0UL, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
|
||||
ok(ret, "HttpAddRequestHeaders failed\n");
|
||||
|
||||
buffer[0] = 0;
|
||||
size = sizeof(buffer);
|
||||
ret = HttpQueryInfo(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
|
||||
ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
|
||||
ok(!strcmp(buffer, "audio/*, image/*, text/*"), "got '%s' expected 'audio/*, image/*, text/*'\n", buffer);
|
||||
|
||||
InternetCloseHandle(req);
|
||||
InternetCloseHandle(con);
|
||||
InternetCloseHandle(ses);
|
||||
}
|
||||
|
||||
static void test_bogus_accept_types_array(void)
|
||||
{
|
||||
HINTERNET ses, con, req;
|
||||
static const char *types[] = { (const char *)6240, "*/*", "%p", "", "*/*", NULL };
|
||||
DWORD size;
|
||||
char buffer[32];
|
||||
BOOL ret;
|
||||
|
||||
ses = InternetOpen("MERONG(0.9/;p)", INTERNET_OPEN_TYPE_DIRECT, "", "", 0);
|
||||
con = InternetConnect(ses, "www.winehq.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
|
||||
req = HttpOpenRequest(con, "POST", "/post/post_action.php", "HTTP/1.0", "", types, INTERNET_FLAG_FORMS_SUBMIT, 0);
|
||||
|
||||
ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
|
||||
|
||||
buffer[0] = 0;
|
||||
size = sizeof(buffer);
|
||||
ret = HttpQueryInfo(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
|
||||
ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
|
||||
ok(!strcmp(buffer, "*/*, %p, */*"), "got '%s' expected '*/*, %%p, */*'\n", buffer);
|
||||
|
||||
InternetCloseHandle(req);
|
||||
InternetCloseHandle(con);
|
||||
InternetCloseHandle(ses);
|
||||
}
|
||||
|
||||
#define STATUS_STRING(status) \
|
||||
memcpy(status_string[status], #status, sizeof(CHAR) * \
|
||||
(strlen(#status) < MAX_STATUS_NAME ? \
|
||||
@@ -1576,6 +1796,7 @@ static void init_status_tests(void)
|
||||
STATUS_STRING(INTERNET_STATUS_CONNECTION_CLOSED);
|
||||
STATUS_STRING(INTERNET_STATUS_HANDLE_CREATED);
|
||||
STATUS_STRING(INTERNET_STATUS_HANDLE_CLOSING);
|
||||
STATUS_STRING(INTERNET_STATUS_DETECTING_PROXY);
|
||||
STATUS_STRING(INTERNET_STATUS_REQUEST_COMPLETE);
|
||||
STATUS_STRING(INTERNET_STATUS_REDIRECT);
|
||||
STATUS_STRING(INTERNET_STATUS_INTERMEDIATE_RESPONSE);
|
||||
@@ -1610,6 +1831,7 @@ START_TEST(http)
|
||||
InternetReadFileExA_test(INTERNET_FLAG_ASYNC);
|
||||
}
|
||||
InternetOpenRequest_test();
|
||||
test_http_cache();
|
||||
InternetOpenUrlA_test();
|
||||
if (!pInternetTimeFromSystemTimeA)
|
||||
skip("skipping the InternetTime tests\n");
|
||||
@@ -1623,4 +1845,6 @@ START_TEST(http)
|
||||
HttpSendRequestEx_test();
|
||||
HttpHeaders_test();
|
||||
test_http_connection();
|
||||
test_user_agent_header();
|
||||
test_bogus_accept_types_array();
|
||||
}
|
||||
|
||||
@@ -113,6 +113,10 @@ static void test_InternetCanonicalizeUrlA(void)
|
||||
"got %u and %u with size %u for '%s' (%d)\n",
|
||||
res, GetLastError(), dwSize, buffer, lstrlenA(buffer));
|
||||
|
||||
res = InternetSetOptionA(NULL, 0xdeadbeef, buffer, sizeof(buffer));
|
||||
ok(!res, "InternetSetOptionA succeeded\n");
|
||||
ok(GetLastError() == ERROR_INTERNET_INVALID_OPTION,
|
||||
"InternetSetOptionA failed %u, expected ERROR_INTERNET_INVALID_OPTION\n", GetLastError());
|
||||
}
|
||||
|
||||
/* ############################### */
|
||||
@@ -285,7 +289,8 @@ static void test_null(void)
|
||||
|
||||
sz = 0;
|
||||
r = InternetGetCookieW(NULL, NULL, NULL, &sz);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INTERNET_UNRECOGNIZED_SCHEME,
|
||||
"wrong error %u\n", GetLastError());
|
||||
ok( r == FALSE, "return wrong\n");
|
||||
|
||||
r = InternetGetCookieW(szServer, NULL, NULL, &sz);
|
||||
@@ -311,7 +316,7 @@ static void test_null(void)
|
||||
ok( r == TRUE, "return wrong\n");
|
||||
|
||||
/* sz == lstrlenW(buffer) only in XP SP1 */
|
||||
ok( sz == 1 + lstrlenW(buffer), "sz wrong\n");
|
||||
ok( sz == 1 + lstrlenW(buffer) || sz == lstrlenW(buffer), "sz wrong %d\n", sz);
|
||||
|
||||
/* before XP SP2, buffer is "server; server" */
|
||||
ok( !lstrcmpW(szExpect, buffer) || !lstrcmpW(szServer, buffer), "cookie data wrong\n");
|
||||
@@ -321,6 +326,19 @@ static void test_null(void)
|
||||
ok(r == TRUE, "ret %d\n", r);
|
||||
}
|
||||
|
||||
static void test_version(void)
|
||||
{
|
||||
INTERNET_VERSION_INFO version;
|
||||
DWORD size;
|
||||
BOOL res;
|
||||
|
||||
size = sizeof(version);
|
||||
res = InternetQueryOptionA(NULL, INTERNET_OPTION_VERSION, &version, &size);
|
||||
ok(res, "Could not get version: %u\n", GetLastError());
|
||||
ok(version.dwMajorVersion == 1, "dwMajorVersion=%d, expected 1\n", version.dwMajorVersion);
|
||||
ok(version.dwMinorVersion == 2, "dwMinorVersion=%d, expected 2\n", version.dwMinorVersion);
|
||||
}
|
||||
|
||||
/* ############################### */
|
||||
|
||||
START_TEST(internet)
|
||||
@@ -328,5 +346,6 @@ START_TEST(internet)
|
||||
test_InternetCanonicalizeUrlA();
|
||||
test_InternetQueryOptionA();
|
||||
test_get_cookie();
|
||||
test_version();
|
||||
test_null();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ extern void func_generated(void);
|
||||
extern void func_http(void);
|
||||
extern void func_internet(void);
|
||||
extern void func_url(void);
|
||||
extern void func_urlcache(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
@@ -19,5 +20,6 @@ const struct test winetest_testlist[] =
|
||||
{ "http", func_http },
|
||||
{ "internet", func_internet },
|
||||
{ "url", func_url },
|
||||
{ "urlcache", func_urlcache },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -452,7 +452,7 @@ static void InternetCreateUrlA_test(void)
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ok(len == -1, "Expected len -1, got %d\n", len);
|
||||
|
||||
/* test valid lpUrlComponets, NULL lpdwUrlLength */
|
||||
/* test valid lpUrlComponents, NULL lpdwUrlLength */
|
||||
fill_url_components(&urlComp);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = InternetCreateUrlA(&urlComp, 0, NULL, NULL);
|
||||
@@ -461,7 +461,7 @@ static void InternetCreateUrlA_test(void)
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ok(len == -1, "Expected len -1, got %d\n", len);
|
||||
|
||||
/* test valid lpUrlComponets, empty szUrl
|
||||
/* test valid lpUrlComponents, empty szUrl
|
||||
* lpdwUrlLength is size of buffer required on exit, including
|
||||
* the terminating null when GLE == ERROR_INSUFFICIENT_BUFFER
|
||||
*/
|
||||
@@ -481,7 +481,7 @@ static void InternetCreateUrlA_test(void)
|
||||
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
|
||||
ok(len == 51, "Expected len 51, got %d\n", len);
|
||||
|
||||
/* test valid lpUrlComponets, alloced szUrl, small size */
|
||||
/* test valid lpUrlComponents, alloc-ed szUrl, small size */
|
||||
SetLastError(0xdeadbeef);
|
||||
szUrl = HeapAlloc(GetProcessHeap(), 0, len);
|
||||
len -= 2;
|
||||
@@ -491,7 +491,7 @@ static void InternetCreateUrlA_test(void)
|
||||
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
|
||||
ok(len == 51, "Expected len 51, got %d\n", len);
|
||||
|
||||
/* alloced szUrl, NULL lpszScheme
|
||||
/* alloc-ed szUrl, NULL lpszScheme
|
||||
* shows that it uses nScheme instead
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
@@ -503,7 +503,7 @@ static void InternetCreateUrlA_test(void)
|
||||
ok(len == 50, "Expected len 50, got %d\n", len);
|
||||
ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
|
||||
|
||||
/* alloced szUrl, invalid nScheme
|
||||
/* alloc-ed szUrl, invalid nScheme
|
||||
* any nScheme out of range seems ignored
|
||||
*/
|
||||
fill_url_components(&urlComp);
|
||||
@@ -516,7 +516,7 @@ static void InternetCreateUrlA_test(void)
|
||||
"Expected 0xdeadbeef, got %d\n", GetLastError());
|
||||
ok(len == 50, "Expected len 50, got %d\n", len);
|
||||
|
||||
/* test valid lpUrlComponets, alloced szUrl */
|
||||
/* test valid lpUrlComponents, alloc-ed szUrl */
|
||||
fill_url_components(&urlComp);
|
||||
SetLastError(0xdeadbeef);
|
||||
len = 51;
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* URL Cache Tests
|
||||
*
|
||||
* Copyright 2008 Robert Shearman 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wininet.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
#define TEST_URL "http://urlcachetest.winehq.org/index.html"
|
||||
|
||||
static char filenameA[MAX_PATH + 1];
|
||||
|
||||
static void check_cache_entry_infoA(const char *returnedfrom, LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo)
|
||||
{
|
||||
ok(lpCacheEntryInfo->dwStructSize == sizeof(*lpCacheEntryInfo), "%s: dwStructSize was %d\n", returnedfrom, lpCacheEntryInfo->dwStructSize);
|
||||
ok(!strcmp(lpCacheEntryInfo->lpszSourceUrlName, TEST_URL), "%s: lpszSourceUrlName should be %s instead of %s\n", returnedfrom, TEST_URL, lpCacheEntryInfo->lpszSourceUrlName);
|
||||
ok(!strcmp(lpCacheEntryInfo->lpszLocalFileName, filenameA), "%s: lpszLocalFileName should be %s instead of %s\n", returnedfrom, filenameA, lpCacheEntryInfo->lpszLocalFileName);
|
||||
ok(!strcmp(lpCacheEntryInfo->lpszFileExtension, "html"), "%s: lpszFileExtension should be html instead of %s\n", returnedfrom, lpCacheEntryInfo->lpszFileExtension);
|
||||
}
|
||||
|
||||
static void test_find_url_cache_entriesA(void)
|
||||
{
|
||||
BOOL ret;
|
||||
HANDLE hEnumHandle;
|
||||
BOOL found = FALSE;
|
||||
DWORD cbCacheEntryInfo;
|
||||
DWORD cbCacheEntryInfoSaved;
|
||||
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
|
||||
|
||||
cbCacheEntryInfo = 0;
|
||||
hEnumHandle = FindFirstUrlCacheEntry(NULL, NULL, &cbCacheEntryInfo);
|
||||
ok(!hEnumHandle, "FindFirstUrlCacheEntry should have failed\n");
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "FindFirstUrlCacheEntry should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
|
||||
lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo * sizeof(char));
|
||||
cbCacheEntryInfoSaved = cbCacheEntryInfo;
|
||||
hEnumHandle = FindFirstUrlCacheEntry(NULL, lpCacheEntryInfo, &cbCacheEntryInfo);
|
||||
ok(hEnumHandle != NULL, "FindFirstUrlCacheEntry failed with error %d\n", GetLastError());
|
||||
while (TRUE)
|
||||
{
|
||||
if (!strcmp(lpCacheEntryInfo->lpszSourceUrlName, TEST_URL))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
cbCacheEntryInfo = cbCacheEntryInfoSaved;
|
||||
ret = FindNextUrlCacheEntry(hEnumHandle, lpCacheEntryInfo, &cbCacheEntryInfo);
|
||||
if (!ret)
|
||||
{
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
lpCacheEntryInfo = HeapReAlloc(GetProcessHeap(), 0, lpCacheEntryInfo, cbCacheEntryInfo);
|
||||
cbCacheEntryInfoSaved = cbCacheEntryInfo;
|
||||
ret = FindNextUrlCacheEntry(hEnumHandle, lpCacheEntryInfo, &cbCacheEntryInfo);
|
||||
}
|
||||
}
|
||||
ok(ret, "FindNextUrlCacheEntry failed with error %d\n", GetLastError());
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
ok(found, "committed url cache entry not found during enumeration\n");
|
||||
|
||||
ret = FindCloseUrlCache(hEnumHandle);
|
||||
ok(ret, "FindCloseUrlCache failed with error %d\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_GetUrlCacheEntryInfoExA(void)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD cbCacheEntryInfo;
|
||||
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
|
||||
|
||||
ret = GetUrlCacheEntryInfoEx(NULL, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
ok(!ret, "GetUrlCacheEntryInfoEx with NULL URL and NULL args should have failed\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetUrlCacheEntryInfoEx with NULL URL and NULL args should have set last error to ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
|
||||
|
||||
ret = GetUrlCacheEntryInfoEx(TEST_URL, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
ok(ret, "GetUrlCacheEntryInfoEx with NULL args failed with error %d\n", GetLastError());
|
||||
|
||||
cbCacheEntryInfo = 0;
|
||||
ret = GetUrlCacheEntryInfoEx(TEST_URL, NULL, &cbCacheEntryInfo, NULL, NULL, NULL, 0);
|
||||
ok(!ret, "GetUrlCacheEntryInfoEx with zero-length buffer should fail\n");
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetUrlCacheEntryInfoEx should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
|
||||
|
||||
lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
|
||||
ret = GetUrlCacheEntryInfoEx(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo, NULL, NULL, NULL, 0);
|
||||
ok(ret, "GetUrlCacheEntryInfoEx failed with error %d\n", GetLastError());
|
||||
|
||||
check_cache_entry_infoA("GetUrlCacheEntryInfoEx", lpCacheEntryInfo);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
|
||||
}
|
||||
|
||||
static void test_urlcacheA(void)
|
||||
{
|
||||
BOOL ret;
|
||||
HANDLE hFile;
|
||||
DWORD written;
|
||||
BYTE zero_byte = 0;
|
||||
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
|
||||
DWORD cbCacheEntryInfo;
|
||||
static const FILETIME filetime_zero;
|
||||
|
||||
ret = CreateUrlCacheEntry(TEST_URL, 0, "html", filenameA, 0);
|
||||
ok(ret, "CreateUrlCacheEntry failed with error %d\n", GetLastError());
|
||||
|
||||
hFile = CreateFileA(filenameA, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA failed with error %d\n", GetLastError());
|
||||
|
||||
ret = WriteFile(hFile, &zero_byte, sizeof(zero_byte), &written, NULL);
|
||||
ok(ret, "WriteFile failed with error %d\n", GetLastError());
|
||||
|
||||
CloseHandle(hFile);
|
||||
|
||||
ret = CommitUrlCacheEntry(TEST_URL, filenameA, filetime_zero, filetime_zero, NORMAL_CACHE_ENTRY, NULL, 0, "html", NULL);
|
||||
ok(ret, "CommitUrlCacheEntry failed with error %d\n", GetLastError());
|
||||
|
||||
cbCacheEntryInfo = 0;
|
||||
ret = RetrieveUrlCacheEntryFile(TEST_URL, NULL, &cbCacheEntryInfo, 0);
|
||||
ok(!ret, "RetrieveUrlCacheEntryFile should have failed\n");
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "RetrieveUrlCacheEntryFile should have set last error to ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
|
||||
|
||||
lpCacheEntryInfo = HeapAlloc(GetProcessHeap(), 0, cbCacheEntryInfo);
|
||||
ret = RetrieveUrlCacheEntryFile(TEST_URL, lpCacheEntryInfo, &cbCacheEntryInfo, 0);
|
||||
ok(ret, "RetrieveUrlCacheEntryFile failed with error %d\n", GetLastError());
|
||||
|
||||
check_cache_entry_infoA("RetrieveUrlCacheEntryFile", lpCacheEntryInfo);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, lpCacheEntryInfo);
|
||||
|
||||
ret = UnlockUrlCacheEntryFile(TEST_URL, 0);
|
||||
ok(ret, "UnlockUrlCacheEntryFile failed with error %d\n", GetLastError());
|
||||
|
||||
/* test Find*UrlCacheEntry functions */
|
||||
test_find_url_cache_entriesA();
|
||||
|
||||
test_GetUrlCacheEntryInfoExA();
|
||||
|
||||
ret = DeleteUrlCacheEntry(TEST_URL);
|
||||
ok(ret, "DeleteUrlCacheEntry failed with error %d\n", GetLastError());
|
||||
|
||||
ret = DeleteFile(filenameA);
|
||||
todo_wine
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "local file should no longer exist\n");
|
||||
}
|
||||
|
||||
START_TEST(urlcache)
|
||||
{
|
||||
test_urlcacheA();
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="wininet_winetest" type="win32cui" installbase="bin" installname="wininet_winetest.exe" allowwarnings="true" entrypoint="0">
|
||||
<module name="wininet_winetest" type="win32cui" installbase="bin" installname="wininet_winetest.exe" allowwarnings="true">
|
||||
<include base="wininet_winetest">.</include>
|
||||
<define name="WINVER">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x600</define>
|
||||
@@ -15,6 +15,7 @@
|
||||
<file>http.c</file>
|
||||
<file>internet.c</file>
|
||||
<file>url.c</file>
|
||||
<file>urlcache.c</file>
|
||||
<file>testlist.c</file>
|
||||
</module>
|
||||
</group>
|
||||
|
||||
Reference in New Issue
Block a user