diff --git a/rostests/winetests/directory.rbuild b/rostests/winetests/directory.rbuild
index 45973de379b..983cb14b7b4 100644
--- a/rostests/winetests/directory.rbuild
+++ b/rostests/winetests/directory.rbuild
@@ -67,10 +67,10 @@
-
diff --git a/rostests/winetests/netapi32/access.c b/rostests/winetests/netapi32/access.c
index 7d5f55a9074..b1036a9d787 100644
--- a/rostests/winetests/netapi32/access.c
+++ b/rostests/winetests/netapi32/access.c
@@ -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,
diff --git a/rostests/winetests/netapi32/netapi32.rbuild b/rostests/winetests/netapi32/netapi32.rbuild
index 42143d0bab6..b8774cde957 100644
--- a/rostests/winetests/netapi32/netapi32.rbuild
+++ b/rostests/winetests/netapi32/netapi32.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/netapi32/wksta.c b/rostests/winetests/netapi32/wksta.c
index 5eefba4e552..01d0d6f7f38 100644
--- a/rostests/winetests/netapi32/wksta.c
+++ b/rostests/winetests/netapi32/wksta.c
@@ -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) +
diff --git a/rostests/winetests/ntdll/atom.c b/rostests/winetests/ntdll/atom.c
index 6ef6ee87e7e..87ea222a8f7 100755
--- a/rostests/winetests/ntdll/atom.c
+++ b/rostests/winetests/ntdll/atom.c
@@ -25,7 +25,7 @@
#include
#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';
diff --git a/rostests/winetests/ntdll/change.c b/rostests/winetests/ntdll/change.c
index 1155df998cb..d3ba58fc1c1 100644
--- a/rostests/winetests/ntdll/change.c
+++ b/rostests/winetests/ntdll/change.c
@@ -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();
diff --git a/rostests/winetests/ntdll/env.c b/rostests/winetests/ntdll/env.c
index 230398b9f35..3363e73484e 100755
--- a/rostests/winetests/ntdll/env.c
+++ b/rostests/winetests/ntdll/env.c
@@ -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);
diff --git a/rostests/winetests/ntdll/error.c b/rostests/winetests/ntdll/error.c
index 9679c8f3423..b00b83bd661 100755
--- a/rostests/winetests/ntdll/error.c
+++ b/rostests/winetests/ntdll/error.c
@@ -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);
diff --git a/rostests/winetests/ntdll/exception.c b/rostests/winetests/ntdll/exception.c
index e0aca2c97a4..e256e187066 100644
--- a/rostests/winetests/ntdll/exception.c
+++ b/rostests/winetests/ntdll/exception.c
@@ -19,20 +19,7 @@
*/
#include
-
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x500 /* For NTSTATUS */
-#endif
-
#include
-#define WIN32_NO_STATUS
-#include
-#define NTOS_MODE_USER
-#include
-
-#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
}
diff --git a/rostests/winetests/ntdll/file.c b/rostests/winetests/ntdll/file.c
new file mode 100644
index 00000000000..6d37390f0b9
--- /dev/null
+++ b/rostests/winetests/ntdll/file.c
@@ -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
+#include
+
+#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();
+}
diff --git a/rostests/winetests/ntdll/generated.c b/rostests/winetests/ntdll/generated.c
index 6ac1749d301..4818c9e50eb 100755
--- a/rostests/winetests/ntdll/generated.c
+++ b/rostests/winetests/ntdll/generated.c
@@ -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();
diff --git a/rostests/winetests/ntdll/info.c b/rostests/winetests/ntdll/info.c
index b134af57980..9fab8065969 100755
--- a/rostests/winetests/ntdll/info.c
+++ b/rostests/winetests/ntdll/info.c
@@ -19,37 +19,39 @@
*/
#include "ntdll_test.h"
+#include
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:: 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();
}
diff --git a/rostests/winetests/ntdll/large_int.c b/rostests/winetests/ntdll/large_int.c
index a8fe2f563e6..bec8ad9bf8f 100755
--- a/rostests/winetests/ntdll/large_int.c
+++ b/rostests/winetests/ntdll/large_int.c
@@ -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);
}
diff --git a/rostests/winetests/ntdll/ntdll.rbuild b/rostests/winetests/ntdll/ntdll.rbuild
index 886ac2af625..7af6b4450c7 100644
--- a/rostests/winetests/ntdll/ntdll.rbuild
+++ b/rostests/winetests/ntdll/ntdll.rbuild
@@ -1,6 +1,11 @@
+
+
+
.
+ 0x0600
+ 0x609
kernel32
ntdll
atom.c
@@ -8,6 +13,7 @@
env.c
error.c
exception.c
+ file.c
info.c
large_int.c
om.c
@@ -21,3 +27,4 @@
time.c
testlist.c
+
diff --git a/rostests/winetests/ntdll/ntdll_test.h b/rostests/winetests/ntdll/ntdll_test.h
index d083729c03f..167e5ca708c 100755
--- a/rostests/winetests/ntdll/ntdll_test.h
+++ b/rostests/winetests/ntdll/ntdll_test.h
@@ -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
diff --git a/rostests/winetests/ntdll/om.c b/rostests/winetests/ntdll/om.c
index acd947c17a4..d211ea00432 100644
--- a/rostests/winetests/ntdll/om.c
+++ b/rostests/winetests/ntdll/om.c
@@ -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();
}
diff --git a/rostests/winetests/ntdll/path.c b/rostests/winetests/ntdll/path.c
index 8423c09a1cd..99d94829bcb 100755
--- a/rostests/winetests/ntdll/path.c
+++ b/rostests/winetests/ntdll/path.c
@@ -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);
diff --git a/rostests/winetests/ntdll/port.c b/rostests/winetests/ntdll/port.c
index 6c79970a9ba..971591737a7 100644
--- a/rostests/winetests/ntdll/port.c
+++ b/rostests/winetests/ntdll/port.c
@@ -20,8 +20,15 @@
#include
#include
-#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
diff --git a/rostests/winetests/ntdll/reg.c b/rostests/winetests/ntdll/reg.c
index a2ee8d3c382..3efdfabaf45 100755
--- a/rostests/winetests/ntdll/reg.c
+++ b/rostests/winetests/ntdll/reg.c
@@ -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);
diff --git a/rostests/winetests/ntdll/rtl.c b/rostests/winetests/ntdll/rtl.c
index 72de77349f5..443b987c1f2 100755
--- a/rostests/winetests/ntdll/rtl.c
+++ b/rostests/winetests/ntdll/rtl.c
@@ -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)
diff --git a/rostests/winetests/ntdll/rtlbitmap.c b/rostests/winetests/ntdll/rtlbitmap.c
index d45eedcaf20..fc7f6c55fc9 100755
--- a/rostests/winetests/ntdll/rtlbitmap.c
+++ b/rostests/winetests/ntdll/rtlbitmap.c
@@ -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);
diff --git a/rostests/winetests/ntdll/rtlstr.c b/rostests/winetests/ntdll/rtlstr.c
index b60f54fdab2..5239de07e04 100755
--- a/rostests/winetests/ntdll/rtlstr.c
+++ b/rostests/winetests/ntdll/rtlstr.c
@@ -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();
diff --git a/rostests/winetests/ntdll/string.c b/rostests/winetests/ntdll/string.c
index a1bc87229a8..e9bf5e10704 100755
--- a/rostests/winetests/ntdll/string.c
+++ b/rostests/winetests/ntdll/string.c
@@ -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");
diff --git a/rostests/winetests/ntdll/testlist.c b/rostests/winetests/ntdll/testlist.c
index 1797ab97be7..0162d0f8937 100644
--- a/rostests/winetests/ntdll/testlist.c
+++ b/rostests/winetests/ntdll/testlist.c
@@ -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 },
diff --git a/rostests/winetests/ntdll/time.c b/rostests/winetests/ntdll/time.c
index 1f6cbc31811..2e9adbc11a5 100755
--- a/rostests/winetests/ntdll/time.c
+++ b/rostests/winetests/ntdll/time.c
@@ -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;
diff --git a/rostests/winetests/odbccp32/misc.c b/rostests/winetests/odbccp32/misc.c
index f5ea5361a0b..ba8e5f45f87 100644
--- a/rostests/winetests/odbccp32/misc.c
+++ b/rostests/winetests/odbccp32/misc.c
@@ -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);
diff --git a/rostests/winetests/odbccp32/odbccp32.rbuild b/rostests/winetests/odbccp32/odbccp32.rbuild
index 3c39cc72303..faad1e73436 100644
--- a/rostests/winetests/odbccp32/odbccp32.rbuild
+++ b/rostests/winetests/odbccp32/odbccp32.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/ole32/clipboard.c b/rostests/winetests/ole32/clipboard.c
index 0127ce5e44c..e365ee8fc69 100644
--- a/rostests/winetests/ole32/clipboard.c
+++ b/rostests/winetests/ole32/clipboard.c
@@ -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);
diff --git a/rostests/winetests/ole32/marshal.c b/rostests/winetests/ole32/marshal.c
index c7f79961bcf..fade8b075a1 100644
--- a/rostests/winetests/ole32/marshal.c
+++ b/rostests/winetests/ole32/marshal.c
@@ -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();
diff --git a/rostests/winetests/ole32/moniker.c b/rostests/winetests/ole32/moniker.c
index 3f3579ae765..b15cce43e5e 100644
--- a/rostests/winetests/ole32/moniker.c
+++ b/rostests/winetests/ole32/moniker.c
@@ -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();
diff --git a/rostests/winetests/ole32/ole32.rbuild b/rostests/winetests/ole32/ole32.rbuild
index 27202e575e9..4438cdf49bb 100644
--- a/rostests/winetests/ole32/ole32.rbuild
+++ b/rostests/winetests/ole32/ole32.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/psapi/psapi.rbuild b/rostests/winetests/psapi/psapi.rbuild
index 97725f7244a..9eb16472ef7 100644
--- a/rostests/winetests/psapi/psapi.rbuild
+++ b/rostests/winetests/psapi/psapi.rbuild
@@ -1,3 +1,6 @@
+
+
+
.
@@ -7,3 +10,4 @@
testlist.c
psapi_main.c
+
diff --git a/rostests/winetests/psapi/psapi_main.c b/rostests/winetests/psapi/psapi_main.c
index ee8f8ab803b..1978fd4d787 100644
--- a/rostests/winetests/psapi/psapi_main.c
+++ b/rostests/winetests/psapi/psapi_main.c
@@ -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);
}
diff --git a/rostests/winetests/riched20/editor.c b/rostests/winetests/riched20/editor.c
index 090eaad0320..1d64580b02d 100644
--- a/rostests/winetests/riched20/editor.c
+++ b/rostests/winetests/riched20/editor.c
@@ -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
diff --git a/rostests/winetests/riched20/riched20.rbuild b/rostests/winetests/riched20/riched20.rbuild
index 86c225b7b2d..94404acbe00 100644
--- a/rostests/winetests/riched20/riched20.rbuild
+++ b/rostests/winetests/riched20/riched20.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/riched32/editor.c b/rostests/winetests/riched32/editor.c
index 66a30909f3e..ff82654ff6e 100644
--- a/rostests/winetests/riched32/editor.c
+++ b/rostests/winetests/riched32/editor.c
@@ -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.
diff --git a/rostests/winetests/riched32/riched32.rbuild b/rostests/winetests/riched32/riched32.rbuild
index 4c328a2301f..0b2cca9a566 100644
--- a/rostests/winetests/riched32/riched32.rbuild
+++ b/rostests/winetests/riched32/riched32.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/rpcrt4/cstub.c b/rostests/winetests/rpcrt4/cstub.c
index 6a38397f679..a47fa6eeb14 100644
--- a/rostests/winetests/rpcrt4/cstub.c
+++ b/rostests/winetests/rpcrt4/cstub.c
@@ -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);
}
diff --git a/rostests/winetests/rpcrt4/generated.c b/rostests/winetests/rpcrt4/generated.c
index fb7d7cca108..b281d0bb1fc 100644
--- a/rostests/winetests/rpcrt4/generated.c
+++ b/rostests/winetests/rpcrt4/generated.c
@@ -21,7 +21,7 @@
#include "wine/test.h"
/***********************************************************************
- * Compability macros
+ * Compatibility macros
*/
#define DWORD_PTR UINT_PTR
diff --git a/rostests/winetests/rpcrt4/ndr_marshall.c b/rostests/winetests/rpcrt4/ndr_marshall.c
index eadb9c7395b..1ff5e3b0438 100644
--- a/rostests/winetests/rpcrt4/ndr_marshall.c
+++ b/rostests/winetests/rpcrt4/ndr_marshall.c
@@ -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();
}
diff --git a/rostests/winetests/rpcrt4/rpc.c b/rostests/winetests/rpcrt4/rpc.c
index a72037012be..4197707d7d4 100644
--- a/rostests/winetests/rpcrt4/rpc.c
+++ b/rostests/winetests/rpcrt4/rpc.c
@@ -21,11 +21,14 @@
#include
#include
+#include
+#define WIN32_NO_STATUS
#include "wine/test.h"
#include
#include
#include
#include
+#include
#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();
}
diff --git a/rostests/winetests/rpcrt4/rpc_async.c b/rostests/winetests/rpcrt4/rpc_async.c
new file mode 100644
index 00000000000..0cc5557ce06
--- /dev/null
+++ b/rostests/winetests/rpcrt4/rpc_async.c
@@ -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
+
+#include "wine/test.h"
+
+#include
+#include
+
+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();
+}
diff --git a/rostests/winetests/rpcrt4/rpcrt4.rbuild b/rostests/winetests/rpcrt4/rpcrt4.rbuild
index d1badbcda0d..5e8209495e0 100644
--- a/rostests/winetests/rpcrt4/rpcrt4.rbuild
+++ b/rostests/winetests/rpcrt4/rpcrt4.rbuild
@@ -21,6 +21,7 @@
generated.c
ndr_marshall.c
rpc.c
+ rpc_async.c
server.c
testlist.c
-
\ No newline at end of file
+
diff --git a/rostests/winetests/rpcrt4/server.c b/rostests/winetests/rpcrt4/server.c
index 7f255189fe3..eb1baacd6c5 100644
--- a/rostests/winetests/rpcrt4/server.c
+++ b/rostests/winetests/rpcrt4/server.c
@@ -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];
diff --git a/rostests/winetests/rpcrt4/server.idl b/rostests/winetests/rpcrt4/server.idl
index ec517572dc3..33e3a480a1c 100644
--- a/rostests/winetests/rpcrt4/server.idl
+++ b/rostests/winetests/rpcrt4/server.idl
@@ -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);
diff --git a/rostests/winetests/rpcrt4/testlist.c b/rostests/winetests/rpcrt4/testlist.c
index 3a7fecf1fdc..8983d699dff 100644
--- a/rostests/winetests/rpcrt4/testlist.c
+++ b/rostests/winetests/rpcrt4/testlist.c
@@ -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 }
};
diff --git a/rostests/winetests/rsabase/rsabase.rbuild b/rostests/winetests/rsabase/rsabase.rbuild
index f6399a28fd6..65d4fc5ad8b 100644
--- a/rostests/winetests/rsabase/rsabase.rbuild
+++ b/rostests/winetests/rsabase/rsabase.rbuild
@@ -1,6 +1,6 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/rsaenh/rsaenh.c b/rostests/winetests/rsaenh/rsaenh.c
index 4fef6e9fb5b..0119f287a57 100644
--- a/rostests/winetests/rsaenh/rsaenh.c
+++ b/rostests/winetests/rsaenh/rsaenh.c
@@ -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());
diff --git a/rostests/winetests/rsaenh/rsaenh.rbuild b/rostests/winetests/rsaenh/rsaenh.rbuild
index 94d58ac95b8..7ef53f8c231 100644
--- a/rostests/winetests/rsaenh/rsaenh.rbuild
+++ b/rostests/winetests/rsaenh/rsaenh.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/schannel/main.c b/rostests/winetests/schannel/main.c
index af245d85c04..814b60a696c 100644
--- a/rostests/winetests/schannel/main.c
+++ b/rostests/winetests/schannel/main.c
@@ -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)
diff --git a/rostests/winetests/schannel/schannel.rbuild b/rostests/winetests/schannel/schannel.rbuild
index d8d051b2d00..500c97bcd15 100644
--- a/rostests/winetests/schannel/schannel.rbuild
+++ b/rostests/winetests/schannel/schannel.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/setupapi/devinst.c b/rostests/winetests/setupapi/devinst.c
new file mode 100644
index 00000000000..727e4540c47
--- /dev/null
+++ b/rostests/winetests/setupapi/devinst.c
@@ -0,0 +1,1096 @@
+/*
+ * Devinst tests
+ *
+ * Copyright 2006 Christian Gmeiner
+ *
+ * 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
+#include
+#include
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "guiddef.h"
+#include "setupapi.h"
+
+#include "wine/test.h"
+
+/* function pointers */
+static HMODULE hSetupAPI;
+static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoList)(GUID*,HWND);
+static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoListExW)(GUID*,HWND,PCWSTR,PVOID);
+static BOOL (WINAPI *pSetupDiCreateDeviceInterfaceA)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, PCSTR, DWORD, PSP_DEVICE_INTERFACE_DATA);
+static BOOL (WINAPI *pSetupDiCallClassInstaller)(DI_FUNCTION, HDEVINFO, PSP_DEVINFO_DATA);
+static BOOL (WINAPI *pSetupDiDestroyDeviceInfoList)(HDEVINFO);
+static BOOL (WINAPI *pSetupDiEnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
+static BOOL (WINAPI *pSetupDiEnumDeviceInterfaces)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, DWORD, PSP_DEVICE_INTERFACE_DATA);
+static BOOL (WINAPI *pSetupDiInstallClassA)(HWND, PCSTR, DWORD, HSPFILEQ);
+static HKEY (WINAPI *pSetupDiOpenClassRegKeyExA)(GUID*,REGSAM,DWORD,PCSTR,PVOID);
+static HKEY (WINAPI *pSetupDiOpenDevRegKey)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM);
+static HKEY (WINAPI *pSetupDiCreateDevRegKeyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, HINF, PCWSTR);
+static BOOL (WINAPI *pSetupDiCreateDeviceInfoA)(HDEVINFO, PCSTR, GUID *, PCSTR, HWND, DWORD, PSP_DEVINFO_DATA);
+static BOOL (WINAPI *pSetupDiCreateDeviceInfoW)(HDEVINFO, PCWSTR, GUID *, PCWSTR, HWND, DWORD, PSP_DEVINFO_DATA);
+static BOOL (WINAPI *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PSTR, DWORD, PDWORD);
+static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailA)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA);
+static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailW)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, DWORD, PDWORD, PSP_DEVINFO_DATA);
+static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA);
+static HDEVINFO (WINAPI *pSetupDiGetClassDevsA)(CONST GUID *, LPCSTR, HWND, DWORD);
+static HDEVINFO (WINAPI *pSetupDiGetClassDevsW)(CONST GUID *, LPCWSTR, HWND, DWORD);
+static BOOL (WINAPI *pSetupDiSetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE *, DWORD);
+static BOOL (WINAPI *pSetupDiSetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE *, DWORD);
+static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
+static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
+
+static void init_function_pointers(void)
+{
+ hSetupAPI = GetModuleHandleA("setupapi.dll");
+
+ pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
+ pSetupDiCreateDeviceInfoW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoW");
+ pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
+ pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
+ pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
+ pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
+ pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
+ pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
+ pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
+ pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
+ pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
+ pSetupDiGetDeviceInterfaceDetailW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailW");
+ pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
+ pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
+ pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
+ pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
+ pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
+ pSetupDiGetClassDevsA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA");
+ pSetupDiGetClassDevsW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsW");
+ pSetupDiSetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyA");
+ pSetupDiSetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyW");
+ pSetupDiGetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyA");
+ pSetupDiGetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW");
+}
+
+/* RegDeleteTreeW from dlls/advapi32/registry.c */
+LSTATUS WINAPI devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
+{
+ LONG ret;
+ DWORD dwMaxSubkeyLen, dwMaxValueLen;
+ DWORD dwMaxLen, dwSize;
+ WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
+ HKEY hSubKey = hKey;
+
+ if(lpszSubKey)
+ {
+ ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+ if (ret) return ret;
+ }
+
+ /* Get highest length for keys, values */
+ ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
+ &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
+ if (ret) goto cleanup;
+
+ dwMaxSubkeyLen++;
+ dwMaxValueLen++;
+ dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
+ if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
+ {
+ /* Name too big: alloc a buffer for it */
+ if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
+ {
+ ret = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
+ }
+ }
+
+
+ /* Recursively delete all the subkeys */
+ while (TRUE)
+ {
+ dwSize = dwMaxLen;
+ if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
+ NULL, NULL, NULL)) break;
+
+ ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
+ if (ret) goto cleanup;
+ }
+
+ if (lpszSubKey)
+ ret = RegDeleteKeyW(hKey, lpszSubKey);
+ else
+ while (TRUE)
+ {
+ dwSize = dwMaxLen;
+ if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
+ NULL, NULL, NULL, NULL)) break;
+
+ ret = RegDeleteValueW(hKey, lpszName);
+ if (ret) goto cleanup;
+ }
+
+cleanup:
+ /* Free buffer if allocated */
+ if (lpszName != szNameBuf)
+ HeapFree( GetProcessHeap(), 0, lpszName);
+ if(lpszSubKey)
+ RegCloseKey(hSubKey);
+ return ret;
+}
+
+
+static void test_SetupDiCreateDeviceInfoListEx(void)
+{
+ HDEVINFO devlist;
+ BOOL ret;
+ DWORD error;
+ static CHAR notnull[] = "NotNull";
+ static const WCHAR machine[] = { 'd','u','m','m','y',0 };
+
+ SetLastError(0xdeadbeef);
+ /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
+ devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
+
+ error = GetLastError();
+ if (error == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
+ return;
+ }
+ ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
+ ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
+
+ SetLastError(0xdeadbeef);
+ /* create empty DeviceInfoList, but set MachineName to something */
+ devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
+
+ error = GetLastError();
+ ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
+ ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
+
+ /* create empty DeviceInfoList */
+ devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
+ ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
+
+ /* destroy DeviceInfoList */
+ ret = pSetupDiDestroyDeviceInfoList(devlist);
+ ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
+}
+
+static void test_SetupDiOpenClassRegKeyExA(void)
+{
+ /* This is a unique guid for testing purposes */
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
+ HKEY hkey;
+
+ /* Check return value for nonexistent key */
+ hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
+ DIOCR_INSTALLER, NULL, NULL);
+ ok(hkey == INVALID_HANDLE_VALUE,
+ "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
+
+ /* Test it for a key that exists */
+ hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
+ if (hkey != INVALID_HANDLE_VALUE)
+ {
+ HKEY classKey;
+ if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
+ {
+ RegCloseKey(classKey);
+ SetLastError(0xdeadbeef);
+ classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
+ DIOCR_INSTALLER, NULL, NULL);
+ ok(classKey != INVALID_HANDLE_VALUE,
+ "opening class registry key failed with error %d\n",
+ GetLastError());
+ if (classKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(classKey);
+ RegDeleteKeyA(hkey, guidString);
+ }
+ else
+ trace("failed to create registry key for test\n");
+ }
+ else
+ trace("failed to open classes key\n");
+}
+
+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, "Class=Bogus\n");
+ append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
+ append_str(&ptr, "[ClassInstall32]\n");
+ append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
+ append_str(&ptr, "[BogusClass.NT.AddReg]\n");
+ append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
+
+ WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
+ CloseHandle(hf);
+}
+
+static void get_temp_filename(LPSTR path)
+{
+ static char curr[MAX_PATH] = { 0 };
+ char temp[MAX_PATH];
+ LPSTR ptr;
+
+ if (!*curr)
+ GetCurrentDirectoryA(MAX_PATH, curr);
+ GetTempFileNameA(curr, "set", 0, temp);
+ ptr = strrchr(temp, '\\');
+
+ lstrcpyA(path, ptr + 1);
+}
+
+static void testInstallClass(void)
+{
+ static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
+ '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
+ '1','1','d','b','-','b','7','0','4','-',
+ '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
+ static const CHAR classKey_win9x[] =
+ "System\\CurrentControlSet\\Services\\Class\\"
+ "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
+ static const CHAR bogus_win9x[] =
+ "System\\CurrentControlSet\\Services\\Class\\Bogus";
+ char tmpfile[MAX_PATH];
+ BOOL ret;
+ HKEY hkey;
+
+ if (!pSetupDiInstallClassA)
+ {
+ skip("No SetupDiInstallClassA\n");
+ return;
+ }
+ tmpfile[0] = '.';
+ tmpfile[1] = '\\';
+ get_temp_filename(tmpfile + 2);
+ create_inf_file(tmpfile + 2);
+
+ ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
+ "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
+ /* The next call will succeed. Information is put into the registry but the
+ * location(s) is/are depending on the Windows version.
+ */
+ ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
+ ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
+ if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, classKey_win9x, &hkey))
+ {
+ /* We are on win9x */
+ RegCloseKey(hkey);
+ ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, classKey_win9x),
+ "Couldn't delete win9x classkey\n");
+ ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus_win9x),
+ "Couldn't delete win9x bogus services class\n");
+ }
+ else
+ {
+ /* NT4 and above */
+ ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
+ "Couldn't delete NT classkey\n");
+ }
+ DeleteFile(tmpfile);
+}
+
+static void testCreateDeviceInfo(void)
+{
+ BOOL ret;
+ HDEVINFO set;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+
+ if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
+ !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
+ {
+ skip("No SetupDiCreateDeviceInfoA\n");
+ return;
+ }
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_DEVINST_NAME,
+ "Expected ERROR_INVALID_DEVINST_NAME, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
+ NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
+ set = pSetupDiCreateDeviceInfoList(&guid, NULL);
+ ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
+ GetLastError());
+ if (set)
+ {
+ SP_DEVINFO_DATA devInfo = { 0 };
+ DWORD i;
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
+ NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ /* Finally, with all three required parameters, this succeeds: */
+ ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
+ NULL, NULL, 0, NULL);
+ ok(ret, "pSetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ /* This fails because the device ID already exists.. */
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
+ NULL, NULL, 0, &devInfo);
+ ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
+ "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
+ /* whereas this "fails" because cbSize is wrong.. */
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
+ DICD_GENERATE_ID, &devInfo);
+ ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
+ "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
+ devInfo.cbSize = sizeof(devInfo);
+ ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
+ DICD_GENERATE_ID, &devInfo);
+ /* and this finally succeeds. */
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ /* There were three devices added, however - the second failure just
+ * resulted in the SP_DEVINFO_DATA not getting copied.
+ */
+ SetLastError(0xdeadbeef);
+ i = 0;
+ while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
+ i++;
+ ok(i == 3, "Expected 3 devices, got %d\n", i);
+ ok(GetLastError() == ERROR_NO_MORE_ITEMS,
+ "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+}
+
+static void testGetDeviceInstanceId(void)
+{
+ BOOL ret;
+ HDEVINFO set;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ SP_DEVINFO_DATA devInfo = { 0 };
+
+ if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
+ !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
+ {
+ skip("No SetupDiGetDeviceInstanceIdA\n");
+ return;
+ }
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
+ set = pSetupDiCreateDeviceInfoList(&guid, NULL);
+ ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
+ GetLastError());
+ if (set)
+ {
+ char instanceID[MAX_PATH];
+ DWORD size;
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ devInfo.cbSize = sizeof(devInfo);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
+ NULL, NULL, 0, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
+ ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
+ sizeof(instanceID), NULL);
+ ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
+ ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
+ "Unexpected instance ID %s\n", instanceID);
+ ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
+ NULL, NULL, DICD_GENERATE_ID, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
+ sizeof(instanceID), NULL);
+ ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
+ ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
+ "Unexpected instance ID %s\n", instanceID);
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+}
+
+static void testRegisterDeviceInfo(void)
+{
+ BOOL ret;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ HDEVINFO set;
+
+ if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
+ !pSetupDiRegisterDeviceInfo)
+ {
+ skip("No SetupDiRegisterDeviceInfo\n");
+ return;
+ }
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
+ set = pSetupDiCreateDeviceInfoList(&guid, NULL);
+ ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
+ if (set)
+ {
+ SP_DEVINFO_DATA devInfo = { 0 };
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ devInfo.cbSize = sizeof(devInfo);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
+ NULL, NULL, 0, &devInfo);
+ ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
+ "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
+ if (ret)
+ {
+ /* If it already existed, registering it again will fail */
+ ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
+ NULL);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
+ }
+ /* FIXME: On Win2K+ systems, this is now persisted to registry in
+ * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
+ * Win9x location is different.
+ * FIXME: the key also becomes undeletable. How to get rid of it?
+ */
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+}
+
+static void testCreateDeviceInterface(void)
+{
+ BOOL ret;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ HDEVINFO set;
+
+ if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
+ !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
+ !pSetupDiEnumDeviceInterfaces)
+ {
+ skip("No SetupDiCreateDeviceInterfaceA\n");
+ return;
+ }
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ set = pSetupDiCreateDeviceInfoList(&guid, NULL);
+ ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
+ if (set)
+ {
+ SP_DEVINFO_DATA devInfo = { 0 };
+ SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
+ { 0 } };
+ DWORD i;
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
+ NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ devInfo.cbSize = sizeof(devInfo);
+ ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
+ NULL, NULL, 0, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
+ NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
+ "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
+ ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
+ NULL);
+ ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
+ /* Creating the same interface a second time succeeds */
+ ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
+ NULL);
+ ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
+ ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
+ NULL);
+ ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
+ ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
+ &interfaceData);
+ ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
+ i = 0;
+ while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
+ &interfaceData))
+ i++;
+ ok(i == 2, "expected 2 interfaces, got %d\n", i);
+ ok(GetLastError() == ERROR_NO_MORE_ITEMS,
+ "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+}
+
+static void testGetDeviceInterfaceDetail(void)
+{
+ BOOL ret;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ HDEVINFO set;
+
+ if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
+ !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
+ !pSetupDiGetDeviceInterfaceDetailA)
+ {
+ skip("No SetupDiGetDeviceInterfaceDetailA\n");
+ return;
+ }
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ set = pSetupDiCreateDeviceInfoList(&guid, NULL);
+ ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
+ if (set)
+ {
+ SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
+ SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
+ { 0 } };
+ DWORD size = 0;
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
+ NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
+ NULL, NULL, 0, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
+ &interfaceData);
+ ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
+ 0, NULL, NULL);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
+ 100, NULL, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
+ "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
+ 0, &size, NULL);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ static const char path[] =
+ "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
+ LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
+ SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
+ (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
+ DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
+
+ detail->cbSize = 0;
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
+ size, &size, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
+ "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
+ detail->cbSize = size;
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
+ size, &size, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
+ "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
+ detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
+ size, &size, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
+ "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
+ /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
+ * on every call (so doesn't get here) and NT4 doesn't have this function.
+ */
+ detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
+ size, &size, NULL);
+ ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
+ GetLastError());
+ ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
+ detail->DevicePath);
+ /* Check SetupDiGetDeviceInterfaceDetailW */
+ if (pSetupDiGetDeviceInterfaceDetailW)
+ {
+ ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
+ ok(expectedsize == size, "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize: expected %d, got %d\n", expectedsize, size);
+ }
+ else
+ skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
+
+ HeapFree(GetProcessHeap(), 0, buf);
+ }
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+}
+
+static void testDevRegKey(void)
+{
+ static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
+ '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
+ '1','1','d','b','-','b','7','0','4','-',
+ '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
+ BOOL ret;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ HDEVINFO set;
+
+ if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
+ !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
+ !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
+ !pSetupDiCallClassInstaller)
+ {
+ skip("No SetupDiOpenDevRegKey\n");
+ return;
+ }
+ set = pSetupDiCreateDeviceInfoList(&guid, NULL);
+ ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
+ if (set)
+ {
+ SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
+ HKEY key = INVALID_HANDLE_VALUE;
+
+ ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
+ NULL, NULL, 0, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_INVALID_FLAGS,
+ "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_INVALID_FLAGS,
+ "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
+ DIREG_BOTH, 0);
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_INVALID_FLAGS,
+ "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
+ DIREG_DRV, 0);
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
+ "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
+ ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
+ DIREG_DRV, 0);
+ /* The software key isn't created by default */
+ todo_wine
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
+ "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
+ DIREG_DEV, 0);
+ todo_wine
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
+ "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
+ DIREG_DRV, NULL, NULL);
+ ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
+ GetLastError());
+ RegCloseKey(key);
+ SetLastError(0xdeadbeef);
+ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
+ DIREG_DRV, 0);
+ todo_wine
+ ok(key == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_INVALID_DATA,
+ "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
+ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
+ DIREG_DRV, KEY_READ);
+ ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
+ GetLastError());
+ ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+ devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
+}
+
+static void testRegisterAndGetDetail(void)
+{
+ HDEVINFO set;
+ BOOL ret;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
+ SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
+ DWORD dwSize = 0;
+
+ SetLastError(0xdeadbeef);
+ set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
+ ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
+ GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
+ DICD_GENERATE_ID, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
+ ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
+ ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
+
+ pSetupDiDestroyDeviceInfoList(set);
+
+ SetLastError(0xdeadbeef);
+ set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
+ ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
+ GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
+ ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
+ if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ static const char path[] =
+ "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
+ PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
+
+ detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
+ if (detail)
+ {
+ detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
+ detail, dwSize, &dwSize, NULL);
+ ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
+ ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
+ detail->DevicePath);
+ HeapFree(GetProcessHeap(), 0, detail);
+ }
+ }
+
+ pSetupDiDestroyDeviceInfoList(set);
+}
+
+static void testDeviceRegistryPropertyA()
+{
+ HDEVINFO set;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
+ CHAR devName[] = "LEGACY_BOGUS";
+ CHAR friendlyName[] = "Bogus";
+ CHAR buf[6] = "";
+ DWORD buflen = 6;
+ DWORD size;
+ DWORD regType;
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
+ ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
+ GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL,
+ DICD_GENERATE_ID, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
+ "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, 0);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_DATA,
+ "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ (PBYTE)friendlyName, buflen);
+ ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
+ "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, NULL, buflen, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_DATA,
+ "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, NULL, 0, &size);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
+ ok(buflen == size, "Unexpected size: %d\n", size);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, (PBYTE)buf, buflen, NULL);
+ ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
+ ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n");
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ ®Type, (PBYTE)buf, buflen, NULL);
+ ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
+ ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n");
+ ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, 0);
+ ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, (PBYTE)buf, buflen, &size);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_DATA,
+ "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
+ pSetupDiDestroyDeviceInfoList(set);
+}
+
+static void testDeviceRegistryPropertyW()
+{
+ HDEVINFO set;
+ GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
+ 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
+ SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
+ WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0};
+ WCHAR friendlyName[] = {'B','o','g','u','s',0};
+ WCHAR buf[6] = {0};
+ DWORD buflen = 6 * sizeof(WCHAR);
+ DWORD size;
+ DWORD regType;
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
+ if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("W-functions are not implemented\n");
+ return;
+ }
+ ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n",
+ GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL,
+ DICD_GENERATE_ID, &devInfo);
+ ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
+ "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, 0);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_DATA,
+ "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ (PBYTE)friendlyName, buflen);
+ ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
+ "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, NULL, buflen, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_DATA,
+ "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, NULL, 0, &size);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
+ ok(buflen == size, "Unexpected size: %d\n", size);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, (PBYTE)buf, buflen, NULL);
+ ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
+ ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n");
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ ®Type, (PBYTE)buf, buflen, NULL);
+ ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
+ ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n");
+ ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, 0);
+ ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
+ NULL, (PBYTE)buf, buflen, &size);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_DATA,
+ "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
+ pSetupDiDestroyDeviceInfoList(set);
+}
+
+START_TEST(devinst)
+{
+ init_function_pointers();
+
+ if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
+ test_SetupDiCreateDeviceInfoListEx();
+ else
+ skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
+
+ if (pSetupDiOpenClassRegKeyExA)
+ test_SetupDiOpenClassRegKeyExA();
+ else
+ skip("SetupDiOpenClassRegKeyExA is not available\n");
+ testInstallClass();
+ testCreateDeviceInfo();
+ testGetDeviceInstanceId();
+ testRegisterDeviceInfo();
+ testCreateDeviceInterface();
+ testGetDeviceInterfaceDetail();
+ testDevRegKey();
+ testRegisterAndGetDetail();
+ testDeviceRegistryPropertyA();
+ testDeviceRegistryPropertyW();
+}
diff --git a/rostests/winetests/setupapi/install.c b/rostests/winetests/setupapi/install.c
index 14a506215bb..0044f019e4b 100644
--- a/rostests/winetests/setupapi/install.c
+++ b/rostests/winetests/setupapi/install.c
@@ -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
#include
-#include
+#include
+#include
+#include
#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);
}
diff --git a/rostests/winetests/setupapi/misc.c b/rostests/winetests/setupapi/misc.c
new file mode 100644
index 00000000000..f8750b60154
--- /dev/null
+++ b/rostests/winetests/setupapi/misc.c
@@ -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
+#include
+#include
+
+#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();
+}
diff --git a/rostests/winetests/setupapi/parser.c b/rostests/winetests/setupapi/parser.c
index 5556c82432c..6341222819e 100644
--- a/rostests/winetests/setupapi/parser.c
+++ b/rostests/winetests/setupapi/parser.c
@@ -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 );
}
diff --git a/rostests/winetests/setupapi/query.c b/rostests/winetests/setupapi/query.c
index be7f154c174..87f167306ca 100644
--- a/rostests/winetests/setupapi/query.c
+++ b/rostests/winetests/setupapi/query.c
@@ -23,29 +23,9 @@
#include
#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();
}
diff --git a/rostests/winetests/setupapi/setupapi.rbuild b/rostests/winetests/setupapi/setupapi.rbuild
index 9b4ab741170..11bc062bb00 100644
--- a/rostests/winetests/setupapi/setupapi.rbuild
+++ b/rostests/winetests/setupapi/setupapi.rbuild
@@ -1,3 +1,6 @@
+
+
+
.
@@ -5,10 +8,14 @@
kernel32
advapi32
setupapi
+ user32
devclass.c
+ devinst.c
install.c
+ misc.c
parser.c
query.c
stringtable.c
testlist.c
+
diff --git a/rostests/winetests/setupapi/stringtable.c b/rostests/winetests/setupapi/stringtable.c
index fab7a7f62d9..4eca3318553 100644
--- a/rostests/winetests/setupapi/stringtable.c
+++ b/rostests/winetests/setupapi/stringtable.c
@@ -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);
}
diff --git a/rostests/winetests/setupapi/testlist.c b/rostests/winetests/setupapi/testlist.c
index 77623f23a91..ae1785c428e 100644
--- a/rostests/winetests/setupapi/testlist.c
+++ b/rostests/winetests/setupapi/testlist.c
@@ -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 },
diff --git a/rostests/winetests/shlwapi/istream.c b/rostests/winetests/shlwapi/istream.c
index 7172e31f764..ef7191ca4fb 100644
--- a/rostests/winetests/shlwapi/istream.c
+++ b/rostests/winetests/shlwapi/istream.c
@@ -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]);
+ }
}
}
}
diff --git a/rostests/winetests/shlwapi/shlwapi.rbuild b/rostests/winetests/shlwapi/shlwapi.rbuild
index f6d735e0b63..29025301b71 100644
--- a/rostests/winetests/shlwapi/shlwapi.rbuild
+++ b/rostests/winetests/shlwapi/shlwapi.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/shlwapi/url.c b/rostests/winetests/shlwapi/url.c
index 2d63a216f61..cd7a5f20286 100644
--- a/rostests/winetests/shlwapi/url.c
+++ b/rostests/winetests/shlwapi/url.c
@@ -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
-
+
.
0x600
0x600
diff --git a/rostests/winetests/usp10/usp10.c b/rostests/winetests/usp10/usp10.c
index b0b50286cf3..0812f1ab52c 100644
--- a/rostests/winetests/usp10/usp10.c
+++ b/rostests/winetests/usp10/usp10.c
@@ -23,24 +23,60 @@
* and filtering characters and bi-directional text with custom line breaks.
*/
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-//#include
-
+#include
#include
-#include
-#include "usp10.h"
-#include "wine/test.h"
-#include "wine/windef.h"
-BOOL WINAPI ShowWindow(HWND,int);
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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);
diff --git a/rostests/winetests/usp10/usp10.rbuild b/rostests/winetests/usp10/usp10.rbuild
index 9a9d7a8ac7d..d84af63d44c 100644
--- a/rostests/winetests/usp10/usp10.rbuild
+++ b/rostests/winetests/usp10/usp10.rbuild
@@ -1,3 +1,6 @@
+
+
+
.
@@ -9,3 +12,4 @@
usp10.c
testlist.c
+
diff --git a/rostests/winetests/uxtheme/system.c b/rostests/winetests/uxtheme/system.c
index b5f661975fb..ef9c08a2522 100644
--- a/rostests/winetests/uxtheme/system.c
+++ b/rostests/winetests/uxtheme/system.c
@@ -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());
diff --git a/rostests/winetests/uxtheme/uxtheme.rbuild b/rostests/winetests/uxtheme/uxtheme.rbuild
index 7e557299de6..dd6c47418fa 100644
--- a/rostests/winetests/uxtheme/uxtheme.rbuild
+++ b/rostests/winetests/uxtheme/uxtheme.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/version/info.c b/rostests/winetests/version/info.c
index 3bfc9fb5e40..9a6bcf4c932 100644
--- a/rostests/winetests/version/info.c
+++ b/rostests/winetests/version/info.c
@@ -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);
diff --git a/rostests/winetests/version/version.rbuild b/rostests/winetests/version/version.rbuild
index a90ee2eae51..119d262d8ab 100644
--- a/rostests/winetests/version/version.rbuild
+++ b/rostests/winetests/version/version.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
diff --git a/rostests/winetests/wininet/ftp.c b/rostests/winetests/wininet/ftp.c
index 985b23b74b8..992bce99feb 100644
--- a/rostests/winetests/wininet/ftp.c
+++ b/rostests/winetests/wininet/ftp.c
@@ -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());
diff --git a/rostests/winetests/wininet/http.c b/rostests/winetests/wininet/http.c
index ec2df72d988..705fcac6020 100644
--- a/rostests/winetests/wininet/http.c
+++ b/rostests/winetests/wininet/http.c
@@ -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();
}
diff --git a/rostests/winetests/wininet/internet.c b/rostests/winetests/wininet/internet.c
index 8704f7dbd56..15495db514d 100644
--- a/rostests/winetests/wininet/internet.c
+++ b/rostests/winetests/wininet/internet.c
@@ -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();
}
diff --git a/rostests/winetests/wininet/testlist.c b/rostests/winetests/wininet/testlist.c
index df55646f40a..218ba206137 100644
--- a/rostests/winetests/wininet/testlist.c
+++ b/rostests/winetests/wininet/testlist.c
@@ -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 }
};
diff --git a/rostests/winetests/wininet/url.c b/rostests/winetests/wininet/url.c
index dd71edb485e..ccc56076bad 100644
--- a/rostests/winetests/wininet/url.c
+++ b/rostests/winetests/wininet/url.c
@@ -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;
diff --git a/rostests/winetests/wininet/urlcache.c b/rostests/winetests/wininet/urlcache.c
new file mode 100644
index 00000000000..6570d5a9eba
--- /dev/null
+++ b/rostests/winetests/wininet/urlcache.c
@@ -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
+#include
+#include
+
+#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();
+}
diff --git a/rostests/winetests/wininet/wininet.rbuild b/rostests/winetests/wininet/wininet.rbuild
index 434d8454900..5c759d72084 100644
--- a/rostests/winetests/wininet/wininet.rbuild
+++ b/rostests/winetests/wininet/wininet.rbuild
@@ -1,7 +1,7 @@
-
+
.
0x600
0x600
@@ -15,6 +15,7 @@
http.c
internet.c
url.c
+ urlcache.c
testlist.c