ntdll pending some winerror.h fixes

svn path=/trunk/; revision=17133
This commit is contained in:
Steven Edwards 2005-08-07 02:16:34 +00:00
parent 447a3da0ea
commit 57f56eab33
16 changed files with 10654 additions and 0 deletions

View file

@ -0,0 +1,402 @@
/* Unit test suite for Ntdll atom API functions
*
* Copyright 2003 Gyorgy 'Nog' Jeney
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* We use function pointers here as there is no import library for NTDLL on
* windows.
*/
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <stdarg.h>
#include "windows.h"
#include "ntstatus.h"
#include "wine/test.h"
#include "wine/unicode.h"
#include "winternl.h"
/* Function pointers for ntdll calls */
static HMODULE hntdll = 0;
static NTSTATUS (WINAPI *pRtlCreateAtomTable)(ULONG,PRTL_ATOM_TABLE);
static NTSTATUS (WINAPI *pRtlDestroyAtomTable)(RTL_ATOM_TABLE);
static NTSTATUS (WINAPI *pRtlEmptyAtomTable)(RTL_ATOM_TABLE,BOOLEAN);
static NTSTATUS (WINAPI *pRtlAddAtomToAtomTable)(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM);
static NTSTATUS (WINAPI *pRtlDeleteAtomFromAtomTable)(RTL_ATOM_TABLE,RTL_ATOM);
static NTSTATUS (WINAPI *pRtlLookupAtomInAtomTable)(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM);
static NTSTATUS (WINAPI *pRtlPinAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM);
static NTSTATUS (WINAPI *pRtlQueryAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM,PULONG,PULONG,PWSTR,PULONG);
static const WCHAR EmptyAtom[] = {0};
static const WCHAR testAtom1[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
static const WCHAR testAtom2[] = {'H','e','l','l','o',' ','W','o','r','l','d','2',0};
static const WCHAR testAtom3[] = {'H','e','l','l','o',' ','W','o','r','l','d','3',0};
static const WCHAR testAtom1Cap[] = {'H','E','L','L','O',' ','W','O','R','L','D',0};
static const WCHAR testAtom1Low[] = {'h','e','l','l','o',' ','w','o','r','l','d',0};
static const WCHAR testAtomInt[] = {'#','1','3','2',0};
static const WCHAR testAtomIntInv[] = {'#','2','3','4','z',0};
static const WCHAR testAtomOTT[] = {'#','1','2','3',0};
static void InitFunctionPtr(void)
{
hntdll = LoadLibraryA("ntdll.dll");
ok(hntdll != 0, "Unable to load ntdll.dll\n");
if (hntdll)
{
pRtlCreateAtomTable = (void *)GetProcAddress(hntdll, "RtlCreateAtomTable");
pRtlDestroyAtomTable = (void *)GetProcAddress(hntdll, "RtlDestroyAtomTable");
pRtlEmptyAtomTable = (void *)GetProcAddress(hntdll, "RtlEmptyAtomTable");
pRtlAddAtomToAtomTable = (void *)GetProcAddress(hntdll, "RtlAddAtomToAtomTable");
pRtlDeleteAtomFromAtomTable = (void *)GetProcAddress(hntdll, "RtlDeleteAtomFromAtomTable");
pRtlLookupAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlLookupAtomInAtomTable");
pRtlPinAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlPinAtomInAtomTable");
pRtlQueryAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlQueryAtomInAtomTable");
}
}
static DWORD RtlAtomTestThread(LPVOID Table)
{
RTL_ATOM_TABLE AtomTable = *(PRTL_ATOM_TABLE)Table;
RTL_ATOM Atom;
NTSTATUS res;
ULONG RefCount = 0, PinCount = 0, Len = 0;
WCHAR Name[64];
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &Atom);
ok(!res, "Unable to find atom from another thread, retval: %lx\n", res);
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &Atom);
ok(!res, "Unable to lookup pinned atom in table, retval: %lx\n", res);
res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len);
ok(res == STATUS_BUFFER_TOO_SMALL, "We got wrong retval: %lx\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(!strcmpW(Name, testAtom2), "We found wrong atom!!\n");
ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\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(!strcmpW(Name, testAtom2), "Found Wrong atom!\n");
ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
return 0;
}
static void test_NtAtom(void)
{
RTL_ATOM_TABLE AtomTable = NULL;
NTSTATUS res;
RTL_ATOM Atom1, Atom2, Atom3, testEAtom, testAtom;
HANDLE testThread;
ULONG RefCount = 0, PinCount = 0, Len = 0;
WCHAR Name[64];
/* If we pass a non-null string to create atom table, then it thinks that we
* have passed it an already allocated atom table */
res = pRtlCreateAtomTable(0, &AtomTable);
ok(!res, "RtlCreateAtomTable should succeed with an atom table size of 0\n");
if (!res)
{
res = pRtlDestroyAtomTable(AtomTable);
ok(!res, "We could create the atom table, but we couldn't destroy it! retval: %lx\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);
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);
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Cap, &testAtom);
ok(!res, "We were unable to find capital version of the atom, retval: %lx\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(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);
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
ok(!res, "Failed to find totally legitimate atom, retval: %lx\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);
res = pRtlPinAtomInAtomTable(AtomTable, Atom2);
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
testThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)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(!strcmpW(Name, testAtom2), "We found wrong atom\n");
ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
res = pRtlEmptyAtomTable(AtomTable, FALSE);
ok(!res, "Unable to empty atom table, retval %lx\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(!strcmpW(Name, testAtom2), "We found wrong atom\n");
ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
ok(!res, "We can't find our pinned atom!! retval: %lx\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);
res = pRtlAddAtomToAtomTable(AtomTable, testAtom3, &Atom3);
ok(!res, "Unable to add atom to table, retval: %lx\n", res);
res = pRtlEmptyAtomTable(AtomTable, TRUE);
ok(!res, "Unable to empty atom table, retval: %lx\n", res);
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "The pinned atom should be removed, retval: %lx\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);
res = pRtlDestroyAtomTable(AtomTable);
ok(!res, "Can't destroy atom table, retval: %lx\n", res);
}
AtomTable = NULL;
res = pRtlCreateAtomTable(37, &AtomTable);
ok(!res, "Unable to create atom table, retval: %lx\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);
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
ok(!res, "Unable to add atom to atom table, retval %lx\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);
res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
ok(!res, "Unable to delete atom from table, retval: %lx\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);
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
ok(!res, "Unable to add atom to atom table, retval: %lx\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((strlenW(testAtom1) * sizeof(WCHAR)) == Len, "Got wrong length %lx\n", Len);
res = pRtlPinAtomInAtomTable(AtomTable, Atom1);
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
ok(!res, "Unable to find atom in atom table, retval: %lx\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);
res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
ok(!res, "Able to find deleted atom in table\n");
res = pRtlDestroyAtomTable(AtomTable);
ok(!res, "Unable to destroy atom table\n");
}
}
/* Test Adding integer atoms to atom table */
static void test_NtIntAtom(void)
{
NTSTATUS res;
RTL_ATOM_TABLE AtomTable;
RTL_ATOM testAtom;
ULONG RefCount = 0, PinCount = 0;
int i;
WCHAR Name[64];
ULONG Len;
AtomTable = NULL;
res = pRtlCreateAtomTable(37, &AtomTable);
ok(!res, "Unable to create atom table, %lx\n", res);
if (!res)
{
/* According to the kernel32 functions, integer atoms are only allowd 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);
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);
}
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);
if (!res)
{
res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
ok(!res, "Unable to pin int atom %i, retval: %lx\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);
}
res = pRtlDestroyAtomTable(AtomTable);
ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
}
AtomTable = NULL;
res = pRtlCreateAtomTable(37, &AtomTable);
ok(!res, "Unable to create atom table, %lx\n", res);
if (!res)
{
res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)123, &testAtom);
ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
res = pRtlAddAtomToAtomTable(AtomTable, testAtomInt, &testAtom);
ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
res = pRtlAddAtomToAtomTable(AtomTable, testAtomIntInv, &testAtom);
ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
ok(!res, "Unable to re-add int atom to table, retval: %lx\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(!strcmpW(testAtomOTT, Name), "Got wrong atom name\n");
ok((strlenW(testAtomOTT) * sizeof(WCHAR)) == Len, "Got wrong len %ld\n", Len);
res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
ok(!res, "Unable to pin int atom, retval: %lx\n", res);
res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
ok(!res, "Unable to pin int atom, retval: %lx\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);
res = pRtlDestroyAtomTable(AtomTable);
ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
}
}
/* Tests to see how the pincount and refcount actually works */
static void test_NtRefPinAtom(void)
{
RTL_ATOM_TABLE AtomTable;
RTL_ATOM Atom;
ULONG PinCount = 0, RefCount = 0;
NTSTATUS res;
AtomTable = NULL;
res = pRtlCreateAtomTable(37, &AtomTable);
ok(!res, "Unable to create atom table, %lx\n", res);
if (!res)
{
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
ok(!res, "Unable to add our atom to the atom table, retval: %lx\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);
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
res = pRtlPinAtomInAtomTable(AtomTable, Atom);
ok(!res, "Unable to pin atom in atom table, retval: %lx\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);
res = pRtlDestroyAtomTable(AtomTable);
ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
}
}
START_TEST(atom)
{
InitFunctionPtr();
if (pRtlCreateAtomTable)
{
test_NtAtom();
test_NtIntAtom();
test_NtRefPinAtom();
}
}

View file

@ -0,0 +1,298 @@
/*
* Unit test suite for ntdll path functions
*
* Copyright 2003 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include "ntdll_test.h"
#include "wine/unicode.h"
static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
LPCSTR src, DWORD srclen );
static NTSTATUS (WINAPI *pRtlCreateEnvironment)(BOOLEAN, PWSTR*);
static NTSTATUS (WINAPI *pRtlDestroyEnvironment)(PWSTR);
static NTSTATUS (WINAPI *pRtlQueryEnvironmentVariable_U)(PWSTR, PUNICODE_STRING, PUNICODE_STRING);
static void (WINAPI *pRtlSetCurrentEnvironment)(PWSTR, PWSTR*);
static NTSTATUS (WINAPI *pRtlSetEnvironmentVariable)(PWSTR*, PUNICODE_STRING, PUNICODE_STRING);
static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings_U)(LPWSTR, PUNICODE_STRING, PUNICODE_STRING, PULONG);
static WCHAR small_env[] = {'f','o','o','=','t','o','t','o',0,
'f','o','=','t','i','t','i',0,
'f','o','o','o','=','t','u','t','u',0,
's','r','=','a','n','=','o','u','o',0,
'g','=','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0,
'=','o','O','H','=','I','I','I',0,
'n','u','l','=',0,
0};
static void testQuery(void)
{
struct test
{
const char *var;
int len;
NTSTATUS status;
const char *val;
};
static const struct test tests[] =
{
{"foo", 256, STATUS_SUCCESS, "toto"},
{"FoO", 256, STATUS_SUCCESS, "toto"},
{"foo=", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
{"foo ", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
{"foo", 1, STATUS_BUFFER_TOO_SMALL, "toto"},
{"foo", 3, STATUS_BUFFER_TOO_SMALL, "toto"},
{"foo", 4, STATUS_SUCCESS, "toto"},
{"fooo", 256, STATUS_SUCCESS, "tutu"},
{"f", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
{"g", 256, STATUS_SUCCESS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
{"sr=an", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
{"sr", 256, STATUS_SUCCESS, "an=ouo"},
{"=oOH", 256, STATUS_SUCCESS, "III"},
{"", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
{"nul", 256, STATUS_SUCCESS, ""},
{NULL, 0, 0, NULL}
};
WCHAR bn[257];
WCHAR bv[257];
UNICODE_STRING name;
UNICODE_STRING value;
const struct test* test;
NTSTATUS nts;
for (test = tests; test->var; test++)
{
name.Length = strlen(test->var) * 2;
name.MaximumLength = name.Length + 2;
name.Buffer = bn;
value.Length = 0;
value.MaximumLength = test->len * 2;
value.Buffer = bv;
bv[test->len] = '@';
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",
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) && strncmpW(bv, bn, test->len) == 0) ||
strcmpW(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 );
break;
}
}
}
static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATUS ret)
{
WCHAR bvar[256], bval1[256], bval2[256];
UNICODE_STRING uvar;
UNICODE_STRING uval;
NTSTATUS nts;
uvar.Length = strlen(var) * sizeof(WCHAR);
uvar.MaximumLength = uvar.Length + sizeof(WCHAR);
uvar.Buffer = bvar;
pRtlMultiByteToUnicodeN( bvar, sizeof(bvar), NULL, var, strlen(var)+1 );
if (val)
{
uval.Length = strlen(val) * sizeof(WCHAR);
uval.MaximumLength = uval.Length + sizeof(WCHAR);
uval.Buffer = bval1;
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);
if (nts == STATUS_SUCCESS)
{
uval.Length = 0;
uval.MaximumLength = sizeof(bval2);
uval.Buffer = bval2;
nts = pRtlQueryEnvironmentVariable_U(*env, &uvar, &uval);
switch (nts)
{
case STATUS_SUCCESS:
ok(strcmpW(bval1, bval2) == 0, "Cannot get value written to environment\n");
break;
case STATUS_VARIABLE_NOT_FOUND:
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);
break;
}
}
}
static void testSet(void)
{
LPWSTR env;
char tmp[16];
int i;
ok(pRtlCreateEnvironment(FALSE, &env) == STATUS_SUCCESS, "Creating environment\n");
memmove(env, small_env, sizeof(small_env));
testSetHelper(&env, "cat", "dog", STATUS_SUCCESS);
testSetHelper(&env, "cat", "horse", STATUS_SUCCESS);
testSetHelper(&env, "cat", "zz", STATUS_SUCCESS);
testSetHelper(&env, "cat", NULL, STATUS_SUCCESS);
testSetHelper(&env, "cat", NULL, STATUS_VARIABLE_NOT_FOUND);
testSetHelper(&env, "foo", "meouw", STATUS_SUCCESS);
testSetHelper(&env, "me=too", "also", STATUS_INVALID_PARAMETER);
testSetHelper(&env, "me", "too=also", STATUS_SUCCESS);
testSetHelper(&env, "=too", "also", STATUS_SUCCESS);
testSetHelper(&env, "=", "also", STATUS_SUCCESS);
for (i = 0; i < 128; i++)
{
sprintf(tmp, "zork%03d", i);
testSetHelper(&env, tmp, "is alive", STATUS_SUCCESS);
}
for (i = 0; i < 128; i++)
{
sprintf(tmp, "zork%03d", i);
testSetHelper(&env, tmp, NULL, STATUS_SUCCESS);
}
testSetHelper(&env, "fOo", NULL, STATUS_SUCCESS);
ok(pRtlDestroyEnvironment(env) == STATUS_SUCCESS, "Destroying environment\n");
}
static void testExpand(void)
{
static const struct test
{
const char *src;
const char *dst;
} tests[] =
{
{"hello%foo%world", "hellototoworld"},
{"hello%=oOH%world", "helloIIIworld"},
{"hello%foo", "hello%foo"},
{"hello%bar%world", "hello%bar%world"},
/*
* {"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 :-/
*/
{NULL, NULL}
};
const struct test* test;
NTSTATUS nts;
UNICODE_STRING us_src, us_dst;
WCHAR src[256], dst[256], rst[256];
ULONG ul;
for (test = tests; test->src; test++)
{
pRtlMultiByteToUnicodeN(src, sizeof(src), NULL, test->src, strlen(test->src)+1);
pRtlMultiByteToUnicodeN(rst, sizeof(rst), NULL, test->dst, strlen(test->dst)+1);
us_src.Length = strlen(test->src) * sizeof(WCHAR);
us_src.MaximumLength = us_src.Length + 2;
us_src.Buffer = src;
us_dst.Length = 0;
us_dst.MaximumLength = 0;
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));
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(strcmpW(dst, rst) == 0, "Wrong result for %s: expecting %s\n",
test->src, test->dst);
us_dst.Length = 0;
us_dst.MaximumLength = 8 * sizeof(WCHAR);
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(strncmpW(dst, rst, 8) == 0,
"Wrong result for %s (with buffer too small): expecting %s\n",
test->src, test->dst);
ok(dst[8] == '-', "Writing too far in buffer (got %c/%d)\n", dst[8], dst[8]);
}
}
START_TEST(env)
{
HMODULE mod = GetModuleHandleA("ntdll.dll");
pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN");
pRtlCreateEnvironment = (void*)GetProcAddress(mod, "RtlCreateEnvironment");
pRtlDestroyEnvironment = (void*)GetProcAddress(mod, "RtlDestroyEnvironment");
pRtlQueryEnvironmentVariable_U = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable_U");
pRtlSetCurrentEnvironment = (void*)GetProcAddress(mod, "RtlSetCurrentEnvironment");
pRtlSetEnvironmentVariable = (void*)GetProcAddress(mod, "RtlSetEnvironmentVariable");
pRtlExpandEnvironmentStrings_U = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings_U");
if (pRtlQueryEnvironmentVariable_U)
testQuery();
if (pRtlSetEnvironmentVariable)
testSet();
if (pRtlExpandEnvironmentStrings_U)
testExpand();
}

View file

@ -0,0 +1,950 @@
/*
* Unit tests for RtlNtStatusToDosError function
*
* Copyright (c) 2002 Andriy Palamarchuk
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define _WIN32_WINNT 0x0501
#include <stdarg.h>
#include <stdio.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/test.h"
#include "windows.h"
#include "windef.h"
#include "winbase.h"
#include "rpcnterr.h"
#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&
* 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
* cases they return somewhat strange results (Win98) or a generic error
* like ERROR_MR_MID_NOT_FOUND (NT4). Our tests have to know about these to
* not fail, but we would very much prefer Wine not to return such garbage.
* To you can pass the 'strict' option to this test to force it to only check
* results against the first listed value. This test should pass in strict
* mode on the latest Windows platform (currently XP) and in Wine.
* (of course older Windows platforms will fail to pass the strict mode)
*/
static ULONG (WINAPI *statustodoserror)(NTSTATUS Status);
static int strict;
static int prepare_test(void)
{
HMODULE ntdll;
int argc;
char** argv;
ntdll = LoadLibraryA("ntdll.dll");
statustodoserror = (void*)GetProcAddress(ntdll, "RtlNtStatusToDosError");
if (!statustodoserror)
return 0;
argc = winetest_get_mainargs(&argv);
strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
return 1;
}
static void cmp_call(NTSTATUS win_nt, ULONG win32, const char* message)
{
ULONG err;
err = statustodoserror(win_nt);
ok(err == win32,
"%s (%lx): got %ld, expected %ld\n",
message, win_nt, err, win32);
}
static void cmp_call2(NTSTATUS win_nt, ULONG win32, const char* message)
{
ULONG err;
err = statustodoserror(win_nt);
ok(err == win32 ||
(!strict && err == ERROR_MR_MID_NOT_FOUND),
"%s (%lx): got %ld, expected %ld (or MID_NOT_FOUND)\n",
message, win_nt, err, win32);
}
static void cmp_call3(NTSTATUS win_nt, ULONG win32_1, ULONG win32_2, const char* message)
{
ULONG err;
err = statustodoserror(win_nt);
ok(err == win32_1 || (!strict && err == win32_2),
"%s (%lx): got %ld, expected %ld or %ld\n",
message, win_nt, err, win32_1, win32_2);
}
static void cmp_call4(NTSTATUS win_nt, ULONG win32_1, ULONG win32_2, const char* message)
{
ULONG err;
err = statustodoserror(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",
message, win_nt, err, win32_1, win32_2);
}
#define cmp(status, error) \
cmp_call(status, error, #status)
#define cmp2(status, error) \
cmp_call2(status, error, #status)
#define cmp3(status, error1, error2) \
cmp_call3(status, error1, error2, #status)
#define cmp4(status, error1, error2) \
cmp_call4(status, error1, error2, #status)
static void run_error_tests(void)
{
cmp(STATUS_DATATYPE_MISALIGNMENT, ERROR_NOACCESS);
cmp(STATUS_ACCESS_VIOLATION, ERROR_NOACCESS);
cmp2(STATUS_DATATYPE_MISALIGNMENT_ERROR, ERROR_NOACCESS);
cmp(STATUS_CTL_FILE_NOT_SUPPORTED, ERROR_NOT_SUPPORTED);
cmp(STATUS_PORT_ALREADY_SET, ERROR_INVALID_PARAMETER);
cmp(STATUS_SECTION_NOT_IMAGE, ERROR_INVALID_PARAMETER);
cmp(STATUS_BAD_WORKING_SET_LIMIT, ERROR_INVALID_PARAMETER);
cmp(STATUS_WORKING_SET_LIMIT_RANGE, ERROR_INVALID_PARAMETER);
cmp(STATUS_INCOMPATIBLE_FILE_MAP, ERROR_INVALID_PARAMETER);
cmp(STATUS_PORT_DISCONNECTED, ERROR_INVALID_HANDLE);
cmp(STATUS_NOT_LOCKED, ERROR_NOT_LOCKED);
cmp(STATUS_NOT_MAPPED_VIEW, ERROR_INVALID_ADDRESS);
cmp(STATUS_UNABLE_TO_FREE_VM, ERROR_INVALID_PARAMETER);
cmp(STATUS_UNABLE_TO_DELETE_SECTION, ERROR_INVALID_PARAMETER);
cmp(STATUS_MORE_PROCESSING_REQUIRED, ERROR_MORE_DATA);
cmp(STATUS_INVALID_CID, ERROR_INVALID_PARAMETER);
cmp(STATUS_STACK_OVERFLOW, ERROR_STACK_OVERFLOW);
cmp(STATUS_BAD_INITIAL_STACK, ERROR_STACK_OVERFLOW);
cmp(STATUS_INVALID_VOLUME_LABEL, ERROR_LABEL_TOO_LONG);
cmp(STATUS_SECTION_NOT_EXTENDED, ERROR_OUTOFMEMORY);
cmp(STATUS_NOT_MAPPED_DATA, ERROR_INVALID_ADDRESS);
cmp2(STATUS_NO_LDT, ERROR_INVALID_THREAD_ID);
cmp(STATUS_INFO_LENGTH_MISMATCH, ERROR_BAD_LENGTH);
cmp(STATUS_INVALID_INFO_CLASS, ERROR_INVALID_PARAMETER);
cmp(STATUS_SUSPEND_COUNT_EXCEEDED, ERROR_SIGNAL_REFUSED);
cmp(STATUS_NOTIFY_ENUM_DIR, ERROR_NOTIFY_ENUM_DIR);
cmp(STATUS_REGISTRY_RECOVERED, ERROR_REGISTRY_RECOVERED);
cmp(STATUS_REGISTRY_IO_FAILED, ERROR_REGISTRY_IO_FAILED);
cmp(STATUS_NOT_REGISTRY_FILE, ERROR_NOT_REGISTRY_FILE);
cmp(STATUS_KEY_DELETED, ERROR_KEY_DELETED);
cmp(STATUS_NO_LOG_SPACE, ERROR_NO_LOG_SPACE);
cmp(STATUS_KEY_HAS_CHILDREN, ERROR_KEY_HAS_CHILDREN);
cmp(STATUS_CHILD_MUST_BE_VOLATILE, ERROR_CHILD_MUST_BE_VOLATILE);
cmp(STATUS_REGISTRY_CORRUPT, ERROR_BADDB);
cmp(STATUS_DLL_NOT_FOUND, ERROR_MOD_NOT_FOUND);
cmp(STATUS_DLL_INIT_FAILED, ERROR_DLL_INIT_FAILED);
cmp2(STATUS_INVALID_IMPORT_OF_NON_DLL, ERROR_INVALID_IMPORT_OF_NON_DLL);
cmp(STATUS_ORDINAL_NOT_FOUND, ERROR_INVALID_ORDINAL);
cmp(STATUS_DRIVER_ORDINAL_NOT_FOUND, ERROR_INVALID_ORDINAL);
cmp2(STATUS_DRIVER_UNABLE_TO_LOAD, ERROR_BAD_DRIVER);
cmp(STATUS_ENTRYPOINT_NOT_FOUND, ERROR_PROC_NOT_FOUND);
cmp(STATUS_DRIVER_ENTRYPOINT_NOT_FOUND, ERROR_PROC_NOT_FOUND);
cmp(STATUS_PENDING, ERROR_IO_PENDING);
cmp(STATUS_MORE_ENTRIES, ERROR_MORE_DATA);
cmp(STATUS_INTEGER_OVERFLOW, ERROR_ARITHMETIC_OVERFLOW);
cmp(STATUS_BUFFER_OVERFLOW, ERROR_MORE_DATA);
cmp(STATUS_NO_MORE_FILES, ERROR_NO_MORE_FILES);
cmp(STATUS_NO_INHERITANCE, ERROR_NO_INHERITANCE);
cmp(STATUS_NO_MORE_EAS, ERROR_NO_MORE_ITEMS);
cmp(STATUS_NO_MORE_ENTRIES, ERROR_NO_MORE_ITEMS);
cmp(STATUS_GUIDS_EXHAUSTED, ERROR_NO_MORE_ITEMS);
cmp(STATUS_AGENTS_EXHAUSTED, ERROR_NO_MORE_ITEMS);
cmp(STATUS_UNSUCCESSFUL, ERROR_GEN_FAILURE);
cmp(STATUS_TOO_MANY_LINKS, ERROR_TOO_MANY_LINKS);
cmp(STATUS_NOT_IMPLEMENTED, ERROR_INVALID_FUNCTION);
cmp(STATUS_ILLEGAL_FUNCTION, ERROR_INVALID_FUNCTION);
cmp(STATUS_IN_PAGE_ERROR, ERROR_SWAPERROR);
cmp(STATUS_PAGEFILE_QUOTA, ERROR_PAGEFILE_QUOTA);
cmp(STATUS_COMMITMENT_LIMIT, ERROR_COMMITMENT_LIMIT);
cmp(STATUS_SECTION_TOO_BIG, ERROR_NOT_ENOUGH_MEMORY);
cmp(RPC_NT_SS_IN_NULL_CONTEXT, ERROR_INVALID_HANDLE);
cmp(RPC_NT_INVALID_BINDING, ERROR_INVALID_HANDLE);
cmp(STATUS_INVALID_HANDLE, ERROR_INVALID_HANDLE);
cmp(STATUS_OBJECT_TYPE_MISMATCH, ERROR_INVALID_HANDLE);
cmp(STATUS_FILE_CLOSED, ERROR_INVALID_HANDLE);
cmp(STATUS_INVALID_PORT_HANDLE, ERROR_INVALID_HANDLE);
cmp(STATUS_HANDLE_NOT_CLOSABLE, ERROR_INVALID_HANDLE);
cmp(STATUS_NOT_COMMITTED, ERROR_INVALID_ADDRESS);
cmp(STATUS_PARTIAL_COPY, ERROR_PARTIAL_COPY);
cmp(STATUS_LPC_REPLY_LOST, ERROR_INTERNAL_ERROR);
cmp(STATUS_INVALID_PARAMETER, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_1, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_2, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_3, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_4, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_5, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_6, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_7, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_8, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_9, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_10, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_11, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_12, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PARAMETER_MIX, ERROR_INVALID_PARAMETER);
cmp(STATUS_INVALID_PAGE_PROTECTION, ERROR_INVALID_PARAMETER);
cmp(STATUS_SECTION_PROTECTION, ERROR_INVALID_PARAMETER);
cmp(STATUS_RESOURCE_DATA_NOT_FOUND, ERROR_RESOURCE_DATA_NOT_FOUND);
cmp(STATUS_RESOURCE_TYPE_NOT_FOUND, ERROR_RESOURCE_TYPE_NOT_FOUND);
cmp(STATUS_RESOURCE_NAME_NOT_FOUND, ERROR_RESOURCE_NAME_NOT_FOUND);
cmp(STATUS_RESOURCE_LANG_NOT_FOUND, ERROR_RESOURCE_LANG_NOT_FOUND);
cmp(STATUS_NO_SUCH_DEVICE, ERROR_FILE_NOT_FOUND);
cmp(STATUS_NO_SUCH_FILE, ERROR_FILE_NOT_FOUND);
cmp(STATUS_INVALID_DEVICE_REQUEST, ERROR_INVALID_FUNCTION);
cmp2(STATUS_VOLUME_NOT_UPGRADED, ERROR_INVALID_FUNCTION);
cmp(STATUS_END_OF_FILE, ERROR_HANDLE_EOF);
cmp(STATUS_FILE_FORCED_CLOSED, ERROR_HANDLE_EOF);
cmp(STATUS_WRONG_VOLUME, ERROR_WRONG_DISK);
cmp(STATUS_NO_MEDIA, ERROR_NO_MEDIA_IN_DRIVE);
cmp(STATUS_NO_MEDIA_IN_DEVICE, ERROR_NOT_READY);
cmp(STATUS_VOLUME_DISMOUNTED, ERROR_NOT_READY);
cmp(STATUS_NONEXISTENT_SECTOR, ERROR_SECTOR_NOT_FOUND);
cmp(STATUS_WORKING_SET_QUOTA, ERROR_WORKING_SET_QUOTA);
cmp(STATUS_NO_MEMORY, ERROR_NOT_ENOUGH_MEMORY);
cmp(STATUS_CONFLICTING_ADDRESSES, ERROR_INVALID_ADDRESS);
cmp(STATUS_INVALID_SYSTEM_SERVICE, ERROR_INVALID_FUNCTION);
cmp(STATUS_THREAD_IS_TERMINATING, ERROR_ACCESS_DENIED);
cmp(STATUS_PROCESS_IS_TERMINATING, ERROR_ACCESS_DENIED);
cmp(STATUS_INVALID_LOCK_SEQUENCE, ERROR_ACCESS_DENIED);
cmp(STATUS_INVALID_VIEW_SIZE, ERROR_ACCESS_DENIED);
cmp(STATUS_ALREADY_COMMITTED, ERROR_ACCESS_DENIED);
cmp(STATUS_ACCESS_DENIED, ERROR_ACCESS_DENIED);
cmp(STATUS_FILE_IS_A_DIRECTORY, ERROR_ACCESS_DENIED);
cmp(STATUS_CANNOT_DELETE, ERROR_ACCESS_DENIED);
cmp(STATUS_INVALID_COMPUTER_NAME, ERROR_INVALID_COMPUTERNAME);
cmp(STATUS_FILE_DELETED, ERROR_ACCESS_DENIED);
cmp2(STATUS_FILE_RENAMED, ERROR_ACCESS_DENIED);
cmp(STATUS_DELETE_PENDING, ERROR_ACCESS_DENIED);
cmp(STATUS_PORT_CONNECTION_REFUSED, ERROR_ACCESS_DENIED);
cmp(STATUS_NO_SUCH_PRIVILEGE, ERROR_NO_SUCH_PRIVILEGE);
cmp(STATUS_PRIVILEGE_NOT_HELD, ERROR_PRIVILEGE_NOT_HELD);
cmp(STATUS_CANNOT_IMPERSONATE, ERROR_CANNOT_IMPERSONATE);
cmp(STATUS_LOGON_FAILURE, ERROR_LOGON_FAILURE);
cmp2(STATUS_MUTUAL_AUTHENTICATION_FAILED, ERROR_MUTUAL_AUTH_FAILED);
cmp2(STATUS_TIME_DIFFERENCE_AT_DC, ERROR_TIME_SKEW);
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);
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);
cmp2(STATUS_SMARTCARD_CARD_BLOCKED, SCARD_W_CHV_BLOCKED);
cmp2(STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED,SCARD_W_CARD_NOT_AUTHENTICATED);
cmp2(STATUS_SMARTCARD_NO_CARD, SCARD_E_NO_SMARTCARD);
cmp2(STATUS_SMARTCARD_NO_KEY_CONTAINER, NTE_NO_KEY);
cmp2(STATUS_SMARTCARD_NO_CERTIFICATE, SCARD_E_NO_SUCH_CERTIFICATE);
cmp2(STATUS_SMARTCARD_NO_KEYSET, NTE_BAD_KEYSET);
cmp2(STATUS_SMARTCARD_IO_ERROR, SCARD_E_COMM_DATA_LOST);
cmp(STATUS_ACCOUNT_RESTRICTION, ERROR_ACCOUNT_RESTRICTION);
cmp(STATUS_INVALID_LOGON_HOURS, ERROR_INVALID_LOGON_HOURS);
cmp(STATUS_INVALID_WORKSTATION, ERROR_INVALID_WORKSTATION);
cmp(STATUS_BUFFER_TOO_SMALL, ERROR_INSUFFICIENT_BUFFER);
cmp(STATUS_UNABLE_TO_DECOMMIT_VM, ERROR_INVALID_ADDRESS);
cmp(STATUS_DISK_CORRUPT_ERROR, ERROR_DISK_CORRUPT);
cmp(STATUS_FT_MISSING_MEMBER, ERROR_IO_DEVICE);
cmp(STATUS_FT_ORPHANING, ERROR_IO_DEVICE);
cmp(STATUS_VARIABLE_NOT_FOUND, ERROR_ENVVAR_NOT_FOUND);
cmp(STATUS_OBJECT_NAME_INVALID, ERROR_INVALID_NAME);
cmp(STATUS_OBJECT_NAME_NOT_FOUND, ERROR_FILE_NOT_FOUND);
cmp(STATUS_OBJECT_NAME_COLLISION, ERROR_ALREADY_EXISTS);
cmp(STATUS_OBJECT_PATH_INVALID, ERROR_BAD_PATHNAME);
cmp(STATUS_OBJECT_PATH_NOT_FOUND, ERROR_PATH_NOT_FOUND);
cmp(STATUS_DFS_EXIT_PATH_FOUND, ERROR_PATH_NOT_FOUND);
cmp2(STATUS_DFS_UNAVAILABLE, ERROR_CONNECTION_UNAVAIL);
cmp(STATUS_OBJECT_PATH_SYNTAX_BAD, ERROR_BAD_PATHNAME);
cmp(STATUS_NAME_TOO_LONG, ERROR_FILENAME_EXCED_RANGE);
cmp(STATUS_DATA_OVERRUN, ERROR_IO_DEVICE);
cmp(STATUS_DATA_LATE_ERROR, ERROR_IO_DEVICE);
cmp(STATUS_DATA_ERROR, ERROR_CRC);
cmp(STATUS_CRC_ERROR, ERROR_CRC);
cmp(STATUS_SHARING_VIOLATION, ERROR_SHARING_VIOLATION);
cmp(STATUS_QUOTA_EXCEEDED, ERROR_NOT_ENOUGH_QUOTA);
cmp(STATUS_MUTANT_NOT_OWNED, ERROR_NOT_OWNER);
cmp(STATUS_SEMAPHORE_LIMIT_EXCEEDED, ERROR_TOO_MANY_POSTS);
cmp(STATUS_DISK_FULL, ERROR_DISK_FULL);
cmp(STATUS_LOCK_NOT_GRANTED, ERROR_LOCK_VIOLATION);
cmp(STATUS_FILE_LOCK_CONFLICT, ERROR_LOCK_VIOLATION);
cmp(STATUS_NOT_A_DIRECTORY, ERROR_DIRECTORY);
cmp2(STATUS_CANNOT_MAKE, ERROR_CANNOT_MAKE);
cmp(STATUS_UNKNOWN_REVISION, ERROR_UNKNOWN_REVISION);
cmp(STATUS_REVISION_MISMATCH, ERROR_REVISION_MISMATCH);
cmp(STATUS_INVALID_OWNER, ERROR_INVALID_OWNER);
cmp(STATUS_INVALID_PRIMARY_GROUP, ERROR_INVALID_PRIMARY_GROUP);
cmp(STATUS_NO_IMPERSONATION_TOKEN, ERROR_NO_IMPERSONATION_TOKEN);
cmp(STATUS_CANT_DISABLE_MANDATORY, ERROR_CANT_DISABLE_MANDATORY);
cmp(STATUS_NO_LOGON_SERVERS, ERROR_NO_LOGON_SERVERS);
cmp(STATUS_DOMAIN_CONTROLLER_NOT_FOUND, ERROR_DOMAIN_CONTROLLER_NOT_FOUND);
cmp(STATUS_NO_SUCH_LOGON_SESSION, ERROR_NO_SUCH_LOGON_SESSION);
cmp(STATUS_INVALID_ACCOUNT_NAME, ERROR_INVALID_ACCOUNT_NAME);
cmp(STATUS_USER_EXISTS, ERROR_USER_EXISTS);
cmp(STATUS_NO_SUCH_USER, ERROR_NO_SUCH_USER);
cmp(STATUS_GROUP_EXISTS, ERROR_GROUP_EXISTS);
cmp(STATUS_NO_SUCH_GROUP, ERROR_NO_SUCH_GROUP);
cmp(STATUS_SPECIAL_GROUP, ERROR_SPECIAL_GROUP);
cmp(STATUS_MEMBER_IN_GROUP, ERROR_MEMBER_IN_GROUP);
cmp(STATUS_MEMBER_NOT_IN_GROUP, ERROR_MEMBER_NOT_IN_GROUP);
cmp(STATUS_LAST_ADMIN, ERROR_LAST_ADMIN);
cmp(STATUS_WRONG_PASSWORD, ERROR_INVALID_PASSWORD);
cmp(STATUS_WRONG_PASSWORD_CORE, ERROR_INVALID_PASSWORD);
cmp(STATUS_ILL_FORMED_PASSWORD, ERROR_ILL_FORMED_PASSWORD);
cmp(STATUS_PASSWORD_RESTRICTION, ERROR_PASSWORD_RESTRICTION);
cmp(STATUS_PASSWORD_EXPIRED, ERROR_PASSWORD_EXPIRED);
cmp(STATUS_PASSWORD_MUST_CHANGE, ERROR_PASSWORD_MUST_CHANGE);
cmp(STATUS_ACCOUNT_DISABLED, ERROR_ACCOUNT_DISABLED);
cmp(STATUS_ACCOUNT_LOCKED_OUT, ERROR_ACCOUNT_LOCKED_OUT);
cmp(STATUS_NONE_MAPPED, ERROR_NONE_MAPPED);
cmp(STATUS_TOO_MANY_LUIDS_REQUESTED, ERROR_TOO_MANY_LUIDS_REQUESTED);
cmp(STATUS_LUIDS_EXHAUSTED, ERROR_LUIDS_EXHAUSTED);
cmp(STATUS_INVALID_SUB_AUTHORITY, ERROR_INVALID_SUB_AUTHORITY);
cmp(STATUS_INVALID_ACL, ERROR_INVALID_ACL);
cmp(STATUS_INVALID_SID, ERROR_INVALID_SID);
cmp(STATUS_INVALID_SECURITY_DESCR, ERROR_INVALID_SECURITY_DESCR);
cmp(STATUS_PROCEDURE_NOT_FOUND, ERROR_PROC_NOT_FOUND);
cmp(STATUS_BAD_INITIAL_PC, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_INVALID_FILE_FOR_SECTION, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_INVALID_IMAGE_FORMAT, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_IMAGE_MP_UP_MISMATCH, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_INVALID_IMAGE_NOT_MZ, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_IMAGE_CHECKSUM_MISMATCH, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_INVALID_IMAGE_PROTECT, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_INVALID_IMAGE_LE_FORMAT, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_INVALID_IMAGE_NE_FORMAT, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_INVALID_IMAGE_WIN_16, ERROR_BAD_EXE_FORMAT);
cmp2(STATUS_INVALID_IMAGE_WIN_32, ERROR_BAD_EXE_FORMAT);
cmp2(STATUS_INVALID_IMAGE_WIN_64, ERROR_BAD_EXE_FORMAT);
cmp(STATUS_NO_TOKEN, ERROR_NO_TOKEN);
cmp(STATUS_RANGE_NOT_LOCKED, ERROR_NOT_LOCKED);
cmp(STATUS_SERVER_DISABLED, ERROR_SERVER_DISABLED);
cmp(STATUS_SERVER_NOT_DISABLED, ERROR_SERVER_NOT_DISABLED);
cmp(STATUS_INVALID_ID_AUTHORITY, ERROR_INVALID_ID_AUTHORITY);
cmp(STATUS_ALLOTTED_SPACE_EXCEEDED, ERROR_ALLOTTED_SPACE_EXCEEDED);
cmp(STATUS_TOO_MANY_PAGING_FILES, ERROR_NOT_ENOUGH_MEMORY);
cmp(STATUS_INSUFFICIENT_RESOURCES, ERROR_NO_SYSTEM_RESOURCES);
cmp(STATUS_INSUFF_SERVER_RESOURCES, ERROR_NOT_ENOUGH_SERVER_MEMORY);
cmp(STATUS_FILE_INVALID, ERROR_FILE_INVALID);
cmp(STATUS_MAPPED_FILE_SIZE_ZERO, ERROR_FILE_INVALID);
cmp(STATUS_DEVICE_PAPER_EMPTY, ERROR_OUT_OF_PAPER);
cmp(STATUS_DEVICE_POWERED_OFF, ERROR_NOT_READY);
cmp(STATUS_DEVICE_OFF_LINE, ERROR_NOT_READY);
cmp(STATUS_DEVICE_DATA_ERROR, ERROR_CRC);
cmp(STATUS_DEVICE_NOT_READY, ERROR_NOT_READY);
cmp3(STATUS_DEVICE_NOT_CONNECTED, ERROR_DEVICE_NOT_CONNECTED, ERROR_NOT_READY);
cmp(STATUS_DEVICE_POWER_FAILURE, ERROR_NOT_READY);
cmp2(STATUS_NOT_FOUND, ERROR_NOT_FOUND);
cmp2(STATUS_NO_MATCH, ERROR_NO_MATCH);
cmp2(STATUS_PROPSET_NOT_FOUND, ERROR_SET_NOT_FOUND);
cmp(STATUS_DEVICE_BUSY, ERROR_BUSY);
cmp(STATUS_FREE_VM_NOT_AT_BASE, ERROR_INVALID_ADDRESS);
cmp(STATUS_MEMORY_NOT_ALLOCATED, ERROR_INVALID_ADDRESS);
cmp(STATUS_NOT_SAME_DEVICE, ERROR_NOT_SAME_DEVICE);
cmp(STATUS_NOT_SUPPORTED, ERROR_NOT_SUPPORTED);
cmp(STATUS_REMOTE_NOT_LISTENING, ERROR_REM_NOT_LIST);
cmp(STATUS_DUPLICATE_NAME, ERROR_DUP_NAME);
cmp(STATUS_BAD_NETWORK_PATH, ERROR_BAD_NETPATH);
cmp(STATUS_NETWORK_BUSY, ERROR_NETWORK_BUSY);
cmp2(STATUS_ONLY_IF_CONNECTED, ERROR_ONLY_IF_CONNECTED);
cmp(STATUS_DEVICE_DOES_NOT_EXIST, ERROR_DEV_NOT_EXIST);
cmp(STATUS_TOO_MANY_COMMANDS, ERROR_TOO_MANY_CMDS);
cmp(STATUS_ADAPTER_HARDWARE_ERROR, ERROR_ADAP_HDW_ERR);
cmp(STATUS_REDIRECTOR_NOT_STARTED, ERROR_PATH_NOT_FOUND);
cmp(STATUS_INVALID_EA_NAME, ERROR_INVALID_EA_NAME);
cmp(STATUS_EA_LIST_INCONSISTENT, ERROR_EA_LIST_INCONSISTENT);
cmp(STATUS_EA_TOO_LARGE, ERROR_EA_LIST_INCONSISTENT);
cmp(STATUS_INVALID_EA_FLAG, ERROR_EA_LIST_INCONSISTENT);
cmp2(STATUS_EAS_NOT_SUPPORTED, ERROR_EAS_NOT_SUPPORTED);
cmp(STATUS_FILE_CORRUPT_ERROR, ERROR_FILE_CORRUPT);
cmp(STATUS_EA_CORRUPT_ERROR, ERROR_FILE_CORRUPT);
cmp(STATUS_NONEXISTENT_EA_ENTRY, ERROR_FILE_CORRUPT);
cmp(STATUS_NO_EAS_ON_FILE, ERROR_FILE_CORRUPT);
cmp2(STATUS_NOT_A_REPARSE_POINT, ERROR_NOT_A_REPARSE_POINT);
cmp4(STATUS_IO_REPARSE_TAG_INVALID, ERROR_REPARSE_TAG_INVALID, ERROR_INVALID_PARAMETER);
cmp4(STATUS_IO_REPARSE_TAG_MISMATCH, ERROR_REPARSE_TAG_MISMATCH, ERROR_INVALID_PARAMETER);
cmp2(STATUS_IO_REPARSE_TAG_NOT_HANDLED, ERROR_CANT_ACCESS_FILE);
cmp2(STATUS_REPARSE_POINT_NOT_RESOLVED, ERROR_CANT_RESOLVE_FILENAME);
cmp2(STATUS_DIRECTORY_IS_A_REPARSE_POINT, ERROR_BAD_PATHNAME);
cmp2(STATUS_REPARSE_ATTRIBUTE_CONFLICT, ERROR_REPARSE_ATTRIBUTE_CONFLICT);
cmp4(STATUS_IO_REPARSE_DATA_INVALID, ERROR_INVALID_REPARSE_DATA, ERROR_INVALID_PARAMETER);
cmp2(STATUS_FILE_IS_OFFLINE, ERROR_FILE_OFFLINE);
cmp2(STATUS_REMOTE_STORAGE_NOT_ACTIVE, ERROR_REMOTE_STORAGE_NOT_ACTIVE);
cmp2(STATUS_REMOTE_STORAGE_MEDIA_ERROR, ERROR_REMOTE_STORAGE_MEDIA_ERROR);
cmp2(STATUS_NO_TRACKING_SERVICE, ERROR_NO_TRACKING_SERVICE);
cmp2(STATUS_JOURNAL_DELETE_IN_PROGRESS, ERROR_JOURNAL_DELETE_IN_PROGRESS);
cmp2(STATUS_JOURNAL_NOT_ACTIVE, ERROR_JOURNAL_NOT_ACTIVE);
cmp2(STATUS_JOURNAL_ENTRY_DELETED, ERROR_JOURNAL_ENTRY_DELETED);
cmp(STATUS_INVALID_NETWORK_RESPONSE, ERROR_BAD_NET_RESP);
cmp(STATUS_USER_SESSION_DELETED, ERROR_UNEXP_NET_ERR);
cmp(STATUS_UNEXPECTED_NETWORK_ERROR, ERROR_UNEXP_NET_ERR);
cmp(STATUS_BAD_REMOTE_ADAPTER, ERROR_BAD_REM_ADAP);
cmp(STATUS_PRINT_QUEUE_FULL, ERROR_PRINTQ_FULL);
cmp(STATUS_NO_SPOOL_SPACE, ERROR_NO_SPOOL_SPACE);
cmp(STATUS_PRINT_CANCELLED, ERROR_PRINT_CANCELLED);
cmp(STATUS_NETWORK_NAME_DELETED, ERROR_NETNAME_DELETED);
cmp(STATUS_NETWORK_ACCESS_DENIED, ERROR_NETWORK_ACCESS_DENIED);
cmp(STATUS_BAD_DEVICE_TYPE, ERROR_BAD_DEV_TYPE);
cmp(STATUS_BAD_NETWORK_NAME, ERROR_BAD_NET_NAME);
cmp(STATUS_TOO_MANY_NAMES, ERROR_TOO_MANY_NAMES);
cmp(STATUS_TOO_MANY_GUIDS_REQUESTED, ERROR_TOO_MANY_NAMES);
cmp(STATUS_TOO_MANY_ADDRESSES, ERROR_TOO_MANY_NAMES);
cmp(STATUS_TOO_MANY_NODES, ERROR_TOO_MANY_NAMES);
cmp(STATUS_TOO_MANY_SESSIONS, ERROR_TOO_MANY_SESS);
cmp(STATUS_SHARING_PAUSED, ERROR_SHARING_PAUSED);
cmp(STATUS_REQUEST_NOT_ACCEPTED, ERROR_REQ_NOT_ACCEP);
cmp(STATUS_REDIRECTOR_PAUSED, ERROR_REDIR_PAUSED);
cmp(STATUS_NET_WRITE_FAULT, ERROR_NET_WRITE_FAULT);
cmp(STATUS_VIRTUAL_CIRCUIT_CLOSED, ERROR_VC_DISCONNECTED);
cmp(STATUS_INVALID_PIPE_STATE, ERROR_BAD_PIPE);
cmp(STATUS_INVALID_READ_MODE, ERROR_BAD_PIPE);
cmp(STATUS_PIPE_CLOSING, ERROR_NO_DATA);
cmp(STATUS_PIPE_EMPTY, ERROR_NO_DATA);
cmp(STATUS_PIPE_CONNECTED, ERROR_PIPE_CONNECTED);
cmp(STATUS_PIPE_DISCONNECTED, ERROR_PIPE_NOT_CONNECTED);
cmp(STATUS_PIPE_LISTENING, ERROR_PIPE_LISTENING);
cmp(STATUS_PIPE_NOT_AVAILABLE, ERROR_PIPE_BUSY);
cmp(STATUS_INSTANCE_NOT_AVAILABLE, ERROR_PIPE_BUSY);
cmp(STATUS_PIPE_BUSY, ERROR_PIPE_BUSY);
cmp(STATUS_PIPE_BROKEN, ERROR_BROKEN_PIPE);
cmp(STATUS_DIRECTORY_NOT_EMPTY, ERROR_DIR_NOT_EMPTY);
cmp(STATUS_TOO_MANY_OPENED_FILES, ERROR_TOO_MANY_OPEN_FILES);
cmp(STATUS_IO_TIMEOUT, ERROR_SEM_TIMEOUT);
cmp(STATUS_CANCELLED, ERROR_OPERATION_ABORTED);
cmp(STATUS_UNRECOGNIZED_MEDIA, ERROR_UNRECOGNIZED_MEDIA);
cmp(STATUS_INVALID_LEVEL, ERROR_INVALID_LEVEL);
cmp(STATUS_UNRECOGNIZED_VOLUME, ERROR_UNRECOGNIZED_VOLUME);
cmp(STATUS_MEDIA_WRITE_PROTECTED, ERROR_WRITE_PROTECT);
cmp(STATUS_TOO_LATE, ERROR_WRITE_PROTECT);
cmp(STATUS_SUCCESS, NO_ERROR);
cmp(STATUS_FULLSCREEN_MODE, ERROR_FULLSCREEN_MODE);
cmp(STATUS_END_OF_MEDIA, ERROR_END_OF_MEDIA);
cmp(STATUS_EOM_OVERFLOW, ERROR_EOM_OVERFLOW);
cmp(STATUS_BEGINNING_OF_MEDIA, ERROR_BEGINNING_OF_MEDIA);
cmp(STATUS_MEDIA_CHANGED, ERROR_MEDIA_CHANGED);
cmp(STATUS_BUS_RESET, ERROR_BUS_RESET);
cmp(STATUS_FILEMARK_DETECTED, ERROR_FILEMARK_DETECTED);
cmp(STATUS_SETMARK_DETECTED, ERROR_SETMARK_DETECTED);
cmp(STATUS_NO_DATA_DETECTED, ERROR_NO_DATA_DETECTED);
cmp(STATUS_PARTITION_FAILURE, ERROR_PARTITION_FAILURE);
cmp(STATUS_INVALID_BLOCK_LENGTH, ERROR_INVALID_BLOCK_LENGTH);
cmp(STATUS_DEVICE_NOT_PARTITIONED, ERROR_DEVICE_NOT_PARTITIONED);
cmp(STATUS_UNABLE_TO_LOCK_MEDIA, ERROR_UNABLE_TO_LOCK_MEDIA);
cmp(STATUS_UNABLE_TO_UNLOAD_MEDIA, ERROR_UNABLE_TO_UNLOAD_MEDIA);
cmp(STATUS_UNMAPPABLE_CHARACTER, ERROR_NO_UNICODE_TRANSLATION);
cmp(STATUS_NOT_ALL_ASSIGNED, ERROR_NOT_ALL_ASSIGNED);
cmp(STATUS_SOME_NOT_MAPPED, ERROR_SOME_NOT_MAPPED);
cmp(STATUS_NO_QUOTAS_FOR_ACCOUNT, ERROR_NO_QUOTAS_FOR_ACCOUNT);
cmp(STATUS_LOCAL_USER_SESSION_KEY, ERROR_LOCAL_USER_SESSION_KEY);
cmp(STATUS_NULL_LM_PASSWORD, ERROR_NULL_LM_PASSWORD);
cmp(STATUS_BAD_INHERITANCE_ACL, ERROR_BAD_INHERITANCE_ACL);
cmp(STATUS_INVALID_GROUP_ATTRIBUTES, ERROR_INVALID_GROUP_ATTRIBUTES);
cmp(STATUS_BAD_IMPERSONATION_LEVEL, ERROR_BAD_IMPERSONATION_LEVEL);
cmp(STATUS_CANT_OPEN_ANONYMOUS, ERROR_CANT_OPEN_ANONYMOUS);
cmp(STATUS_BAD_VALIDATION_CLASS, ERROR_BAD_VALIDATION_CLASS);
cmp(STATUS_BAD_TOKEN_TYPE, ERROR_BAD_TOKEN_TYPE);
cmp2(STATUS_BAD_MASTER_BOOT_RECORD, ERROR_INVALID_PARAMETER);
cmp(STATUS_NO_SECURITY_ON_OBJECT, ERROR_NO_SECURITY_ON_OBJECT);
cmp(STATUS_CANT_ACCESS_DOMAIN_INFO, ERROR_CANT_ACCESS_DOMAIN_INFO);
cmp(STATUS_INVALID_SERVER_STATE, ERROR_INVALID_SERVER_STATE);
cmp(STATUS_INVALID_DOMAIN_STATE, ERROR_INVALID_DOMAIN_STATE);
cmp(STATUS_INVALID_DOMAIN_ROLE, ERROR_INVALID_DOMAIN_ROLE);
cmp(STATUS_NO_SUCH_DOMAIN, ERROR_NO_SUCH_DOMAIN);
cmp(STATUS_DOMAIN_EXISTS, ERROR_DOMAIN_EXISTS);
cmp(STATUS_DOMAIN_LIMIT_EXCEEDED, ERROR_DOMAIN_LIMIT_EXCEEDED);
cmp2(STATUS_OPLOCK_NOT_GRANTED, ERROR_OPLOCK_NOT_GRANTED);
cmp2(STATUS_INVALID_OPLOCK_PROTOCOL, ERROR_INVALID_OPLOCK_PROTOCOL);
cmp(STATUS_INTERNAL_DB_CORRUPTION, ERROR_INTERNAL_DB_CORRUPTION);
cmp(STATUS_INTERNAL_ERROR, ERROR_INTERNAL_ERROR);
cmp(STATUS_GENERIC_NOT_MAPPED, ERROR_GENERIC_NOT_MAPPED);
cmp(STATUS_BAD_DESCRIPTOR_FORMAT, ERROR_BAD_DESCRIPTOR_FORMAT);
cmp(STATUS_NOT_LOGON_PROCESS, ERROR_NOT_LOGON_PROCESS);
cmp(STATUS_LOGON_SESSION_EXISTS, ERROR_LOGON_SESSION_EXISTS);
cmp(STATUS_NO_SUCH_PACKAGE, ERROR_NO_SUCH_PACKAGE);
cmp(STATUS_BAD_LOGON_SESSION_STATE, ERROR_BAD_LOGON_SESSION_STATE);
cmp(STATUS_LOGON_SESSION_COLLISION, ERROR_LOGON_SESSION_COLLISION);
cmp(STATUS_INVALID_LOGON_TYPE, ERROR_INVALID_LOGON_TYPE);
cmp(STATUS_RXACT_INVALID_STATE, ERROR_RXACT_INVALID_STATE);
cmp(STATUS_RXACT_COMMIT_FAILURE, ERROR_RXACT_COMMIT_FAILURE);
cmp(STATUS_SPECIAL_ACCOUNT, ERROR_SPECIAL_ACCOUNT);
cmp(STATUS_SPECIAL_USER, ERROR_SPECIAL_USER);
cmp(STATUS_MEMBERS_PRIMARY_GROUP, ERROR_MEMBERS_PRIMARY_GROUP);
cmp(STATUS_TOKEN_ALREADY_IN_USE, ERROR_TOKEN_ALREADY_IN_USE);
cmp(STATUS_NO_SUCH_ALIAS, ERROR_NO_SUCH_ALIAS);
cmp(STATUS_MEMBER_NOT_IN_ALIAS, ERROR_MEMBER_NOT_IN_ALIAS);
cmp(STATUS_MEMBER_IN_ALIAS, ERROR_MEMBER_IN_ALIAS);
cmp(STATUS_ALIAS_EXISTS, ERROR_ALIAS_EXISTS);
cmp(STATUS_LOGON_NOT_GRANTED, ERROR_LOGON_NOT_GRANTED);
cmp(STATUS_TOO_MANY_SECRETS, ERROR_TOO_MANY_SECRETS);
cmp(STATUS_SECRET_TOO_LONG, ERROR_SECRET_TOO_LONG);
cmp(STATUS_INTERNAL_DB_ERROR, ERROR_INTERNAL_DB_ERROR);
cmp(STATUS_TOO_MANY_CONTEXT_IDS, ERROR_TOO_MANY_CONTEXT_IDS);
cmp(STATUS_LOGON_TYPE_NOT_GRANTED, ERROR_LOGON_TYPE_NOT_GRANTED);
cmp(STATUS_NT_CROSS_ENCRYPTION_REQUIRED, ERROR_NT_CROSS_ENCRYPTION_REQUIRED);
cmp(STATUS_NO_SUCH_MEMBER, ERROR_NO_SUCH_MEMBER);
cmp(STATUS_INVALID_MEMBER, ERROR_INVALID_MEMBER);
cmp(STATUS_TOO_MANY_SIDS, ERROR_TOO_MANY_SIDS);
cmp(STATUS_LM_CROSS_ENCRYPTION_REQUIRED, ERROR_LM_CROSS_ENCRYPTION_REQUIRED);
cmp(STATUS_MESSAGE_NOT_FOUND, ERROR_MR_MID_NOT_FOUND);
cmp(STATUS_LOCAL_DISCONNECT, ERROR_NETNAME_DELETED);
cmp(STATUS_REMOTE_DISCONNECT, ERROR_NETNAME_DELETED);
cmp(STATUS_REMOTE_RESOURCES, ERROR_REM_NOT_LIST);
cmp(STATUS_LINK_FAILED, ERROR_UNEXP_NET_ERR);
cmp(STATUS_LINK_TIMEOUT, ERROR_UNEXP_NET_ERR);
cmp(STATUS_INVALID_CONNECTION, ERROR_UNEXP_NET_ERR);
cmp(STATUS_INVALID_ADDRESS, ERROR_UNEXP_NET_ERR);
cmp(STATUS_IO_DEVICE_ERROR, ERROR_IO_DEVICE);
cmp(STATUS_DEVICE_PROTOCOL_ERROR, ERROR_IO_DEVICE);
cmp(STATUS_DRIVER_INTERNAL_ERROR, ERROR_IO_DEVICE);
cmp(STATUS_INVALID_DEVICE_STATE, ERROR_BAD_COMMAND);
cmp(STATUS_DEVICE_CONFIGURATION_ERROR, ERROR_INVALID_PARAMETER);
cmp2(STATUS_SOURCE_ELEMENT_EMPTY, ERROR_SOURCE_ELEMENT_EMPTY);
cmp2(STATUS_DESTINATION_ELEMENT_FULL, ERROR_DESTINATION_ELEMENT_FULL);
cmp2(STATUS_ILLEGAL_ELEMENT_ADDRESS, ERROR_ILLEGAL_ELEMENT_ADDRESS);
cmp2(STATUS_MAGAZINE_NOT_PRESENT, ERROR_MAGAZINE_NOT_PRESENT);
cmp2(STATUS_REINITIALIZATION_NEEDED, ERROR_DEVICE_REINITIALIZATION_NEEDED);
cmp2(STATUS_DEVICE_REQUIRES_CLEANING, ERROR_DEVICE_REQUIRES_CLEANING);
cmp2(STATUS_DEVICE_DOOR_OPEN, ERROR_DEVICE_DOOR_OPEN);
cmp2(STATUS_TRANSPORT_FULL, ERROR_TRANSPORT_FULL);
cmp2(STATUS_CLEANER_CARTRIDGE_INSTALLED, ERROR_CLEANER_CARTRIDGE_INSTALLED);
cmp2(STATUS_REG_NAT_CONSUMPTION, ERROR_REG_NAT_CONSUMPTION);
cmp4(STATUS_ENCRYPTION_FAILED, ERROR_ACCESS_DENIED, ERROR_ENCRYPTION_FAILED);
cmp4(STATUS_DECRYPTION_FAILED, ERROR_ACCESS_DENIED, ERROR_DECRYPTION_FAILED);
cmp4(STATUS_NO_RECOVERY_POLICY, ERROR_ACCESS_DENIED, ERROR_NO_RECOVERY_POLICY);
cmp4(STATUS_NO_EFS, ERROR_ACCESS_DENIED, ERROR_NO_EFS);
cmp4(STATUS_WRONG_EFS, ERROR_ACCESS_DENIED, ERROR_WRONG_EFS);
cmp4(STATUS_NO_USER_KEYS, ERROR_ACCESS_DENIED, ERROR_NO_USER_KEYS);
cmp2(STATUS_FILE_NOT_ENCRYPTED, ERROR_FILE_NOT_ENCRYPTED);
cmp2(STATUS_NOT_EXPORT_FORMAT, ERROR_NOT_EXPORT_FORMAT);
cmp2(STATUS_FILE_ENCRYPTED, ERROR_FILE_ENCRYPTED);
cmp2(STATUS_EFS_ALG_BLOB_TOO_BIG, ERROR_EFS_ALG_BLOB_TOO_BIG);
cmp(STATUS_INVALID_USER_BUFFER, ERROR_INVALID_USER_BUFFER);
cmp(STATUS_SERIAL_NO_DEVICE_INITED, ERROR_SERIAL_NO_DEVICE);
cmp(STATUS_SHARED_IRQ_BUSY, ERROR_IRQ_BUSY);
cmp(STATUS_SERIAL_MORE_WRITES, ERROR_MORE_WRITES);
cmp(STATUS_SERIAL_COUNTER_TIMEOUT, ERROR_COUNTER_TIMEOUT);
cmp(STATUS_FLOPPY_ID_MARK_NOT_FOUND, ERROR_FLOPPY_ID_MARK_NOT_FOUND);
cmp(STATUS_FLOPPY_WRONG_CYLINDER, ERROR_FLOPPY_WRONG_CYLINDER);
cmp(STATUS_FLOPPY_UNKNOWN_ERROR, ERROR_FLOPPY_UNKNOWN_ERROR);
cmp(STATUS_FLOPPY_BAD_REGISTERS, ERROR_FLOPPY_BAD_REGISTERS);
cmp(STATUS_DISK_RECALIBRATE_FAILED, ERROR_DISK_RECALIBRATE_FAILED);
cmp(STATUS_DISK_OPERATION_FAILED, ERROR_DISK_OPERATION_FAILED);
cmp(STATUS_DISK_RESET_FAILED, ERROR_DISK_RESET_FAILED);
cmp(STATUS_EVENTLOG_FILE_CORRUPT, ERROR_EVENTLOG_FILE_CORRUPT);
cmp(STATUS_EVENTLOG_CANT_START, ERROR_EVENTLOG_CANT_START);
cmp(STATUS_NETLOGON_NOT_STARTED, ERROR_NETLOGON_NOT_STARTED);
cmp(STATUS_ACCOUNT_EXPIRED, ERROR_ACCOUNT_EXPIRED);
cmp(STATUS_NETWORK_CREDENTIAL_CONFLICT, ERROR_SESSION_CREDENTIAL_CONFLICT);
cmp(STATUS_REMOTE_SESSION_LIMIT, ERROR_REMOTE_SESSION_LIMIT_EXCEEDED);
cmp(STATUS_INVALID_BUFFER_SIZE, ERROR_INVALID_USER_BUFFER);
cmp(STATUS_INVALID_ADDRESS_COMPONENT, ERROR_INVALID_NETNAME);
cmp(STATUS_INVALID_ADDRESS_WILDCARD, ERROR_INVALID_NETNAME);
cmp(STATUS_ADDRESS_ALREADY_EXISTS, ERROR_DUP_NAME);
cmp(STATUS_ADDRESS_CLOSED, ERROR_NETNAME_DELETED);
cmp(STATUS_CONNECTION_DISCONNECTED, ERROR_NETNAME_DELETED);
cmp(STATUS_CONNECTION_RESET, ERROR_NETNAME_DELETED);
cmp(STATUS_TRANSACTION_ABORTED, ERROR_UNEXP_NET_ERR);
cmp(STATUS_TRANSACTION_TIMED_OUT, ERROR_UNEXP_NET_ERR);
cmp(STATUS_TRANSACTION_NO_RELEASE, ERROR_UNEXP_NET_ERR);
cmp(STATUS_TRANSACTION_NO_MATCH, ERROR_UNEXP_NET_ERR);
cmp(STATUS_TRANSACTION_RESPONDED, ERROR_UNEXP_NET_ERR);
cmp(STATUS_TRANSACTION_INVALID_ID, ERROR_UNEXP_NET_ERR);
cmp(STATUS_TRANSACTION_INVALID_TYPE, ERROR_UNEXP_NET_ERR);
cmp(STATUS_NOT_SERVER_SESSION, ERROR_NOT_SUPPORTED);
cmp(STATUS_NOT_CLIENT_SESSION, ERROR_NOT_SUPPORTED);
cmp(STATUS_USER_MAPPED_FILE, ERROR_USER_MAPPED_FILE);
cmp(STATUS_PLUGPLAY_NO_DEVICE, ERROR_SERVICE_DISABLED);
cmp2(STATUS_WMI_GUID_NOT_FOUND, ERROR_WMI_GUID_NOT_FOUND);
cmp2(STATUS_WMI_INSTANCE_NOT_FOUND, ERROR_WMI_INSTANCE_NOT_FOUND);
cmp2(STATUS_WMI_ITEMID_NOT_FOUND, ERROR_WMI_ITEMID_NOT_FOUND);
cmp2(STATUS_WMI_TRY_AGAIN, ERROR_WMI_TRY_AGAIN);
cmp2(STATUS_WMI_READ_ONLY, ERROR_WMI_READ_ONLY);
cmp2(STATUS_WMI_SET_FAILURE, ERROR_WMI_SET_FAILURE);
cmp2(STATUS_WMI_NOT_SUPPORTED, ERROR_NOT_SUPPORTED);
cmp2(STATUS_WMI_GUID_DISCONNECTED, ERROR_WMI_GUID_DISCONNECTED);
cmp2(STATUS_WMI_ALREADY_DISABLED, ERROR_WMI_ALREADY_DISABLED);
cmp2(STATUS_WMI_ALREADY_ENABLED, ERROR_WMI_ALREADY_ENABLED);
cmp2(STATUS_COPY_PROTECTION_FAILURE, STG_E_STATUS_COPY_PROTECTION_FAILURE);
cmp2(STATUS_CSS_AUTHENTICATION_FAILURE, STG_E_CSS_AUTHENTICATION_FAILURE);
cmp2(STATUS_CSS_KEY_NOT_PRESENT, STG_E_CSS_KEY_NOT_PRESENT);
cmp2(STATUS_CSS_KEY_NOT_ESTABLISHED, STG_E_CSS_KEY_NOT_ESTABLISHED);
cmp2(STATUS_CSS_SCRAMBLED_SECTOR, STG_E_CSS_SCRAMBLED_SECTOR);
cmp2(STATUS_CSS_REGION_MISMATCH, STG_E_CSS_REGION_MISMATCH);
cmp2(STATUS_CSS_RESETS_EXHAUSTED, STG_E_RESETS_EXHAUSTED);
cmp(RPC_NT_SERVER_UNAVAILABLE, RPC_S_SERVER_UNAVAILABLE);
cmp(RPC_NT_INVALID_STRING_BINDING, RPC_S_INVALID_STRING_BINDING);
cmp(RPC_NT_WRONG_KIND_OF_BINDING, RPC_S_WRONG_KIND_OF_BINDING);
cmp(RPC_NT_PROTSEQ_NOT_SUPPORTED, RPC_S_PROTSEQ_NOT_SUPPORTED);
cmp(RPC_NT_INVALID_RPC_PROTSEQ, RPC_S_INVALID_RPC_PROTSEQ);
cmp(RPC_NT_INVALID_STRING_UUID, RPC_S_INVALID_STRING_UUID);
cmp(RPC_NT_INVALID_ENDPOINT_FORMAT, RPC_S_INVALID_ENDPOINT_FORMAT);
cmp(RPC_NT_INVALID_NET_ADDR, RPC_S_INVALID_NET_ADDR);
cmp(RPC_NT_NO_ENDPOINT_FOUND, RPC_S_NO_ENDPOINT_FOUND);
cmp(RPC_NT_INVALID_TIMEOUT, RPC_S_INVALID_TIMEOUT);
cmp(RPC_NT_OBJECT_NOT_FOUND, RPC_S_OBJECT_NOT_FOUND);
cmp(RPC_NT_ALREADY_REGISTERED, RPC_S_ALREADY_REGISTERED);
cmp(RPC_NT_TYPE_ALREADY_REGISTERED, RPC_S_TYPE_ALREADY_REGISTERED);
cmp(RPC_NT_ALREADY_LISTENING, RPC_S_ALREADY_LISTENING);
cmp(RPC_NT_NO_PROTSEQS_REGISTERED, RPC_S_NO_PROTSEQS_REGISTERED);
cmp(RPC_NT_NOT_LISTENING, RPC_S_NOT_LISTENING);
cmp(RPC_NT_UNKNOWN_MGR_TYPE, RPC_S_UNKNOWN_MGR_TYPE);
cmp(RPC_NT_UNKNOWN_IF, RPC_S_UNKNOWN_IF);
cmp(RPC_NT_NO_BINDINGS, RPC_S_NO_BINDINGS);
cmp(RPC_NT_NO_MORE_BINDINGS, RPC_S_NO_MORE_BINDINGS);
cmp(RPC_NT_NO_PROTSEQS, RPC_S_NO_PROTSEQS);
cmp(RPC_NT_CANT_CREATE_ENDPOINT, RPC_S_CANT_CREATE_ENDPOINT);
cmp(RPC_NT_OUT_OF_RESOURCES, RPC_S_OUT_OF_RESOURCES);
cmp(RPC_NT_SERVER_TOO_BUSY, RPC_S_SERVER_TOO_BUSY);
cmp(RPC_NT_INVALID_NETWORK_OPTIONS, RPC_S_INVALID_NETWORK_OPTIONS);
cmp(RPC_NT_NO_CALL_ACTIVE, RPC_S_NO_CALL_ACTIVE);
cmp(RPC_NT_CALL_FAILED, RPC_S_CALL_FAILED);
cmp(RPC_NT_CALL_FAILED_DNE, RPC_S_CALL_FAILED_DNE);
cmp(RPC_NT_PROTOCOL_ERROR, RPC_S_PROTOCOL_ERROR);
cmp(RPC_NT_UNSUPPORTED_TRANS_SYN, RPC_S_UNSUPPORTED_TRANS_SYN);
cmp(RPC_NT_UNSUPPORTED_TYPE, RPC_S_UNSUPPORTED_TYPE);
cmp(RPC_NT_INVALID_TAG, RPC_S_INVALID_TAG);
cmp(RPC_NT_INVALID_BOUND, RPC_S_INVALID_BOUND);
cmp(RPC_NT_NO_ENTRY_NAME, RPC_S_NO_ENTRY_NAME);
cmp(RPC_NT_INVALID_NAME_SYNTAX, RPC_S_INVALID_NAME_SYNTAX);
cmp(RPC_NT_UNSUPPORTED_NAME_SYNTAX, RPC_S_UNSUPPORTED_NAME_SYNTAX);
cmp(RPC_NT_UUID_NO_ADDRESS, RPC_S_UUID_NO_ADDRESS);
cmp(RPC_NT_DUPLICATE_ENDPOINT, RPC_S_DUPLICATE_ENDPOINT);
cmp(RPC_NT_UNKNOWN_AUTHN_TYPE, RPC_S_UNKNOWN_AUTHN_TYPE);
cmp(RPC_NT_MAX_CALLS_TOO_SMALL, RPC_S_MAX_CALLS_TOO_SMALL);
cmp(RPC_NT_STRING_TOO_LONG, RPC_S_STRING_TOO_LONG);
cmp(RPC_NT_PROTSEQ_NOT_FOUND, RPC_S_PROTSEQ_NOT_FOUND);
cmp(RPC_NT_PROCNUM_OUT_OF_RANGE, RPC_S_PROCNUM_OUT_OF_RANGE);
cmp(RPC_NT_BINDING_HAS_NO_AUTH, RPC_S_BINDING_HAS_NO_AUTH);
cmp(RPC_NT_UNKNOWN_AUTHN_SERVICE, RPC_S_UNKNOWN_AUTHN_SERVICE);
cmp(RPC_NT_UNKNOWN_AUTHN_LEVEL, RPC_S_UNKNOWN_AUTHN_LEVEL);
cmp(RPC_NT_INVALID_AUTH_IDENTITY, RPC_S_INVALID_AUTH_IDENTITY);
cmp(RPC_NT_UNKNOWN_AUTHZ_SERVICE, RPC_S_UNKNOWN_AUTHZ_SERVICE);
cmp(EPT_NT_INVALID_ENTRY, EPT_S_INVALID_ENTRY);
cmp(EPT_NT_CANT_PERFORM_OP, EPT_S_CANT_PERFORM_OP);
cmp(EPT_NT_NOT_REGISTERED, EPT_S_NOT_REGISTERED);
cmp(RPC_NT_NOTHING_TO_EXPORT, RPC_S_NOTHING_TO_EXPORT);
cmp(RPC_NT_INCOMPLETE_NAME, RPC_S_INCOMPLETE_NAME);
cmp(RPC_NT_INVALID_VERS_OPTION, RPC_S_INVALID_VERS_OPTION);
cmp(RPC_NT_NO_MORE_MEMBERS, RPC_S_NO_MORE_MEMBERS);
cmp(RPC_NT_NOT_ALL_OBJS_UNEXPORTED, RPC_S_NOT_ALL_OBJS_UNEXPORTED);
cmp(RPC_NT_INTERFACE_NOT_FOUND, RPC_S_INTERFACE_NOT_FOUND);
cmp(RPC_NT_ENTRY_ALREADY_EXISTS, RPC_S_ENTRY_ALREADY_EXISTS);
cmp(RPC_NT_ENTRY_NOT_FOUND, RPC_S_ENTRY_NOT_FOUND);
cmp(RPC_NT_NAME_SERVICE_UNAVAILABLE, RPC_S_NAME_SERVICE_UNAVAILABLE);
cmp(RPC_NT_INVALID_NAF_ID, RPC_S_INVALID_NAF_ID);
cmp(RPC_NT_CANNOT_SUPPORT, RPC_S_CANNOT_SUPPORT);
cmp(RPC_NT_NO_CONTEXT_AVAILABLE, RPC_S_NO_CONTEXT_AVAILABLE);
cmp(RPC_NT_INTERNAL_ERROR, RPC_S_INTERNAL_ERROR);
cmp(RPC_NT_ZERO_DIVIDE, RPC_S_ZERO_DIVIDE);
cmp(RPC_NT_ADDRESS_ERROR, RPC_S_ADDRESS_ERROR);
cmp(RPC_NT_FP_DIV_ZERO, RPC_S_FP_DIV_ZERO);
cmp(RPC_NT_FP_UNDERFLOW, RPC_S_FP_UNDERFLOW);
cmp(RPC_NT_FP_OVERFLOW, RPC_S_FP_OVERFLOW);
cmp(RPC_NT_NO_MORE_ENTRIES, RPC_X_NO_MORE_ENTRIES);
cmp(RPC_NT_SS_CHAR_TRANS_OPEN_FAIL, RPC_X_SS_CHAR_TRANS_OPEN_FAIL);
cmp(RPC_NT_SS_CHAR_TRANS_SHORT_FILE, RPC_X_SS_CHAR_TRANS_SHORT_FILE);
cmp(RPC_NT_SS_CONTEXT_MISMATCH, ERROR_INVALID_HANDLE);
cmp(RPC_NT_SS_CONTEXT_DAMAGED, RPC_X_SS_CONTEXT_DAMAGED);
cmp(RPC_NT_SS_HANDLES_MISMATCH, RPC_X_SS_HANDLES_MISMATCH);
cmp(RPC_NT_SS_CANNOT_GET_CALL_HANDLE, RPC_X_SS_CANNOT_GET_CALL_HANDLE);
cmp(RPC_NT_NULL_REF_POINTER, RPC_X_NULL_REF_POINTER);
cmp(RPC_NT_ENUM_VALUE_OUT_OF_RANGE, RPC_X_ENUM_VALUE_OUT_OF_RANGE);
cmp(RPC_NT_BYTE_COUNT_TOO_SMALL, RPC_X_BYTE_COUNT_TOO_SMALL);
cmp(RPC_NT_BAD_STUB_DATA, RPC_X_BAD_STUB_DATA);
cmp(RPC_NT_INVALID_OBJECT, RPC_S_INVALID_OBJECT);
cmp(STATUS_NO_TRUST_LSA_SECRET, ERROR_NO_TRUST_LSA_SECRET);
cmp(STATUS_NO_TRUST_SAM_ACCOUNT, ERROR_NO_TRUST_SAM_ACCOUNT);
cmp(STATUS_TRUSTED_DOMAIN_FAILURE, ERROR_TRUSTED_DOMAIN_FAILURE);
cmp(STATUS_TRUSTED_RELATIONSHIP_FAILURE, ERROR_TRUSTED_RELATIONSHIP_FAILURE);
cmp(STATUS_TRUST_FAILURE, ERROR_TRUST_FAILURE);
cmp(RPC_NT_CALL_IN_PROGRESS, RPC_S_CALL_IN_PROGRESS);
cmp(STATUS_LOG_FILE_FULL, ERROR_LOG_FILE_FULL);
cmp(STATUS_EVENTLOG_FILE_CHANGED, ERROR_EVENTLOG_FILE_CHANGED);
cmp(STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT, ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT);
cmp(STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT);
cmp(STATUS_NOLOGON_SERVER_TRUST_ACCOUNT, ERROR_NOLOGON_SERVER_TRUST_ACCOUNT);
cmp(STATUS_DOMAIN_TRUST_INCONSISTENT, ERROR_DOMAIN_TRUST_INCONSISTENT);
cmp(STATUS_NO_USER_SESSION_KEY, ERROR_NO_USER_SESSION_KEY);
cmp(STATUS_POSSIBLE_DEADLOCK, ERROR_POSSIBLE_DEADLOCK);
cmp(STATUS_IMAGE_ALREADY_LOADED, ERROR_SERVICE_ALREADY_RUNNING);
cmp(RPC_NT_GROUP_MEMBER_NOT_FOUND, RPC_S_GROUP_MEMBER_NOT_FOUND);
cmp(RPC_NT_NO_INTERFACES, RPC_S_NO_INTERFACES);
cmp(RPC_NT_CALL_CANCELLED, RPC_S_CALL_CANCELLED);
cmp(RPC_NT_BINDING_INCOMPLETE, RPC_S_BINDING_INCOMPLETE);
cmp(RPC_NT_COMM_FAILURE, RPC_S_COMM_FAILURE);
cmp(RPC_NT_UNSUPPORTED_AUTHN_LEVEL, RPC_S_UNSUPPORTED_AUTHN_LEVEL);
cmp(RPC_NT_NO_PRINC_NAME, RPC_S_NO_PRINC_NAME);
cmp(RPC_NT_NOT_RPC_ERROR, RPC_S_NOT_RPC_ERROR);
cmp(RPC_NT_UUID_LOCAL_ONLY, RPC_S_UUID_LOCAL_ONLY);
cmp(RPC_NT_SEC_PKG_ERROR, RPC_S_SEC_PKG_ERROR);
cmp(RPC_NT_NOT_CANCELLED, RPC_S_NOT_CANCELLED);
cmp(RPC_NT_INVALID_ES_ACTION, RPC_X_INVALID_ES_ACTION);
cmp(RPC_NT_WRONG_ES_VERSION, RPC_X_WRONG_ES_VERSION);
cmp(RPC_NT_WRONG_STUB_VERSION, RPC_X_WRONG_STUB_VERSION);
cmp(RPC_NT_INVALID_PIPE_OBJECT, RPC_X_INVALID_PIPE_OBJECT);
cmp(RPC_NT_INVALID_PIPE_OPERATION, RPC_X_INVALID_PIPE_OPERATION);
cmp(RPC_NT_WRONG_PIPE_VERSION, RPC_X_WRONG_PIPE_VERSION);
cmp(EPT_NT_CANT_CREATE, EPT_S_CANT_CREATE);
cmp(RPC_NT_SEND_INCOMPLETE, RPC_S_SEND_INCOMPLETE);
cmp2(RPC_NT_INVALID_ASYNC_HANDLE, RPC_S_INVALID_ASYNC_HANDLE);
cmp2(RPC_NT_INVALID_ASYNC_CALL, RPC_S_INVALID_ASYNC_CALL);
cmp2(RPC_NT_PIPE_CLOSED, RPC_X_PIPE_CLOSED);
cmp2(RPC_NT_PIPE_EMPTY, RPC_X_PIPE_EMPTY);
cmp2(RPC_NT_PIPE_DISCIPLINE_ERROR, RPC_X_PIPE_DISCIPLINE_ERROR);
cmp(STATUS_NO_BROWSER_SERVERS_FOUND, ERROR_NO_BROWSER_SERVERS_FOUND);
cmp(STATUS_MAPPED_ALIGNMENT, ERROR_MAPPED_ALIGNMENT);
cmp(STATUS_CONNECTION_IN_USE, ERROR_DEVICE_IN_USE);
cmp(STATUS_VERIFY_REQUIRED, ERROR_MEDIA_CHANGED);
cmp(STATUS_ALREADY_DISCONNECTED, ERROR_ACTIVE_CONNECTIONS);
cmp(STATUS_CONNECTION_REFUSED, ERROR_CONNECTION_REFUSED);
cmp(STATUS_GRACEFUL_DISCONNECT, ERROR_GRACEFUL_DISCONNECT);
cmp(STATUS_ADDRESS_ALREADY_ASSOCIATED, ERROR_ADDRESS_ALREADY_ASSOCIATED);
cmp(STATUS_ADDRESS_NOT_ASSOCIATED, ERROR_ADDRESS_NOT_ASSOCIATED);
cmp(STATUS_CONNECTION_INVALID, ERROR_CONNECTION_INVALID);
cmp(STATUS_CONNECTION_ACTIVE, ERROR_CONNECTION_ACTIVE);
cmp(STATUS_NETWORK_UNREACHABLE, ERROR_NETWORK_UNREACHABLE);
cmp(STATUS_HOST_UNREACHABLE, ERROR_HOST_UNREACHABLE);
cmp2(STATUS_HOST_DOWN, ERROR_HOST_DOWN);
cmp(STATUS_PROTOCOL_UNREACHABLE, ERROR_PROTOCOL_UNREACHABLE);
cmp(STATUS_PORT_UNREACHABLE, ERROR_PORT_UNREACHABLE);
cmp(STATUS_REQUEST_ABORTED, ERROR_REQUEST_ABORTED);
cmp(STATUS_CONNECTION_ABORTED, ERROR_CONNECTION_ABORTED);
cmp(STATUS_CONNECTION_COUNT_LIMIT, ERROR_CONNECTION_COUNT_LIMIT);
cmp(STATUS_PATH_NOT_COVERED, ERROR_HOST_UNREACHABLE);
cmp(STATUS_LOGIN_TIME_RESTRICTION, ERROR_LOGIN_TIME_RESTRICTION);
cmp(STATUS_LOGIN_WKSTA_RESTRICTION, ERROR_LOGIN_WKSTA_RESTRICTION);
cmp(STATUS_LICENSE_QUOTA_EXCEEDED, ERROR_LICENSE_QUOTA_EXCEEDED);
cmp(STATUS_RESOURCE_NOT_OWNED, ERROR_NOT_OWNER);
cmp(STATUS_DUPLICATE_OBJECTID, STATUS_DUPLICATE_OBJECTID);
cmp(STATUS_OBJECTID_EXISTS, STATUS_OBJECTID_EXISTS);
cmp2(STATUS_OBJECTID_NOT_FOUND, ERROR_FILE_NOT_FOUND);
cmp2(STATUS_MFT_TOO_FRAGMENTED, ERROR_DISK_TOO_FRAGMENTED);
cmp(SEC_E_INSUFFICIENT_MEMORY, ERROR_NO_SYSTEM_RESOURCES);
cmp(SEC_E_INVALID_HANDLE, ERROR_INVALID_HANDLE);
cmp(SEC_E_UNSUPPORTED_FUNCTION, ERROR_INVALID_FUNCTION);
cmp(SEC_E_TARGET_UNKNOWN, ERROR_BAD_NETPATH);
cmp(SEC_E_INTERNAL_ERROR, ERROR_INTERNAL_ERROR);
cmp(SEC_E_SECPKG_NOT_FOUND, ERROR_NO_SUCH_PACKAGE);
cmp(SEC_E_NOT_OWNER, ERROR_NOT_OWNER);
cmp(SEC_E_CANNOT_INSTALL, ERROR_NO_SUCH_PACKAGE);
cmp(SEC_E_INVALID_TOKEN, ERROR_INVALID_PARAMETER);
cmp(SEC_E_CANNOT_PACK, ERROR_INVALID_PARAMETER);
cmp(SEC_E_QOP_NOT_SUPPORTED, ERROR_NOT_SUPPORTED);
cmp(SEC_E_NO_IMPERSONATION, ERROR_CANNOT_IMPERSONATE);
cmp2(SEC_E_MULTIPLE_ACCOUNTS, ERROR_CANNOT_IMPERSONATE);
cmp(SEC_E_LOGON_DENIED, ERROR_LOGON_FAILURE);
cmp(SEC_E_UNKNOWN_CREDENTIALS, ERROR_INVALID_PARAMETER);
cmp2(SEC_E_INCOMPLETE_CREDENTIALS, ERROR_INVALID_PARAMETER);
cmp(SEC_E_NO_CREDENTIALS, ERROR_NO_SUCH_LOGON_SESSION);
cmp(SEC_E_MESSAGE_ALTERED, ERROR_ACCESS_DENIED);
cmp(SEC_E_OUT_OF_SEQUENCE, ERROR_ACCESS_DENIED);
cmp(SEC_E_NO_AUTHENTICATING_AUTHORITY, ERROR_NO_LOGON_SERVERS);
cmp(SEC_E_BAD_PKGID, ERROR_NO_SUCH_PACKAGE);
cmp4(SEC_E_WRONG_PRINCIPAL, ERROR_WRONG_TARGET_NAME, 1462);
cmp2(SEC_E_INCOMPLETE_MESSAGE, ERROR_INVALID_USER_BUFFER);
cmp2(SEC_E_BUFFER_TOO_SMALL, ERROR_INSUFFICIENT_BUFFER);
cmp2(SEC_E_UNTRUSTED_ROOT, ERROR_TRUST_FAILURE);
cmp2(SEC_E_ILLEGAL_MESSAGE, ERROR_INVALID_PARAMETER);
cmp2(SEC_E_CERT_UNKNOWN, ERROR_INVALID_PARAMETER);
cmp2(SEC_E_CERT_EXPIRED, ERROR_PASSWORD_EXPIRED);
cmp2(SEC_E_ENCRYPT_FAILURE, ERROR_ENCRYPTION_FAILED);
cmp2(SEC_E_DECRYPT_FAILURE, ERROR_DECRYPTION_FAILED);
cmp2(SEC_E_ALGORITHM_MISMATCH, ERROR_INVALID_FUNCTION);
cmp2(SEC_E_CONTEXT_EXPIRED, ERROR_CONTEXT_EXPIRED);
cmp2(STATUS_BAD_BINDINGS, SEC_E_BAD_BINDINGS);
cmp2(TRUST_E_CERT_SIGNATURE, ERROR_MUTUAL_AUTH_FAILED);
cmp2(CRYPT_E_REVOKED, ERROR_MUTUAL_AUTH_FAILED);
cmp2(CRYPT_E_NO_REVOCATION_CHECK, ERROR_MUTUAL_AUTH_FAILED);
cmp2(CRYPT_E_REVOCATION_OFFLINE, ERROR_MUTUAL_AUTH_FAILED);
cmp2(STATUS_SHUTDOWN_IN_PROGRESS, ERROR_SHUTDOWN_IN_PROGRESS);
cmp2(STATUS_SERVER_SHUTDOWN_IN_PROGRESS, ERROR_SERVER_SHUTDOWN_IN_PROGRESS);
cmp4(STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY, ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY, 1922);
cmp4(STATUS_DS_NO_ATTRIBUTE_OR_VALUE, ERROR_DS_NO_ATTRIBUTE_OR_VALUE, 1923);
cmp4(STATUS_DS_INVALID_ATTRIBUTE_SYNTAX, ERROR_DS_INVALID_ATTRIBUTE_SYNTAX, 1924);
cmp4(STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED, ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED, 1925);
cmp4(STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS, ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS, 1926);
cmp4(STATUS_DS_BUSY, ERROR_DS_BUSY, 1927);
cmp4(STATUS_DS_UNAVAILABLE, ERROR_DS_UNAVAILABLE, 1928);
cmp4(STATUS_DS_NO_RIDS_ALLOCATED, ERROR_DS_NO_RIDS_ALLOCATED, 1929);
cmp4(STATUS_DS_NO_MORE_RIDS, ERROR_DS_NO_MORE_RIDS, 1930);
cmp4(STATUS_DS_INCORRECT_ROLE_OWNER, ERROR_DS_INCORRECT_ROLE_OWNER, 1931);
cmp4(STATUS_DS_RIDMGR_INIT_ERROR, ERROR_DS_RIDMGR_INIT_ERROR, 1932);
cmp4(STATUS_DS_OBJ_CLASS_VIOLATION, ERROR_DS_OBJ_CLASS_VIOLATION, 1933);
cmp4(STATUS_DS_CANT_ON_NON_LEAF, ERROR_DS_CANT_ON_NON_LEAF, 1934);
cmp4(STATUS_DS_CANT_ON_RDN, ERROR_DS_CANT_ON_RDN, 1935);
cmp4(STATUS_DS_CROSS_DOM_MOVE_FAILED, ERROR_DS_CROSS_DOM_MOVE_ERROR, 1937);
cmp4(STATUS_DS_GC_NOT_AVAILABLE, ERROR_DS_GC_NOT_AVAILABLE, 1938);
cmp2(STATUS_DS_CANT_MOD_OBJ_CLASS, ERROR_DS_CANT_MOD_OBJ_CLASS);
cmp2(STATUS_DS_ADMIN_LIMIT_EXCEEDED, ERROR_DS_ADMIN_LIMIT_EXCEEDED);
cmp2(STATUS_DIRECTORY_SERVICE_REQUIRED, ERROR_DS_DS_REQUIRED);
cmp2(STATUS_DS_SAM_INIT_FAILURE, ERROR_DS_SAM_INIT_FAILURE);
cmp2(STATUS_DS_CANT_START, ERROR_DS_CANT_START);
cmp2(STATUS_DS_INIT_FAILURE, ERROR_DS_INIT_FAILURE);
cmp2(STATUS_SAM_INIT_FAILURE, ERROR_SAM_INIT_FAILURE);
cmp2(STATUS_DS_SENSITIVE_GROUP_VIOLATION, ERROR_DS_SENSITIVE_GROUP_VIOLATION);
cmp2(STATUS_DS_CANT_MOD_PRIMARYGROUPID, ERROR_DS_CANT_MOD_PRIMARYGROUPID);
cmp2(STATUS_DS_INVALID_GROUP_TYPE, ERROR_DS_INVALID_GROUP_TYPE);
cmp2(STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN, ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN);
cmp2(STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN, ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN);
cmp2(STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER, ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER);
cmp2(STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER, ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER);
cmp2(STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER, ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER);
cmp2(STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER, ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER);
cmp2(STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER, ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER);
cmp2(STATUS_DS_HAVE_PRIMARY_MEMBERS, ERROR_DS_HAVE_PRIMARY_MEMBERS);
cmp2(STATUS_DS_GC_REQUIRED, ERROR_DS_GC_REQUIRED);
cmp2(STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY, ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY);
cmp2(STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS, ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS);
cmp2(STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED,ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED);
cmp2(STATUS_SAM_NEED_BOOTKEY_PASSWORD, ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD);
cmp2(STATUS_SAM_NEED_BOOTKEY_FLOPPY, ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY);
cmp2(STATUS_DS_INIT_FAILURE_CONSOLE, ERROR_DS_INIT_FAILURE_CONSOLE);
cmp2(STATUS_DS_SAM_INIT_FAILURE_CONSOLE, ERROR_DS_SAM_INIT_FAILURE_CONSOLE);
cmp2(STATUS_UNFINISHED_CONTEXT_DELETED, SEC_E_UNFINISHED_CONTEXT_DELETED);
cmp2(STATUS_NO_TGT_REPLY, SEC_E_NO_TGT_REPLY);
cmp2(STATUS_NO_IP_ADDRESSES, SEC_E_NO_IP_ADDRESSES);
cmp2(STATUS_WRONG_CREDENTIAL_HANDLE, SEC_E_WRONG_CREDENTIAL_HANDLE);
cmp2(STATUS_CRYPTO_SYSTEM_INVALID, SEC_E_CRYPTO_SYSTEM_INVALID);
cmp2(STATUS_MAX_REFERRALS_EXCEEDED, SEC_E_MAX_REFERRALS_EXCEEDED);
cmp2(STATUS_MUST_BE_KDC, SEC_E_MUST_BE_KDC);
cmp2(STATUS_STRONG_CRYPTO_NOT_SUPPORTED, SEC_E_STRONG_CRYPTO_NOT_SUPPORTED);
cmp2(STATUS_TOO_MANY_PRINCIPALS, SEC_E_TOO_MANY_PRINCIPALS);
cmp2(STATUS_NO_PA_DATA, SEC_E_NO_PA_DATA);
cmp2(STATUS_PKINIT_NAME_MISMATCH, SEC_E_PKINIT_NAME_MISMATCH);
cmp2(STATUS_SMARTCARD_LOGON_REQUIRED, SEC_E_SMARTCARD_LOGON_REQUIRED);
cmp2(STATUS_KDC_INVALID_REQUEST, SEC_E_KDC_INVALID_REQUEST);
cmp2(STATUS_KDC_UNABLE_TO_REFER, SEC_E_KDC_UNABLE_TO_REFER);
cmp2(STATUS_KDC_UNKNOWN_ETYPE, SEC_E_KDC_UNKNOWN_ETYPE);
cmp2(STATUS_UNSUPPORTED_PREAUTH, SEC_E_UNSUPPORTED_PREAUTH);
cmp4(STATUS_SHARED_POLICY, ERROR_SHARED_POLICY, 1939);
cmp4(STATUS_POLICY_OBJECT_NOT_FOUND, ERROR_POLICY_OBJECT_NOT_FOUND, 1940);
cmp4(STATUS_POLICY_ONLY_IN_DS, ERROR_POLICY_ONLY_IN_DS, 1941);
cmp4(STATUS_DEVICE_REMOVED, ERROR_DEVICE_REMOVED, 617);
cmp2(STATUS_RETRY, ERROR_RETRY);
cmp2(STATUS_NOT_SUPPORTED_ON_SBS, ERROR_NOT_SUPPORTED_ON_SBS);
cmp2(STATUS_DRIVER_BLOCKED_CRITICAL, ERROR_DRIVER_BLOCKED);
cmp2(STATUS_DRIVER_BLOCKED, ERROR_DRIVER_BLOCKED);
cmp2(STATUS_PRENT4_MACHINE_ACCOUNT, ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4);
cmp2(STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER,ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER);
cmp2(STATUS_DS_SHUTTING_DOWN, ERROR_DS_SHUTTING_DOWN);
cmp2(STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT, ERROR_ACCESS_DISABLED_BY_POLICY);
cmp2(STATUS_ACCESS_DISABLED_BY_POLICY_PATH, ERROR_ACCESS_DISABLED_BY_POLICY);
cmp2(STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER, ERROR_ACCESS_DISABLED_BY_POLICY);
cmp2(STATUS_ACCESS_DISABLED_BY_POLICY_OTHER, ERROR_ACCESS_DISABLED_BY_POLICY);
cmp2(STATUS_FAIL_CHECK, ERROR_INVALID_PARAMETER);
cmp2(STATUS_CTX_CLOSE_PENDING, ERROR_CTX_CLOSE_PENDING);
cmp2(STATUS_CTX_NO_OUTBUF, ERROR_CTX_NO_OUTBUF);
cmp2(STATUS_CTX_MODEM_INF_NOT_FOUND, ERROR_CTX_MODEM_INF_NOT_FOUND);
cmp2(STATUS_CTX_INVALID_MODEMNAME, ERROR_CTX_INVALID_MODEMNAME);
cmp2(STATUS_CTX_RESPONSE_ERROR, ERROR_CTX_MODEM_RESPONSE_ERROR);
cmp2(STATUS_CTX_MODEM_RESPONSE_TIMEOUT, ERROR_CTX_MODEM_RESPONSE_TIMEOUT);
cmp2(STATUS_CTX_MODEM_RESPONSE_NO_CARRIER, ERROR_CTX_MODEM_RESPONSE_NO_CARRIER);
cmp2(STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE, ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE);
cmp2(STATUS_CTX_MODEM_RESPONSE_BUSY, ERROR_CTX_MODEM_RESPONSE_BUSY);
cmp2(STATUS_CTX_MODEM_RESPONSE_VOICE, ERROR_CTX_MODEM_RESPONSE_VOICE);
cmp2(STATUS_CTX_TD_ERROR, ERROR_CTX_TD_ERROR);
cmp2(STATUS_CTX_WINSTATION_NAME_INVALID, ERROR_CTX_WINSTATION_NAME_INVALID);
cmp2(STATUS_CTX_WINSTATION_NOT_FOUND, ERROR_CTX_WINSTATION_NOT_FOUND);
cmp2(STATUS_CTX_WINSTATION_NAME_COLLISION, ERROR_CTX_WINSTATION_ALREADY_EXISTS);
cmp2(STATUS_CTX_WINSTATION_BUSY, ERROR_CTX_WINSTATION_BUSY);
cmp2(STATUS_CTX_GRAPHICS_INVALID, ERROR_CTX_GRAPHICS_INVALID);
cmp2(STATUS_CTX_BAD_VIDEO_MODE, ERROR_CTX_BAD_VIDEO_MODE);
cmp2(STATUS_CTX_NOT_CONSOLE, ERROR_CTX_NOT_CONSOLE);
cmp2(STATUS_CTX_CLIENT_QUERY_TIMEOUT, ERROR_CTX_CLIENT_QUERY_TIMEOUT);
cmp2(STATUS_CTX_CONSOLE_DISCONNECT, ERROR_CTX_CONSOLE_DISCONNECT);
cmp2(STATUS_CTX_CONSOLE_CONNECT, ERROR_CTX_CONSOLE_CONNECT);
cmp2(STATUS_CTX_SHADOW_DENIED, ERROR_CTX_SHADOW_DENIED);
cmp2(STATUS_CTX_SHADOW_INVALID, ERROR_CTX_SHADOW_INVALID);
cmp2(STATUS_CTX_SHADOW_DISABLED, ERROR_CTX_SHADOW_DISABLED);
cmp2(STATUS_CTX_WINSTATION_ACCESS_DENIED, ERROR_CTX_WINSTATION_ACCESS_DENIED);
cmp2(STATUS_CTX_INVALID_PD, ERROR_CTX_INVALID_PD);
cmp2(STATUS_CTX_PD_NOT_FOUND, ERROR_CTX_PD_NOT_FOUND);
cmp2(STATUS_CTX_INVALID_WD, ERROR_CTX_INVALID_WD);
cmp2(STATUS_CTX_WD_NOT_FOUND, ERROR_CTX_WD_NOT_FOUND);
cmp2(STATUS_CTX_CLIENT_LICENSE_IN_USE, ERROR_CTX_CLIENT_LICENSE_IN_USE);
cmp2(STATUS_CTX_CLIENT_LICENSE_NOT_SET, ERROR_CTX_CLIENT_LICENSE_NOT_SET);
cmp2(STATUS_CTX_LICENSE_NOT_AVAILABLE, ERROR_CTX_LICENSE_NOT_AVAILABLE);
cmp2(STATUS_CTX_LICENSE_CLIENT_INVALID, ERROR_CTX_LICENSE_CLIENT_INVALID);
cmp2(STATUS_CTX_LICENSE_EXPIRED, ERROR_CTX_LICENSE_EXPIRED);
cmp2(STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE, ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE);
cmp2(STATUS_CTX_SHADOW_NOT_RUNNING, ERROR_CTX_SHADOW_NOT_RUNNING);
cmp2(STATUS_LICENSE_VIOLATION, ERROR_CTX_LICENSE_NOT_AVAILABLE);
#if 0
/* FIXME - unknown STATUS values, see bug 1001 */
cmp(STATUS_ENDPOINT_CLOSED, ERROR_DEV_NOT_EXIST);
cmp(STATUS_DISCONNECTED, ERROR_DEV_NOT_EXIST);
cmp(STATUS_NONEXISTENT_NET_NAME, ERROR_DEV_NOT_EXIST);
#endif
cmp2(STATUS_NETWORK_SESSION_EXPIRED, ERROR_NO_USER_SESSION_KEY);
cmp2(STATUS_FILES_OPEN, ERROR_OPEN_FILES);
cmp2(STATUS_SXS_SECTION_NOT_FOUND, ERROR_SXS_SECTION_NOT_FOUND);
cmp2(STATUS_SXS_CANT_GEN_ACTCTX, ERROR_SXS_CANT_GEN_ACTCTX);
cmp2(STATUS_SXS_INVALID_ACTCTXDATA_FORMAT, ERROR_SXS_INVALID_ACTCTXDATA_FORMAT);
cmp2(STATUS_SXS_ASSEMBLY_NOT_FOUND, ERROR_SXS_ASSEMBLY_NOT_FOUND);
cmp2(STATUS_SXS_MANIFEST_FORMAT_ERROR, ERROR_SXS_MANIFEST_FORMAT_ERROR);
cmp2(STATUS_SXS_MANIFEST_PARSE_ERROR, ERROR_SXS_MANIFEST_PARSE_ERROR);
cmp2(STATUS_SXS_ACTIVATION_CONTEXT_DISABLED, ERROR_SXS_ACTIVATION_CONTEXT_DISABLED);
cmp2(STATUS_SXS_KEY_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND);
cmp2(STATUS_SXS_WRONG_SECTION_TYPE, ERROR_SXS_WRONG_SECTION_TYPE);
cmp2(STATUS_SXS_THREAD_QUERIES_DISABLED, ERROR_SXS_THREAD_QUERIES_DISABLED);
cmp2(STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET, ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET);
cmp2(STATUS_REDIRECTOR_STARTED, ERROR_SERVICE_ALREADY_RUNNING);
cmp2(STATUS_AUDITING_DISABLED, ERROR_AUDITING_DISABLED);
cmp2(STATUS_CLUSTER_NODE_ALREADY_UP, ERROR_CLUSTER_NODE_ALREADY_UP);
cmp2(STATUS_CLUSTER_NODE_ALREADY_DOWN, ERROR_CLUSTER_NODE_ALREADY_DOWN);
cmp2(STATUS_CLUSTER_NETWORK_ALREADY_ONLINE, ERROR_CLUSTER_NETWORK_ALREADY_ONLINE);
cmp2(STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE, ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE);
cmp2(STATUS_CLUSTER_NODE_ALREADY_MEMBER, ERROR_CLUSTER_NODE_ALREADY_MEMBER);
cmp2(STATUS_CLUSTER_INVALID_NODE, ERROR_CLUSTER_INVALID_NODE);
cmp2(STATUS_CLUSTER_NODE_EXISTS, ERROR_CLUSTER_NODE_EXISTS);
cmp2(STATUS_CLUSTER_JOIN_IN_PROGRESS, ERROR_CLUSTER_JOIN_IN_PROGRESS);
cmp2(STATUS_CLUSTER_NODE_NOT_FOUND, ERROR_CLUSTER_NODE_NOT_FOUND);
cmp2(STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND, ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND);
cmp2(STATUS_CLUSTER_NETWORK_EXISTS, ERROR_CLUSTER_NETWORK_EXISTS);
cmp2(STATUS_CLUSTER_NETWORK_NOT_FOUND, ERROR_CLUSTER_NETWORK_NOT_FOUND);
cmp2(STATUS_CLUSTER_NETINTERFACE_EXISTS, ERROR_CLUSTER_NETINTERFACE_EXISTS);
cmp2(STATUS_CLUSTER_NETINTERFACE_NOT_FOUND, ERROR_CLUSTER_NETINTERFACE_NOT_FOUND);
cmp2(STATUS_CLUSTER_INVALID_REQUEST, ERROR_CLUSTER_INVALID_REQUEST);
cmp2(STATUS_CLUSTER_INVALID_NETWORK_PROVIDER,ERROR_CLUSTER_INVALID_NETWORK_PROVIDER);
cmp2(STATUS_CLUSTER_NODE_DOWN, ERROR_CLUSTER_NODE_DOWN);
cmp2(STATUS_CLUSTER_NODE_UNREACHABLE, ERROR_CLUSTER_NODE_UNREACHABLE);
cmp2(STATUS_CLUSTER_NODE_NOT_MEMBER, ERROR_CLUSTER_NODE_NOT_MEMBER);
cmp2(STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS, ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS);
cmp2(STATUS_CLUSTER_INVALID_NETWORK, ERROR_CLUSTER_INVALID_NETWORK);
cmp2(STATUS_CLUSTER_NODE_UP, ERROR_CLUSTER_NODE_UP);
cmp2(STATUS_CLUSTER_NODE_PAUSED, ERROR_CLUSTER_NODE_PAUSED);
cmp2(STATUS_CLUSTER_NODE_NOT_PAUSED, ERROR_CLUSTER_NODE_NOT_PAUSED);
cmp2(STATUS_CLUSTER_NO_SECURITY_CONTEXT, ERROR_CLUSTER_NO_SECURITY_CONTEXT);
cmp2(STATUS_CLUSTER_NETWORK_NOT_INTERNAL, ERROR_CLUSTER_NETWORK_NOT_INTERNAL);
}
START_TEST(error)
{
if (prepare_test())
run_error_tests();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,828 @@
/* Unit test suite for *Information* Registry API functions
*
* Copyright 2005 Paul Vriens
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "ntdll_test.h"
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
static HMODULE hntdll = 0;
/* 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) \
p ## func = (void*)GetProcAddress(hntdll, #func); \
if(!p ## func) { \
trace("GetProcAddress(%s) failed\n", #func); \
FreeLibrary(hntdll); \
return FALSE; \
}
static BOOL InitFunctionPtrs(void)
{
hntdll = LoadLibraryA("ntdll.dll");
if(!hntdll) {
trace("Could not load ntdll.dll\n");
return FALSE;
}
if (hntdll)
{
NTDLL_GET_PROC(NtQuerySystemInformation)
NTDLL_GET_PROC(NtQueryInformationProcess)
}
return TRUE;
}
static void test_query_basic(void)
{
DWORD status;
ULONG ReturnLength;
SYSTEM_BASIC_INFORMATION sbi;
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
/* Check if we have some return values */
trace("Number of Processors : %d\n", sbi.NumberOfProcessors);
ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n", sbi.NumberOfProcessors);
}
static void test_query_cpu(void)
{
DWORD status;
ULONG ReturnLength;
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);
/* 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);
}
static void test_query_performance(void)
{
DWORD status;
ULONG ReturnLength;
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);
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);
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);
/* Not return values yet, as struct members are unknown */
}
static void test_query_timeofday(void)
{
DWORD status;
ULONG ReturnLength;
/* Copy of our winternl.h structure turned into a private one */
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE {
LARGE_INTEGER liKeBootTime;
LARGE_INTEGER liKeSystemTime;
LARGE_INTEGER liExpTimeZoneBias;
ULONG uCurrentTimeZoneId;
DWORD dwUnknown1[5];
} 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
* then 48 and 0 otherwise
* Windows NT returns STATUS_INFO_LENGTH_MISMATCH when the given buffer size is not correct
* and 0 otherwise
*
* Windows 2000 and XP copy the given buffer size into the provided buffer, if the return code is STATUS_SUCCESS
* NT only fills the buffer if the return code is STATUS_SUCCESS
*
*/
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
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);
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);
}
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);
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( 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( 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);
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);
}
/* Check if we have some return values */
trace("uCurrentTimeZoneId : (%ld)\n", sti.uCurrentTimeZoneId);
}
static void test_query_process(void)
{
DWORD status;
DWORD last_pid;
ULONG ReturnLength;
int i = 0, j = 0, k = 0;
int is_nt = 0;
SYSTEM_BASIC_INFORMATION sbi;
/* Copy of our winternl.h structure turned into a private one */
typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE {
DWORD dwOffset;
DWORD dwThreadCount;
DWORD dwUnknown1[6];
FILETIME ftCreationTime;
FILETIME ftUserTime;
FILETIME ftKernelTime;
UNICODE_STRING ProcessName;
DWORD dwBasePriority;
DWORD dwProcessID;
DWORD dwParentProcessID;
DWORD dwHandleCount;
DWORD dwUnknown3;
DWORD dwUnknown4;
VM_COUNTERS vmCounters;
IO_COUNTERS ioCounters;
SYSTEM_THREAD_INFORMATION ti[1];
} SYSTEM_PROCESS_INFORMATION_PRIVATE, *PSYSTEM_PROCESS_INFORMATION_PRIVATE;
ULONG SystemInformationLength = sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE);
SYSTEM_PROCESS_INFORMATION_PRIVATE* spi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
/* Only W2K3 returns the needed length, the rest returns 0, so we have to loop */
for (;;)
{
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);
/* Get the first dwOffset, from this we can deduce the OS version we're running
*
* W2K/WinXP/W2K3:
* dwOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
* NT:
* dwOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
* Wine (with every windows version):
* dwOffset for a process is 0 if just this test is running
* dwOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) +
* ProcessName.MaximumLength
* if more wine processes are running
*
* Note : On windows the first process is in fact the Idle 'process' with a thread for every processor
*/
pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
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");
/* 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 (;;)
{
i++;
last_pid = spi->dwProcessID;
ok( spi->dwThreadCount > 0, "Expected some threads for this process, got 0\n");
/* Loop through the threads, skip NT4 for now */
if (!is_nt)
{
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",
spi->ti[j].dwOwningPID, spi->dwProcessID);
}
}
if (!spi->dwOffset) break;
one_before_last_pid = last_pid;
spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->dwOffset);
}
trace("Total number of running processes : %d\n", i);
if (!is_nt) trace("Total number of running threads : %d\n", k);
if (one_before_last_pid == 0) one_before_last_pid = last_pid;
HeapFree( GetProcessHeap(), 0, spi);
}
static void test_query_procperf(void)
{
DWORD status;
ULONG ReturnLength;
ULONG NeededLength;
SYSTEM_BASIC_INFORMATION sbi;
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
/* Find out the number of processors */
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
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);
/* 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( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
"Inconsistent length (%d) <-> (%ld)\n", sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), 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);
/* 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);
HeapFree( GetProcessHeap(), 0, sppi);
}
static void test_query_module(void)
{
DWORD status;
ULONG ReturnLength;
DWORD ModuleCount;
int i;
ULONG SystemInformationLength = sizeof(SYSTEM_MODULE_INFORMATION);
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( 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);
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");
}
/* 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 %d\n", sm->Id, i);
sm++;
}
HeapFree( GetProcessHeap(), 0, smi);
}
static void test_query_handle(void)
{
DWORD status;
ULONG ReturnLength;
ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
/* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
/* 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( ReturnLength > 0, "Expected ReturnLength to be > 0, it was %ld\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);
/* Check if we have some return values */
trace("Number of Handles : %ld\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);
}
HeapFree( GetProcessHeap(), 0, shi);
}
static void test_query_cache(void)
{
DWORD status;
ULONG ReturnLength;
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);
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);
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);
}
static void test_query_interrupt(void)
{
DWORD status;
ULONG ReturnLength;
ULONG NeededLength;
SYSTEM_BASIC_INFORMATION sbi;
SYSTEM_INTERRUPT_INFORMATION* sii;
/* Find out the number of processors */
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
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);
/* Try it for all processors */
status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\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
*/
HeapFree( GetProcessHeap(), 0, sii);
}
static void test_query_kerndebug(void)
{
DWORD status;
ULONG ReturnLength;
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);
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);
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);
}
static void test_query_regquota(void)
{
DWORD status;
ULONG ReturnLength;
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);
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);
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);
}
static void test_query_process_basic(void)
{
DWORD status;
ULONG ReturnLength;
typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE {
DWORD ExitStatus;
DWORD PebBaseAddress;
DWORD AffinityMask;
DWORD BasePriority;
ULONG UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION_PRIVATE, *PPROCESS_BASIC_INFORMATION_PRIVATE;
PROCESS_BASIC_INFORMATION_PRIVATE pbi;
/* 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 = pNtQueryInformationProcess(NULL, -1, NULL, 0, NULL);
ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08lx\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);
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
/* Check if we have some return values */
trace("ProcessID : %ld\n", pbi.UniqueProcessId);
ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
}
static void test_query_process_vm(void)
{
DWORD status;
ULONG ReturnLength;
VM_COUNTERS pvi;
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);
status = pNtQueryInformationProcess(NULL, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
/* Windows XP and W2K3 will report success for a size of 44 AND 48 !
Windows W2K will only report success for 44.
For now we only care for 44, which is sizeof(VM_COUNTERS)
If an app depends on it, we have to implement this in ntdll/process.c
*/
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 24, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\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);
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);
/* Check if we have some return values */
trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
todo_wine
{
ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
}
}
static void test_query_process_io(void)
{
DWORD status;
ULONG ReturnLength;
IO_COUNTERS pii;
/* NT4 doesn't support this information class, so check for it */
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
if (status == STATUS_NOT_SUPPORTED)
{
trace("ProcessIoCounters information class not supported, skipping tests\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);
status = pNtQueryInformationProcess(NULL, ProcessIoCounters, &pii, sizeof(pii), NULL);
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, 24, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\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);
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);
/* Check if we have some return values */
trace("OtherOperationCount : %lld\n", pii.OtherOperationCount);
todo_wine
{
ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
}
}
static void test_query_process_times(void)
{
DWORD status;
ULONG ReturnLength;
HANDLE process;
SYSTEMTIME UTC, Local;
KERNEL_USER_TIMES spti;
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);
status = pNtQueryInformationProcess(NULL, ProcessTimes, &spti, sizeof(spti), NULL);
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, 24, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\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());
process = GetCurrentProcess();
trace("ProcessTimes for current process\n");
}
else
trace("ProcessTimes for process with ID : %ld\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);
CloseHandle(process);
FileTimeToSystemTime((const FILETIME *)&spti.CreateTime, &UTC);
SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
Local.wHour, Local.wMinute, Local.wSecond);
FileTimeToSystemTime((const FILETIME *)&spti.ExitTime, &UTC);
SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
trace("ExitTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
Local.wHour, Local.wMinute, Local.wSecond);
FileTimeToSystemTime((const FILETIME *)&spti.KernelTime, &Local);
trace("KernelTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
FileTimeToSystemTime((const FILETIME *)&spti.UserTime, &Local);
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);
}
static void test_query_process_handlecount(void)
{
DWORD status;
ULONG ReturnLength;
DWORD handlecount;
HANDLE process;
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);
status = pNtQueryInformationProcess(NULL, ProcessHandleCount, &handlecount, sizeof(handlecount), NULL);
ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, 2, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
trace("Handlecount for process with ID : %ld\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);
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);
/* Check if we have some return values */
trace("HandleCount : %ld\n", handlecount);
todo_wine
{
ok( handlecount > 0, "Expected some handles, got 0\n");
}
}
START_TEST(info)
{
if(!InitFunctionPtrs())
return;
/* NtQuerySystemInformation */
/* 0x0 SystemBasicInformation */
trace("Starting test_query_basic()\n");
test_query_basic();
/* 0x1 SystemCpuInformation */
trace("Starting test_query_cpu()\n");
test_query_cpu();
/* 0x2 SystemPerformanceInformation */
trace("Starting test_query_performance()\n");
test_query_performance();
/* 0x3 SystemTimeOfDayInformation */
trace("Starting test_query_timeofday()\n");
test_query_timeofday();
/* 0x5 SystemProcessInformation */
trace("Starting test_query_process()\n");
test_query_process();
/* 0x8 SystemProcessorPerformanceInformation */
trace("Starting test_query_procperf()\n");
test_query_procperf();
/* 0xb SystemModuleInformation */
trace("Starting test_query_module()\n");
test_query_module();
/* 0x10 SystemHandleInformation */
trace("Starting test_query_handle()\n");
test_query_handle();
/* 0x15 SystemCacheInformation */
trace("Starting test_query_cache()\n");
test_query_cache();
/* 0x17 SystemInterruptInformation */
trace("Starting test_query_interrupt()\n");
test_query_interrupt();
/* 0x23 SystemKernelDebuggerInformation */
trace("Starting test_query_kerndebug()\n");
test_query_kerndebug();
/* 0x25 SystemRegistryQuotaInformation */
trace("Starting test_query_regquota()\n");
test_query_regquota();
/* NtQueryInformationProcess */
/* 0x0 ProcessBasicInformation */
trace("Starting test_query_process_basic()\n");
test_query_process_basic();
/* 0x2 ProcessIoCounters */
trace("Starting test_query_process_io()\n");
test_query_process_io();
/* 0x3 ProcessVmCounters */
trace("Starting test_query_process_vm()\n");
test_query_process_vm();
/* 0x4 ProcessTimes */
trace("Starting test_query_process_times()\n");
test_query_process_times();
/* 0x14 ProcessHandleCount */
trace("Starting test_query_process_handlecount()\n");
test_query_process_handlecount();
FreeLibrary(hntdll);
}

View file

@ -0,0 +1,423 @@
/* Unit test suite for Rtl large integer functions
*
* Copyright 2003 Thomas Mertes
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* We use function pointers here as there is no import library for NTDLL on
* windows.
*/
#include <stdlib.h>
#include "ntdll_test.h"
/* Function ptrs for ntdll calls */
static HMODULE hntdll = 0;
static LONGLONG (WINAPI *pRtlExtendedMagicDivide)(LONGLONG, LONGLONG, INT);
static VOID (WINAPI *pRtlFreeAnsiString)(PSTRING);
static NTSTATUS (WINAPI *pRtlInt64ToUnicodeString)(ULONGLONG, ULONG, UNICODE_STRING *);
static NTSTATUS (WINAPI *pRtlLargeIntegerToChar)(ULONGLONG *, ULONG, ULONG, PCHAR);
static NTSTATUS (WINAPI *pRtlUnicodeStringToAnsiString)(STRING *, const UNICODE_STRING *, BOOLEAN);
static void InitFunctionPtrs(void)
{
hntdll = LoadLibraryA("ntdll.dll");
ok(hntdll != 0, "LoadLibrary failed\n");
if (hntdll) {
pRtlExtendedMagicDivide = (void *)GetProcAddress(hntdll, "RtlExtendedMagicDivide");
pRtlFreeAnsiString = (void *)GetProcAddress(hntdll, "RtlFreeAnsiString");
pRtlInt64ToUnicodeString = (void *)GetProcAddress(hntdll, "RtlInt64ToUnicodeString");
pRtlLargeIntegerToChar = (void *)GetProcAddress(hntdll, "RtlLargeIntegerToChar");
pRtlUnicodeStringToAnsiString = (void *)GetProcAddress(hntdll, "RtlUnicodeStringToAnsiString");
} /* if */
}
#define ULL(a,b) (((ULONGLONG)(a) << 32) | (b))
typedef struct {
LONGLONG a;
LONGLONG b;
INT shift;
LONGLONG result;
} magic_divide_t;
static const magic_divide_t magic_divide[] = {
{ 3, ULL(0x55555555,0x55555555), 0, 0}, /* 1 */
{ 333333333, ULL(0x55555555,0x55555555), 0, 111111110}, /* 111111111 */
{ ULL(0x7fffffff,0xffffffff), ULL(0x55555555,0x55555555), 0, ULL(0x2aaaaaaa,0xaaaaaaaa)},
{ 3, ULL(0xaaaaaaaa,0xaaaaaaaa), 1, 0}, /* 1 */
{ 333333333, ULL(0xaaaaaaaa,0xaaaaaaaa), 1, 111111110}, /* 111111111 */
{ ULL(0x7fffffff,0xffffffff), ULL(0xaaaaaaaa,0xaaaaaaaa), 1, ULL(0x2aaaaaaa,0xaaaaaaaa)},
{ -3, ULL(0x55555555,0x55555555), 0, 0}, /* -1 */
{ -333333333, ULL(0x55555555,0x55555555), 0, -111111110}, /* -111111111 */
{-ULL(0x7fffffff,0xffffffff), ULL(0x55555555,0x55555555), 0, -ULL(0x2aaaaaaa,0xaaaaaaaa)},
{ -3, ULL(0xaaaaaaaa,0xaaaaaaaa), 1, 0}, /* -1 */
{ -333333333, ULL(0xaaaaaaaa,0xaaaaaaaa), 1, -111111110}, /* -111111111 */
{-ULL(0x7fffffff,0xffffffff), ULL(0xaaaaaaaa,0xaaaaaaaa), 1, -ULL(0x2aaaaaaa,0xaaaaaaaa)},
{ -3, -ULL(0x55555555,0x55555555), 0, -2}, /* -1 */
{ -333333333, -ULL(0x55555555,0x55555555), 0, -222222222}, /* -111111111 */
{-ULL(0x7fffffff,0xffffffff), -ULL(0x55555555,0x55555555), 0, -ULL(0x55555555,0x55555554)},
{ -3, -ULL(0xaaaaaaaa,0xaaaaaaaa), 1, 0}, /* -1 */
{ -333333333, -ULL(0xaaaaaaaa,0xaaaaaaaa), 1, -55555555}, /* -111111111 */
{-ULL(0x7fffffff,0xffffffff), -ULL(0xaaaaaaaa,0xaaaaaaaa), 1, -ULL(0x15555555,0x55555555)},
{ 3, -ULL(0x55555555,0x55555555), 0, 2}, /* -1 */
{ 333333333, -ULL(0x55555555,0x55555555), 0, 222222222}, /* -111111111 */
{ ULL(0x7fffffff,0xffffffff), -ULL(0x55555555,0x55555555), 0, ULL(0x55555555,0x55555554)},
{ 3, -ULL(0xaaaaaaaa,0xaaaaaaaa), 1, 0}, /* -1 */
{ 333333333, -ULL(0xaaaaaaaa,0xaaaaaaaa), 1, 55555555}, /* -111111111 */
{ ULL(0x7fffffff,0xffffffff), -ULL(0xaaaaaaaa,0xaaaaaaaa), 1, ULL(0x15555555,0x55555555)},
{ 3, ULL(0xaaaaaaaa,0xaaaaa800), 1, 0}, /* 1 */
{ 333333333, ULL(0xaaaaaaaa,0xaaaaa800), 1, 111111110}, /* 111111111 */
{ ULL(0x7fffffff,0xffffffff), ULL(0xaaaaaaaa,0xaaaaa800), 1, ULL(0x2aaaaaaa,0xaaaaa9ff)}, /* 0x2aaaaaaaaaaaaaaa */
{ 5, ULL(0x33333333,0x333333ff), 0, 1},
{ 555555555, ULL(0x33333333,0x333333ff), 0, 111111111},
{ ULL(0x7fffffff,0xffffffff), ULL(0x33333333,0x333333ff), 0, ULL(0x19999999,0x999999ff)}, /* 0x199999999999999a */
{ 5, ULL(0x66666666,0x666667fe), 1, 1},
{ 555555555, ULL(0x66666666,0x666667fe), 1, 111111111},
{ ULL(0x7fffffff,0xffffffff), ULL(0x66666666,0x666667fe), 1, ULL(0x19999999,0x999999ff)}, /* 0x199999999999999a */
{ 5, ULL(0xcccccccc,0xcccccffd), 2, 1},
{ 555555555, ULL(0xcccccccc,0xcccccffd), 2, 111111111},
{ ULL(0x7fffffff,0xffffffff), ULL(0xcccccccc,0xcccccffd), 2, ULL(0x19999999,0x999999ff)}, /* 0x199999999999999a */
{ ULL(0x00000add,0xcafeface), ULL(0x002f1e28,0xfd1b5cca), 33, 1},
{ ULL(0x081ac1b9,0xc2310a80), ULL(0x002f1e28,0xfd1b5cca), 33, 0xbeef},
{ ULL(0x74ae3b5f,0x1558c800), ULL(0x002f1e28,0xfd1b5cca), 33, 0xabcde},
{ ULL(0x00000add,0xcafeface), ULL(0x2f1e28fd,0x1b5cca00), 41, 1},
{ ULL(0x081ac1b9,0xc2310a80), ULL(0x2f1e28fd,0x1b5cca00), 41, 0xbeef},
{ ULL(0x74ae3b5f,0x1558c800), ULL(0x2f1e28fd,0x1b5cca00), 41, 0xabcde},
};
#define NB_MAGIC_DIVIDE (sizeof(magic_divide)/sizeof(*magic_divide))
static void test_RtlExtendedMagicDivide(void)
{
int i;
LONGLONG result;
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);
}
}
#define LARGE_STRI_BUFFER_LENGTH 67
typedef struct {
int base;
ULONGLONG value;
USHORT Length;
USHORT MaximumLength;
const char *Buffer;
NTSTATUS result;
} largeint2str_t;
/*
* The native DLL does produce garbage or STATUS_BUFFER_OVERFLOW for
* base 2, 8 and 16 when the value is larger than 0xFFFFFFFF.
* Therefore these testcases are commented out.
*/
static const largeint2str_t largeint2str[] = {
{10, 123, 3, 11, "123\0---------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 0x80000000U, 10, 11, "2147483648\0--------------------------------------------------------", STATUS_SUCCESS},
{ 0, -2147483647, 20, 21, "18446744071562067969\0----------------------------------------------", STATUS_SUCCESS},
{ 0, -2, 20, 21, "18446744073709551614\0----------------------------------------------", STATUS_SUCCESS},
{ 0, -1, 20, 21, "18446744073709551615\0----------------------------------------------", STATUS_SUCCESS},
{ 0, 0, 1, 11, "0\0-----------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 1, 1, 11, "1\0-----------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 12, 2, 11, "12\0----------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 123, 3, 11, "123\0---------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 1234, 4, 11, "1234\0--------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 12345, 5, 11, "12345\0-------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 123456, 6, 11, "123456\0------------------------------------------------------------", STATUS_SUCCESS},
{ 0, 1234567, 7, 11, "1234567\0-----------------------------------------------------------", STATUS_SUCCESS},
{ 0, 12345678, 8, 11, "12345678\0----------------------------------------------------------", STATUS_SUCCESS},
{ 0, 123456789, 9, 11, "123456789\0---------------------------------------------------------", STATUS_SUCCESS},
{ 0, 2147483646, 10, 11, "2147483646\0--------------------------------------------------------", STATUS_SUCCESS},
{ 0, 2147483647, 10, 11, "2147483647\0--------------------------------------------------------", STATUS_SUCCESS},
{ 0, 2147483648U, 10, 11, "2147483648\0--------------------------------------------------------", STATUS_SUCCESS},
{ 0, 2147483649U, 10, 11, "2147483649\0--------------------------------------------------------", STATUS_SUCCESS},
{ 0, 4294967294U, 10, 11, "4294967294\0--------------------------------------------------------", STATUS_SUCCESS},
{ 0, 4294967295U, 10, 11, "4294967295\0--------------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0x2,0xdfdc1c35), 11, 12, "12345678901\0-------------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0xe5,0xf4c8f374), 12, 13, "987654321012\0------------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0x1c0,0xfc161e3e), 13, 14, "1928374656574\0-----------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0xbad,0xcafeface), 14, 15, "12841062955726\0----------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0x5bad,0xcafeface), 15, 16, "100801993177806\0---------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0xaface,0xbeefcafe), 16, 20, "3090515640699646\0--------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0xa5beef,0xabcdcafe), 17, 20, "46653307746110206\0-------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0x1f8cf9b,0xf2df3af1), 18, 20, "142091656963767025\0------------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0x0fffffff,0xffffffff), 19, 20, "1152921504606846975\0-----------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0xffffffff,0xfffffffe), 20, 21, "18446744073709551614\0----------------------------------------------", STATUS_SUCCESS},
{ 0, ULL(0xffffffff,0xffffffff), 20, 21, "18446744073709551615\0----------------------------------------------", STATUS_SUCCESS},
{ 2, 0x80000000U, 32, 33, "10000000000000000000000000000000\0----------------------------------", STATUS_SUCCESS},
/*
* { 2, -2147483647, 64, 65, "1111111111111111111111111111111110000000000000000000000000000001\0--", STATUS_SUCCESS},
* { 2, -2, 64, 65, "1111111111111111111111111111111111111111111111111111111111111110\0--", STATUS_SUCCESS},
* { 2, -1, 64, 65, "1111111111111111111111111111111111111111111111111111111111111111\0--", STATUS_SUCCESS},
*/
{ 2, 0, 1, 33, "0\0-----------------------------------------------------------------", STATUS_SUCCESS},
{ 2, 1, 1, 33, "1\0-----------------------------------------------------------------", STATUS_SUCCESS},
{ 2, 10, 4, 33, "1010\0--------------------------------------------------------------", STATUS_SUCCESS},
{ 2, 100, 7, 33, "1100100\0-----------------------------------------------------------", STATUS_SUCCESS},
{ 2, 1000, 10, 33, "1111101000\0--------------------------------------------------------", STATUS_SUCCESS},
{ 2, 10000, 14, 33, "10011100010000\0----------------------------------------------------", STATUS_SUCCESS},
{ 2, 32767, 15, 33, "111111111111111\0---------------------------------------------------", STATUS_SUCCESS},
{ 2, 32768, 16, 33, "1000000000000000\0--------------------------------------------------", STATUS_SUCCESS},
{ 2, 65535, 16, 33, "1111111111111111\0--------------------------------------------------", STATUS_SUCCESS},
{ 2, 100000, 17, 33, "11000011010100000\0-------------------------------------------------", STATUS_SUCCESS},
{ 2, 1000000, 20, 33, "11110100001001000000\0----------------------------------------------", STATUS_SUCCESS},
{ 2, 10000000, 24, 33, "100110001001011010000000\0------------------------------------------", STATUS_SUCCESS},
{ 2, 100000000, 27, 33, "101111101011110000100000000\0---------------------------------------", STATUS_SUCCESS},
{ 2, 1000000000, 30, 33, "111011100110101100101000000000\0------------------------------------", STATUS_SUCCESS},
{ 2, 1073741823, 30, 33, "111111111111111111111111111111\0------------------------------------", STATUS_SUCCESS},
{ 2, 2147483646, 31, 33, "1111111111111111111111111111110\0-----------------------------------", STATUS_SUCCESS},
{ 2, 2147483647, 31, 33, "1111111111111111111111111111111\0-----------------------------------", STATUS_SUCCESS},
{ 2, 2147483648U, 32, 33, "10000000000000000000000000000000\0----------------------------------", STATUS_SUCCESS},
{ 2, 2147483649U, 32, 33, "10000000000000000000000000000001\0----------------------------------", STATUS_SUCCESS},
{ 2, 4294967294U, 32, 33, "11111111111111111111111111111110\0----------------------------------", STATUS_SUCCESS},
{ 2, 0xFFFFFFFF, 32, 33, "11111111111111111111111111111111\0----------------------------------", STATUS_SUCCESS},
/*
* { 2, 0x1FFFFFFFF, 33, 34, "111111111111111111111111111111111\0---------------------------------", STATUS_SUCCESS},
* { 2, 0x3FFFFFFFF, 34, 35, "1111111111111111111111111111111111\0--------------------------------", STATUS_SUCCESS},
* { 2, 0x7FFFFFFFF, 35, 36, "11111111111111111111111111111111111\0-------------------------------", STATUS_SUCCESS},
* { 2, 0xFFFFFFFFF, 36, 37, "111111111111111111111111111111111111\0------------------------------", STATUS_SUCCESS},
* { 2, 0x1FFFFFFFFF, 37, 38, "1111111111111111111111111111111111111\0-----------------------------", STATUS_SUCCESS},
* { 2, 0x3FFFFFFFFF, 38, 39, "11111111111111111111111111111111111111\0----------------------------", STATUS_SUCCESS},
* { 2, 0x7FFFFFFFFF, 39, 40, "111111111111111111111111111111111111111\0---------------------------", STATUS_SUCCESS},
* { 2, 0xFFFFFFFFFF, 40, 41, "1111111111111111111111111111111111111111\0--------------------------", STATUS_SUCCESS},
*/
{ 8, 0x80000000U, 11, 12, "20000000000\0-------------------------------------------------------", STATUS_SUCCESS},
/*
* { 8, -2147483647, 22, 23, "1777777777760000000001\0--------------------------------------------", STATUS_SUCCESS},
* { 8, -2, 22, 23, "1777777777777777777776\0--------------------------------------------", STATUS_SUCCESS},
* { 8, -1, 22, 23, "1777777777777777777777\0--------------------------------------------", STATUS_SUCCESS},
*/
{ 8, 0, 1, 12, "0\0-----------------------------------------------------------------", STATUS_SUCCESS},
{ 8, 1, 1, 12, "1\0-----------------------------------------------------------------", STATUS_SUCCESS},
{ 8, 2147483646, 11, 12, "17777777776\0-------------------------------------------------------", STATUS_SUCCESS},
{ 8, 2147483647, 11, 12, "17777777777\0-------------------------------------------------------", STATUS_SUCCESS},
{ 8, 2147483648U, 11, 12, "20000000000\0-------------------------------------------------------", STATUS_SUCCESS},
{ 8, 2147483649U, 11, 12, "20000000001\0-------------------------------------------------------", STATUS_SUCCESS},
{ 8, 4294967294U, 11, 12, "37777777776\0-------------------------------------------------------", STATUS_SUCCESS},
{ 8, 4294967295U, 11, 12, "37777777777\0-------------------------------------------------------", STATUS_SUCCESS},
{10, 0x80000000U, 10, 11, "2147483648\0--------------------------------------------------------", STATUS_SUCCESS},
{10, -2147483647, 20, 21, "18446744071562067969\0----------------------------------------------", STATUS_SUCCESS},
{10, -2, 20, 21, "18446744073709551614\0----------------------------------------------", STATUS_SUCCESS},
{10, -1, 20, 21, "18446744073709551615\0----------------------------------------------", STATUS_SUCCESS},
{10, 0, 1, 11, "0\0-----------------------------------------------------------------", STATUS_SUCCESS},
{10, 1, 1, 11, "1\0-----------------------------------------------------------------", STATUS_SUCCESS},
{10, 2147483646, 10, 11, "2147483646\0--------------------------------------------------------", STATUS_SUCCESS},
{10, 2147483647, 10, 11, "2147483647\0--------------------------------------------------------", STATUS_SUCCESS},
{10, 2147483648U, 10, 11, "2147483648\0--------------------------------------------------------", STATUS_SUCCESS},
{10, 2147483649U, 10, 11, "2147483649\0--------------------------------------------------------", STATUS_SUCCESS},
{10, 4294967294U, 10, 11, "4294967294\0--------------------------------------------------------", STATUS_SUCCESS},
{10, 4294967295U, 10, 11, "4294967295\0--------------------------------------------------------", STATUS_SUCCESS},
{16, 0, 1, 9, "0\0-----------------------------------------------------------------", STATUS_SUCCESS},
{16, 1, 1, 9, "1\0-----------------------------------------------------------------", STATUS_SUCCESS},
{16, 2147483646, 8, 9, "7FFFFFFE\0----------------------------------------------------------", STATUS_SUCCESS},
{16, 2147483647, 8, 9, "7FFFFFFF\0----------------------------------------------------------", STATUS_SUCCESS},
{16, 0x80000000, 8, 9, "80000000\0----------------------------------------------------------", STATUS_SUCCESS},
{16, 0x80000001, 8, 9, "80000001\0----------------------------------------------------------", STATUS_SUCCESS},
{16, 0xFFFFFFFE, 8, 9, "FFFFFFFE\0----------------------------------------------------------", STATUS_SUCCESS},
{16, 0xFFFFFFFF, 8, 9, "FFFFFFFF\0----------------------------------------------------------", STATUS_SUCCESS},
/*
* {16, 0x100000000, 9, 10, "100000000\0---------------------------------------------------------", STATUS_SUCCESS},
* {16, 0xBADDEADBEEF, 11, 12, "BADDEADBEEF\0-------------------------------------------------------", STATUS_SUCCESS},
* {16, 0x8000000000000000, 16, 17, "8000000000000000\0--------------------------------------------------", STATUS_SUCCESS},
* {16, 0xFEDCBA9876543210, 16, 17, "FEDCBA9876543210\0--------------------------------------------------", STATUS_SUCCESS},
* {16, 0xFFFFFFFF80000001, 16, 17, "FFFFFFFF80000001\0--------------------------------------------------", STATUS_SUCCESS},
* {16, 0xFFFFFFFFFFFFFFFE, 16, 17, "FFFFFFFFFFFFFFFE\0--------------------------------------------------", STATUS_SUCCESS},
* {16, 0xFFFFFFFFFFFFFFFF, 16, 17, "FFFFFFFFFFFFFFFF\0--------------------------------------------------", STATUS_SUCCESS},
*/
{ 2, 32768, 16, 17, "1000000000000000\0--------------------------------------------------", STATUS_SUCCESS},
{ 2, 32768, 16, 16, "1000000000000000---------------------------------------------------", STATUS_SUCCESS},
{ 2, 65536, 17, 18, "10000000000000000\0-------------------------------------------------", STATUS_SUCCESS},
{ 2, 65536, 17, 17, "10000000000000000--------------------------------------------------", STATUS_SUCCESS},
{ 2, 131072, 18, 19, "100000000000000000\0------------------------------------------------", STATUS_SUCCESS},
{ 2, 131072, 18, 18, "100000000000000000-------------------------------------------------", STATUS_SUCCESS},
{16, 0xffffffff, 8, 9, "FFFFFFFF\0----------------------------------------------------------", STATUS_SUCCESS},
{16, 0xffffffff, 8, 8, "FFFFFFFF-----------------------------------------------------------", STATUS_SUCCESS},
{16, 0xffffffff, 8, 7, "-------------------------------------------------------------------", STATUS_BUFFER_OVERFLOW},
{16, 0xa, 1, 2, "A\0-----------------------------------------------------------------", STATUS_SUCCESS},
{16, 0xa, 1, 1, "A------------------------------------------------------------------", STATUS_SUCCESS},
{16, 0, 1, 0, "-------------------------------------------------------------------", STATUS_BUFFER_OVERFLOW},
{20, 0xdeadbeef, 0, 9, "-------------------------------------------------------------------", STATUS_INVALID_PARAMETER},
{-8, 07654321, 0, 12, "-------------------------------------------------------------------", STATUS_INVALID_PARAMETER},
};
#define NB_LARGEINT2STR (sizeof(largeint2str)/sizeof(*largeint2str))
static void one_RtlInt64ToUnicodeString_test(int test_num, const largeint2str_t *largeint2str)
{
int pos;
WCHAR expected_str_Buffer[LARGE_STRI_BUFFER_LENGTH + 1];
UNICODE_STRING expected_unicode_string;
STRING expected_ansi_str;
WCHAR str_Buffer[LARGE_STRI_BUFFER_LENGTH + 1];
UNICODE_STRING unicode_string;
STRING ansi_str;
NTSTATUS result;
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
expected_str_Buffer[pos] = largeint2str->Buffer[pos];
} /* for */
expected_unicode_string.Length = largeint2str->Length * sizeof(WCHAR);
expected_unicode_string.MaximumLength = largeint2str->MaximumLength * sizeof(WCHAR);
expected_unicode_string.Buffer = expected_str_Buffer;
pRtlUnicodeStringToAnsiString(&expected_ansi_str, &expected_unicode_string, 1);
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
str_Buffer[pos] = '-';
} /* for */
unicode_string.Length = 0;
unicode_string.MaximumLength = largeint2str->MaximumLength * sizeof(WCHAR);
unicode_string.Buffer = str_Buffer;
if (largeint2str->base == 0) {
result = pRtlInt64ToUnicodeString(largeint2str->value, 10, &unicode_string);
} else {
result = pRtlInt64ToUnicodeString(largeint2str->value, largeint2str->base, &unicode_string);
} /* if */
pRtlUnicodeStringToAnsiString(&ansi_str, &unicode_string, 1);
if (result == STATUS_BUFFER_OVERFLOW) {
/* On BUFFER_OVERFLOW the string Buffer should be unchanged */
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
expected_str_Buffer[pos] = '-';
} /* for */
/* w2k: The native function has two reasons for BUFFER_OVERFLOW: */
/* If the value is too large to convert: The Length is unchanged */
/* If str is too small to hold the string: Set str->Length to the length */
/* the string would have (which can be larger than the MaximumLength). */
/* To allow all this in the tests we do the following: */
if (expected_unicode_string.Length >= 64) {
/* The value is too large to convert only triggerd when testing native */
/* Length is not filled with the expected string length (garbage?) */
expected_unicode_string.Length = unicode_string.Length;
} /* 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);
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);
} /* 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);
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);
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);
pRtlFreeAnsiString(&expected_ansi_str);
pRtlFreeAnsiString(&ansi_str);
}
static void test_RtlInt64ToUnicodeString(void)
{
int test_num;
for (test_num = 0; test_num < NB_LARGEINT2STR; test_num++) {
one_RtlInt64ToUnicodeString_test(test_num, &largeint2str[test_num]);
} /* for */
}
static void one_RtlLargeIntegerToChar_test(int test_num, const largeint2str_t *largeint2str)
{
NTSTATUS result;
char dest_str[LARGE_STRI_BUFFER_LENGTH + 1];
ULONGLONG value;
memset(dest_str, '-', LARGE_STRI_BUFFER_LENGTH);
dest_str[LARGE_STRI_BUFFER_LENGTH] = '\0';
value = largeint2str->value;
if (largeint2str->base == 0) {
result = pRtlLargeIntegerToChar(&value, 10, largeint2str->MaximumLength, dest_str);
} else {
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);
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);
}
static void test_RtlLargeIntegerToChar(void)
{
NTSTATUS result;
int test_num;
ULONGLONG value;
for (test_num = 0; test_num < NB_LARGEINT2STR; test_num++) {
one_RtlLargeIntegerToChar_test(test_num, &largeint2str[test_num]);
} /* for */
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: %x\n",
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: %x\n",
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: %x\n",
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: %x\n",
largeint2str[0].value, largeint2str[0].base, largeint2str[0].MaximumLength, result, STATUS_ACCESS_VIOLATION);
}
START_TEST(large_int)
{
InitFunctionPtrs();
if (pRtlExtendedMagicDivide)
test_RtlExtendedMagicDivide();
if (pRtlInt64ToUnicodeString)
test_RtlInt64ToUnicodeString();
if (pRtlLargeIntegerToChar)
test_RtlLargeIntegerToChar();
}

View file

@ -0,0 +1,35 @@
/*
* Unit test suite for ntdll path functions
*
* Copyright 2003 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x500 /* For NTSTATUS */
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winnt.h"
#include "winreg.h"
#include "winternl.h"
#include "wine/test.h"

View file

@ -0,0 +1,18 @@
<module name="ntdll_test" type="win32cui" installbase="bin" installname="ntdll_test.exe" warnings="true">
<include base="ntdll_test">.</include>
<define name="__USE_W32API" />
<library>ntdll</library>
<file>atom.c</file>
<file>env.c</file>
<file>error.c</file>
<file>info.c</file>
<file>large_int.c</file>
<file>path.c</file>
<file>reg.c</file>
<file>rtlbitmap.c</file>
<file>rtl.c</file>
<file>rtlstr.c</file>
<file>string.c</file>
<file>time.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,304 @@
/*
* Unit test suite for ntdll path functions
*
* Copyright 2002 Alexandre Julliard
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ntdll_test.h"
static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
LPCSTR src, DWORD srclen );
static NTSTATUS (WINAPI *pRtlUnicodeToMultiByteN)(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
static UINT (WINAPI *pRtlDetermineDosPathNameType_U)( PCWSTR path );
static ULONG (WINAPI *pRtlIsDosDeviceName_U)( PCWSTR dos_name );
static NTSTATUS (WINAPI *pRtlOemStringToUnicodeString)(UNICODE_STRING *, const STRING *, BOOLEAN );
static BOOLEAN (WINAPI *pRtlIsNameLegalDOS8Dot3)(const UNICODE_STRING*,POEM_STRING,PBOOLEAN);
static DWORD (WINAPI *pRtlGetFullPathName_U)(const WCHAR*,ULONG,WCHAR*,WCHAR**);
static void test_RtlDetermineDosPathNameType(void)
{
struct test
{
const char *path;
UINT ret;
};
static const struct test tests[] =
{
{ "\\\\foo", 1 },
{ "//foo", 1 },
{ "\\/foo", 1 },
{ "/\\foo", 1 },
{ "\\\\", 1 },
{ "//", 1 },
{ "c:\\foo", 2 },
{ "c:/foo", 2 },
{ "c://foo", 2 },
{ "c:\\", 2 },
{ "c:/", 2 },
{ "c:foo", 3 },
{ "c:f\\oo", 3 },
{ "c:foo/bar", 3 },
{ "\\foo", 4 },
{ "/foo", 4 },
{ "\\", 4 },
{ "/", 4 },
{ "foo", 5 },
{ "", 5 },
{ "\0:foo", 5 },
{ "\\\\.\\foo", 6 },
{ "//./foo", 6 },
{ "/\\./foo", 6 },
{ "\\\\.foo", 1 },
{ "//.foo", 1 },
{ "\\\\.", 7 },
{ "//.", 7 },
{ NULL, 0 }
};
const struct test *test;
WCHAR buffer[MAX_PATH];
UINT ret;
for (test = tests; test->path; test++)
{
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
ret = pRtlDetermineDosPathNameType_U( buffer );
ok( ret == test->ret, "Wrong result %d/%d for %s\n", ret, test->ret, test->path );
}
}
static void test_RtlIsDosDeviceName(void)
{
struct test
{
const char *path;
WORD pos;
WORD len;
};
static const struct test tests[] =
{
{ "\\\\.\\CON", 8, 6 },
{ "\\\\.\\con", 8, 6 },
{ "\\\\.\\CON2", 0, 0 },
{ "", 0, 0 },
{ "\\\\foo\\nul", 0, 0 },
{ "c:\\nul:", 6, 6 },
{ "c:\\nul::", 0, 0 },
{ "c:prn ", 4, 6 },
{ "c:prn.......", 4, 6 },
{ "c:prn... ...", 4, 6 },
{ "c:NUL .... ", 0, 0 },
{ "c: . . .", 0, 0 },
{ "c:", 0, 0 },
{ " . . . :", 0, 0 },
{ ":", 0, 0 },
{ "c:nul. . . :", 4, 6 },
{ "c:nul . . :", 0, 0 },
{ "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 },
{ "CoM4:", 0, 8 },
{ "lpt9:", 0, 8 },
{ "c:\\lpt0.txt", 0, 0 },
{ "c:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\nul.txt", 1000, 6 },
{ NULL, 0 }
};
const struct test *test;
WCHAR buffer[2000];
ULONG ret;
for (test = tests; test->path; test++)
{
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
ret = pRtlIsDosDeviceName_U( buffer );
ok( ret == MAKELONG( test->len, test->pos ),
"Wrong result (%d,%d)/(%d,%d) for %s\n",
HIWORD(ret), LOWORD(ret), test->pos, test->len, test->path );
}
}
static void test_RtlIsNameLegalDOS8Dot3(void)
{
struct test
{
const char *path;
BOOLEAN result;
BOOLEAN spaces;
};
static const struct test tests[] =
{
{ "12345678", TRUE, FALSE },
{ "123 5678", TRUE, TRUE },
{ "12345678.", FALSE, 2 /*not set*/ },
{ "1234 678.", FALSE, 2 /*not set*/ },
{ "12345678.a", TRUE, FALSE },
{ "12345678.a ", FALSE, 2 /*not set*/ },
{ "12345678.a c", TRUE, TRUE },
{ " 2345678.a ", FALSE, 2 /*not set*/ },
{ "1 345678.abc", TRUE, TRUE },
{ "1 8.a c", TRUE, TRUE },
{ "1 3 5 7 .abc", FALSE, 2 /*not set*/ },
{ "12345678. c", TRUE, TRUE },
{ "123456789.a", FALSE, 2 /*not set*/ },
{ "12345.abcd", FALSE, 2 /*not set*/ },
{ "12345.ab d", FALSE, 2 /*not set*/ },
{ ".abc", FALSE, 2 /*not set*/ },
{ "12.abc.d", FALSE, 2 /*not set*/ },
{ ".", TRUE, FALSE },
{ "..", TRUE, FALSE },
{ "...", FALSE, 2 /*not set*/ },
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", FALSE, 2 /*not set*/ },
{ NULL, 0 }
};
const struct test *test;
UNICODE_STRING ustr;
OEM_STRING oem, oem_ret;
WCHAR buffer[200];
char buff2[12];
BOOLEAN ret, spaces;
ustr.MaximumLength = sizeof(buffer);
ustr.Buffer = buffer;
for (test = tests; test->path; test++)
{
char path[100];
strcpy(path, test->path);
oem.Buffer = path;
oem.Length = strlen(test->path);
oem.MaximumLength = oem.Length + 1;
pRtlOemStringToUnicodeString( &ustr, &oem, FALSE );
spaces = 2;
oem_ret.Length = oem_ret.MaximumLength = sizeof(buff2);
oem_ret.Buffer = buff2;
ret = pRtlIsNameLegalDOS8Dot3( &ustr, &oem_ret, &spaces );
ok( ret == test->result, "Wrong result %d/%d for '%s'\n", ret, test->result, test->path );
ok( spaces == test->spaces, "Wrong spaces value %d/%d for '%s'\n", spaces, test->spaces, test->path );
if (strlen(test->path) <= 12)
{
char str[13];
int i;
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 );
ok( !memcmp( oem_ret.Buffer, str, oem_ret.Length ),
"Wrong string '%.*s'/'%s'\n", oem_ret.Length, oem_ret.Buffer, str );
}
}
}
static void test_RtlGetFullPathName_U(void)
{
struct test
{
const char *path;
const char *rname;
const char *rfile;
};
static const struct test tests[] =
{
{ "c:/test", "c:\\test", "test"},
{ "c:/test ", "c:\\test", "test"},
{ "c:/test.", "c:\\test", "test"},
{ "c:/test .... .. ", "c:\\test", "test"},
{ "c:/test/ .... .. ", "c:\\test\\", NULL},
{ "c:/test/..", "c:\\", NULL},
{ "c:/test/.. ", "c:\\test\\", NULL},
{ "c:/TEST", "c:\\test", "test"},
{ "c:/test/file", "c:\\test\\file", "file"},
{ "c:/test./file", "c:\\test\\file", "file"},
{ "c:/test../file", "c:\\test.\\file", "file"},
{ "c:/test.. /file", "c:\\test.. \\file","file"},
{ "c:/test/././file", "c:\\test\\file", "file"},
{ "c:/test\\.\\.\\file", "c:\\test\\file", "file"},
{ "c:/test/\\.\\.\\file", "c:\\test\\file", "file"},
{ "c:/test\\\\.\\.\\file", "c:\\test\\file", "file"},
{ "c:/test\\test1\\..\\.\\file", "c:\\test\\file", "file"},
{ "c:///test\\.\\.\\file//", "c:\\test\\file\\", NULL},
{ "c:///test\\..\\file\\..\\//", "c:\\", NULL},
{ NULL, NULL, NULL}
};
const struct test *test;
WCHAR pathbufW[2*MAX_PATH], rbufferW[MAX_PATH];
CHAR rbufferA[MAX_PATH], rfileA[MAX_PATH];
ULONG ret;
WCHAR *file_part;
DWORD reslen;
UINT len;
for (test = tests; test->path; test++)
{
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(pRtlUnicodeToMultiByteN(rbufferA,MAX_PATH,&reslen,rbufferW,MAX_PATH) == STATUS_SUCCESS,
"RtlUnicodeToMultiByteN failed\n");
ok(lstrcmpiA(rbufferA,test->rname) == 0, "Got \"%s\" expected \"%s\"\n",rbufferA,test->rname);
if (file_part)
{
ok(pRtlUnicodeToMultiByteN(rfileA,MAX_PATH,&reslen,file_part,MAX_PATH) == STATUS_SUCCESS,
"RtlUnicodeToMultiByteN failed\n");
ok(test->rfile && !lstrcmpiA(rfileA,test->rfile), "Got \"%s\" expected \"%s\"\n",rfileA,test->rfile);
}
else
{
ok( !test->rfile, "Got NULL expected \"%s\"\n", test->rfile );
}
}
}
START_TEST(path)
{
HMODULE mod = GetModuleHandleA("ntdll.dll");
pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN");
pRtlUnicodeToMultiByteN = (void *)GetProcAddress(mod,"RtlUnicodeToMultiByteN");
pRtlDetermineDosPathNameType_U = (void *)GetProcAddress(mod,"RtlDetermineDosPathNameType_U");
pRtlIsDosDeviceName_U = (void *)GetProcAddress(mod,"RtlIsDosDeviceName_U");
pRtlOemStringToUnicodeString = (void *)GetProcAddress(mod,"RtlOemStringToUnicodeString");
pRtlIsNameLegalDOS8Dot3 = (void *)GetProcAddress(mod,"RtlIsNameLegalDOS8Dot3");
pRtlGetFullPathName_U = (void *)GetProcAddress(mod,"RtlGetFullPathName_U");
if (pRtlDetermineDosPathNameType_U)
test_RtlDetermineDosPathNameType();
if (pRtlIsDosDeviceName_U)
test_RtlIsDosDeviceName();
if (pRtlIsNameLegalDOS8Dot3)
test_RtlIsNameLegalDOS8Dot3();
if (pRtlGetFullPathName_U && pRtlMultiByteToUnicodeN)
test_RtlGetFullPathName_U();
}

View file

@ -0,0 +1,380 @@
/* Unit test suite for Rtl* Registry API functions
*
* Copyright 2003 Thomas Mertes
* Copyright 2005 Brad DeMorrow
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTE: I don't test every RelativeTo value because it would be redundant, all calls go through
* helper function RTL_GetKeyHandle().--Brad DeMorrow
*
*/
#include "ntdll_test.h"
#include "winternl.h"
//#include "wine/library.h"
#include "stdio.h"
#include "winnt.h"
#include "winnls.h"
#include "stdlib.h"
#include "wine/unicode.h"
#ifndef __WINE_WINTERNL_H
/* RtlQueryRegistryValues structs and defines */
#define RTL_REGISTRY_ABSOLUTE 0
#define RTL_REGISTRY_SERVICES 1
#define RTL_REGISTRY_CONTROL 2
#define RTL_REGISTRY_WINDOWS_NT 3
#define RTL_REGISTRY_DEVICEMAP 4
#define RTL_REGISTRY_USER 5
#define RTL_REGISTRY_HANDLE 0x40000000
#define RTL_REGISTRY_OPTIONAL 0x80000000
#define RTL_QUERY_REGISTRY_SUBKEY 0x00000001
#define RTL_QUERY_REGISTRY_TOPKEY 0x00000002
#define RTL_QUERY_REGISTRY_REQUIRED 0x00000004
#define RTL_QUERY_REGISTRY_NOVALUE 0x00000008
#define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010
#define RTL_QUERY_REGISTRY_DIRECT 0x00000020
#define RTL_QUERY_REGISTRY_DELETE 0x00000040
typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext);
typedef struct _RTL_QUERY_REGISTRY_TABLE {
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
ULONG Flags;
PWSTR Name;
PVOID EntryContext;
ULONG DefaultType;
PVOID DefaultData;
ULONG DefaultLength;
} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
#endif
static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
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 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)(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)( PHKEY, const PUNICODE_STRING, ULONG,
ULONG, const PVOID, ULONG );
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);
static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
static HMODULE hntdll = 0;
static int CurrentTest = 0;
static UNICODE_STRING winetestpath;
#define NTDLL_GET_PROC(func) \
p ## func = (void*)GetProcAddress(hntdll, #func); \
if(!p ## func) { \
trace("GetProcAddress(%s) failed\n", #func); \
FreeLibrary(hntdll); \
return FALSE; \
}
static BOOL InitFunctionPtrs(void)
{
hntdll = LoadLibraryA("ntdll.dll");
if(!hntdll) {
trace("Could not load ntdll.dll\n");
return FALSE;
}
if (hntdll)
{
NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
NTDLL_GET_PROC(RtlCreateUnicodeString)
NTDLL_GET_PROC(RtlFreeUnicodeString)
NTDLL_GET_PROC(NtDeleteValueKey)
NTDLL_GET_PROC(RtlQueryRegistryValues)
NTDLL_GET_PROC(RtlCheckRegistryKey)
NTDLL_GET_PROC(RtlOpenCurrentUser)
NTDLL_GET_PROC(NtClose)
NTDLL_GET_PROC(NtDeleteValueKey)
NTDLL_GET_PROC(NtCreateKey)
NTDLL_GET_PROC(NtDeleteKey)
NTDLL_GET_PROC(NtSetValueKey)
NTDLL_GET_PROC(NtOpenKey)
NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
NTDLL_GET_PROC(RtlReAllocateHeap)
NTDLL_GET_PROC(RtlAppendUnicodeToString)
NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
NTDLL_GET_PROC(RtlFreeHeap)
NTDLL_GET_PROC(RtlAllocateHeap)
NTDLL_GET_PROC(RtlZeroMemory)
}
return TRUE;
}
#undef NTDLL_GET_PROC
static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
{
NTSTATUS ret = STATUS_SUCCESS;
int ValueNameLength = 0;
LPSTR ValName = 0;
trace("**Test %d**\n", CurrentTest);
if(ValueName)
{
ValueNameLength = strlenW(ValueName);
ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
trace("ValueName: %s\n", ValName);
}
else
trace("ValueName: (null)\n");
switch(ValueType)
{
case REG_NONE:
trace("ValueType: REG_NONE\n");
trace("ValueData: %d\n", (int)ValueData);
break;
case REG_BINARY:
trace("ValueType: REG_BINARY\n");
trace("ValueData: %d\n", (int)ValueData);
break;
case REG_SZ:
trace("ValueType: REG_SZ\n");
trace("ValueData: %s\n", (char*)ValueData);
break;
case REG_MULTI_SZ:
trace("ValueType: REG_MULTI_SZ\n");
trace("ValueData: %s\n", (char*)ValueData);
break;
case REG_EXPAND_SZ:
trace("ValueType: REG_EXPAND_SZ\n");
trace("ValueData: %s\n", (char*)ValueData);
break;
case REG_DWORD:
trace("ValueType: REG_DWORD\n");
trace("ValueData: %d\n", (int)ValueData);
break;
};
trace("ValueLength: %d\n", (int)ValueLength);
if(CurrentTest == 0)
ok(1, "\n"); /*checks that QueryRoutine is called*/
if(CurrentTest > 7)
ok(!1, "Invalid Test Specified!\n");
CurrentTest++;
if(ValName)
pRtlFreeHeap(GetProcessHeap(), 0, ValName);
return ret;
}
static void test_RtlQueryRegistryValues(void)
{
/*
******************************
* QueryTable Flags *
******************************
*RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
*RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
*RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
*RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
*RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
*RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
*RTL_QUERY_REGISTRY_DELETE * Delete value key after query
******************************
**Test layout(numbered according to CurrentTest value)**
0)NOVALUE Just make sure call-back works
1)Null Name See if QueryRoutine is called for every value in current key
2)SUBKEY See if we can use SUBKEY to change the current path on the fly
3)REQUIRED Test for value that's not there
4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
6)DefaultType Test return values when key isn't present
7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
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)
12)Delete Try to delete value key
*/
NTSTATUS status;
ULONG RelativeTo;
PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
QueryTable[0].QueryRoutine = QueryRoutine;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
QueryTable[0].Name = NULL;
QueryTable[0].EntryContext = NULL;
QueryTable[0].DefaultType = REG_BINARY;
QueryTable[0].DefaultData = NULL;
QueryTable[0].DefaultLength = 100;
QueryTable[1].QueryRoutine = QueryRoutine;
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 = NULL;
QueryTable[2].Flags = 0;
QueryTable[2].Name = NULL;
QueryTable[2].EntryContext = 0;
QueryTable[2].DefaultType = REG_NONE;
QueryTable[2].DefaultData = NULL;
QueryTable[2].DefaultLength = 0;
status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08lx\n", status);
pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
}
static void test_NtCreateKey(void)
{
/*Create WineTest*/
OBJECT_ATTRIBUTES attr;
UNICODE_STRING ValName;
HKEY key;
ACCESS_MASK am = GENERIC_ALL;
NTSTATUS status;
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08lx\n", status);
pRtlFreeUnicodeString(&ValName);
pNtClose(&key);
}
static void test_NtSetValueKey(void)
{
HANDLE key;
NTSTATUS status;
OBJECT_ATTRIBUTES attr;
ACCESS_MASK am = KEY_WRITE;
UNICODE_STRING ValName;
DWORD data = 711;
pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
status = pNtOpenKey(&key, am, &attr);
ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status);
status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status);
pRtlFreeUnicodeString(&ValName);
pNtClose(&key);
}
static void test_RtlOpenCurrentUser(void)
{
NTSTATUS status;
HKEY handle;
status=pRtlOpenCurrentUser(KEY_READ, &handle);
ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08lx\n", status);
pNtClose(&handle);
}
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);
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);
}
static void test_NtDeleteKey(void)
{
NTSTATUS status;
HANDLE hkey;
OBJECT_ATTRIBUTES attr;
ACCESS_MASK am = KEY_ALL_ACCESS;
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
status = pNtOpenKey(&hkey, am, &attr);
status = pNtDeleteKey(hkey);
ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status);
}
START_TEST(reg)
{
static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
if(!InitFunctionPtrs())
return;
pRtlFormatCurrentUserKeyPath(&winetestpath);
winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
pRtlAppendUnicodeToString(&winetestpath, winetest);
test_NtCreateKey();
test_NtSetValueKey();
test_RtlCheckRegistryKey();
test_RtlOpenCurrentUser();
test_RtlQueryRegistryValues();
test_NtDeleteKey();
pRtlFreeUnicodeString(&winetestpath);
FreeLibrary(hntdll);
}

View file

@ -0,0 +1,891 @@
/* Unit test suite for Rtl* API functions
*
* Copyright 2003 Thomas Mertes
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* We use function pointers here as there is no import library for NTDLL on
* windows.
*/
#include <stdlib.h>
#include "ntdll_test.h"
/* Function ptrs for ntdll calls */
static HMODULE hntdll = 0;
static SIZE_T (WINAPI *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T);
static SIZE_T (WINAPI *pRtlCompareMemoryUlong)(PULONG, SIZE_T, ULONG);
static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T);
static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE);
static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG);
static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T);
static ULONGLONG (WINAPIV *pRtlUlonglongByteSwap)(ULONGLONG source);
static ULONG (WINAPI *pRtlUniform)(PULONG);
static ULONG (WINAPI *pRtlRandom)(PULONG);
static BOOLEAN (WINAPI *pRtlAreAllAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
static BOOLEAN (WINAPI *pRtlAreAnyAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
static DWORD (WINAPI *pRtlComputeCrc32)(DWORD,const BYTE*,INT);
static void (WINAPI * pRtlInitializeHandleTable)(ULONG, ULONG, RTL_HANDLE_TABLE *);
static BOOLEAN (WINAPI * pRtlIsValidIndexHandle)(const RTL_HANDLE_TABLE *, ULONG, RTL_HANDLE **);
static NTSTATUS (WINAPI * pRtlDestroyHandleTable)(RTL_HANDLE_TABLE *);
static RTL_HANDLE * (WINAPI * pRtlAllocateHandle)(RTL_HANDLE_TABLE *, ULONG *);
static BOOLEAN (WINAPI * pRtlFreeHandle)(RTL_HANDLE_TABLE *, RTL_HANDLE *);
#define LEN 16
static const char* src_src = "This is a test!"; /* 16 bytes long, incl NUL */
static ULONG src_aligned_block[4];
static ULONG dest_aligned_block[32];
static const char *src = (const char*)src_aligned_block;
static char* dest = (char*)dest_aligned_block;
static void InitFunctionPtrs(void)
{
hntdll = LoadLibraryA("ntdll.dll");
ok(hntdll != 0, "LoadLibrary failed\n");
if (hntdll) {
pRtlCompareMemory = (void *)GetProcAddress(hntdll, "RtlCompareMemory");
pRtlCompareMemoryUlong = (void *)GetProcAddress(hntdll, "RtlCompareMemoryUlong");
pRtlMoveMemory = (void *)GetProcAddress(hntdll, "RtlMoveMemory");
pRtlFillMemory = (void *)GetProcAddress(hntdll, "RtlFillMemory");
pRtlFillMemoryUlong = (void *)GetProcAddress(hntdll, "RtlFillMemoryUlong");
pRtlZeroMemory = (void *)GetProcAddress(hntdll, "RtlZeroMemory");
pRtlUlonglongByteSwap = (void *)GetProcAddress(hntdll, "RtlUlonglongByteSwap");
pRtlUniform = (void *)GetProcAddress(hntdll, "RtlUniform");
pRtlRandom = (void *)GetProcAddress(hntdll, "RtlRandom");
pRtlAreAllAccessesGranted = (void *)GetProcAddress(hntdll, "RtlAreAllAccessesGranted");
pRtlAreAnyAccessesGranted = (void *)GetProcAddress(hntdll, "RtlAreAnyAccessesGranted");
pRtlComputeCrc32 = (void *)GetProcAddress(hntdll, "RtlComputeCrc32");
pRtlInitializeHandleTable = (void *)GetProcAddress(hntdll, "RtlInitializeHandleTable");
pRtlIsValidIndexHandle = (void *)GetProcAddress(hntdll, "RtlIsValidIndexHandle");
pRtlDestroyHandleTable = (void *)GetProcAddress(hntdll, "RtlDestroyHandleTable");
pRtlAllocateHandle = (void *)GetProcAddress(hntdll, "RtlAllocateHandle");
pRtlFreeHandle = (void *)GetProcAddress(hntdll, "RtlFreeHandle");
}
strcpy((char*)src_aligned_block, src_src);
ok(strlen(src) == 15, "Source must be 16 bytes long!\n");
}
#define COMP(str1,str2,cmplen,len) size = pRtlCompareMemory(str1, str2, cmplen); \
ok(size == len, "Expected %ld, got %ld\n", size, (SIZE_T)len)
static void test_RtlCompareMemory(void)
{
SIZE_T size;
if (!pRtlCompareMemory)
return;
strcpy(dest, src);
COMP(src,src,0,0);
COMP(src,src,LEN,LEN);
dest[0] = 'x';
COMP(src,dest,LEN,0);
}
static void test_RtlCompareMemoryUlong(void)
{
ULONG a[10];
ULONG result;
a[0]= 0x0123;
a[1]= 0x4567;
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);
result = pRtlCompareMemoryUlong(a, 3, 0x0123);
ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %lu, expected 0\n", a, result);
result = pRtlCompareMemoryUlong(a, 4, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 5, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 7, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 8, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 9, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 4, 0x0127);
ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x0127) returns %lu, expected 0\n", a, result);
result = pRtlCompareMemoryUlong(a, 4, 0x7123);
ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x7123) returns %lu, expected 0\n", a, result);
result = pRtlCompareMemoryUlong(a, 16, 0x4567);
ok(result == 0, "RtlCompareMemoryUlong(%p, 16, 0x4567) returns %lu, 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);
result = pRtlCompareMemoryUlong(a, 4, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 5, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 7, 0x0123);
ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %lu, expected 4\n", a, result);
result = pRtlCompareMemoryUlong(a, 8, 0x0123);
ok(result == 8, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %lu, expected 8\n", a, result);
result = pRtlCompareMemoryUlong(a, 9, 0x0123);
ok(result == 8, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %lu, expected 8\n", a, result);
}
#define COPY(len) memset(dest,0,sizeof(dest_aligned_block)); pRtlMoveMemory(dest, src, len)
#define CMP(str) ok(strcmp(dest,str) == 0, "Expected '%s', got '%s'\n", str, dest)
static void test_RtlMoveMemory(void)
{
if (!pRtlMoveMemory)
return;
/* Length should be in bytes and not rounded. Use strcmp to ensure we
* didn't write past the end (it checks for the final NUL left by memset)
*/
COPY(0); CMP("");
COPY(1); CMP("T");
COPY(2); CMP("Th");
COPY(3); CMP("Thi");
COPY(4); CMP("This");
COPY(5); CMP("This ");
COPY(6); CMP("This i");
COPY(7); CMP("This is");
COPY(8); CMP("This is ");
COPY(9); CMP("This is a");
/* Overlapping */
strcpy(dest, src); pRtlMoveMemory(dest, dest + 1, strlen(src) - 1);
CMP("his is a test!!");
strcpy(dest, src); pRtlMoveMemory(dest + 1, dest, strlen(src));
CMP("TThis is a test!");
}
#define FILL(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlFillMemory(dest,len,'x')
static void test_RtlFillMemory(void)
{
if (!pRtlFillMemory)
return;
/* Length should be in bytes and not rounded. Use strcmp to ensure we
* didn't write past the end (the remainder of the string should match)
*/
FILL(0); CMP("This is a test!");
FILL(1); CMP("xhis is a test!");
FILL(2); CMP("xxis is a test!");
FILL(3); CMP("xxxs is a test!");
FILL(4); CMP("xxxx is a test!");
FILL(5); CMP("xxxxxis a test!");
FILL(6); CMP("xxxxxxs a test!");
FILL(7); CMP("xxxxxxx a test!");
FILL(8); CMP("xxxxxxxxa test!");
FILL(9); CMP("xxxxxxxxx test!");
}
#define LFILL(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlFillMemoryUlong(dest,len,val)
static void test_RtlFillMemoryUlong(void)
{
ULONG val = ('x' << 24) | ('x' << 16) | ('x' << 8) | 'x';
if (!pRtlFillMemoryUlong)
return;
/* Length should be in bytes and not rounded. Use strcmp to ensure we
* didn't write past the end (the remainder of the string should match)
*/
LFILL(0); CMP("This is a test!");
LFILL(1); CMP("This is a test!");
LFILL(2); CMP("This is a test!");
LFILL(3); CMP("This is a test!");
LFILL(4); CMP("xxxx is a test!");
LFILL(5); CMP("xxxx is a test!");
LFILL(6); CMP("xxxx is a test!");
LFILL(7); CMP("xxxx is a test!");
LFILL(8); CMP("xxxxxxxxa test!");
LFILL(9); CMP("xxxxxxxxa test!");
}
#define ZERO(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlZeroMemory(dest,len)
#define MCMP(str) ok(memcmp(dest,str,LEN) == 0, "Memcmp failed\n")
static void test_RtlZeroMemory(void)
{
if (!pRtlZeroMemory)
return;
/* Length should be in bytes and not rounded. */
ZERO(0); MCMP("This is a test!");
ZERO(1); MCMP("\0his is a test!");
ZERO(2); MCMP("\0\0is is a test!");
ZERO(3); MCMP("\0\0\0s is a test!");
ZERO(4); MCMP("\0\0\0\0 is a test!");
ZERO(5); MCMP("\0\0\0\0\0is a test!");
ZERO(6); MCMP("\0\0\0\0\0\0s a test!");
ZERO(7); MCMP("\0\0\0\0\0\0\0 a test!");
ZERO(8); MCMP("\0\0\0\0\0\0\0\0a test!");
ZERO(9); MCMP("\0\0\0\0\0\0\0\0\0 test!");
}
static void test_RtlUlonglongByteSwap(void)
{
ULONGLONG result;
result = pRtlUlonglongByteSwap( ((ULONGLONG)0x76543210 << 32) | 0x87654321 );
ok( (((ULONGLONG)0x21436587 << 32) | 0x10325476) == result,
"RtlUlonglongByteSwap(0x7654321087654321) returns 0x%llx, expected 0x2143658710325476\n",
result);
}
static void test_RtlUniform(void)
{
ULONGLONG num;
ULONG seed;
ULONG seed_bak;
ULONG expected;
ULONG result;
/*
* According to the documentation RtlUniform is using D.H. Lehmer's 1948
* algorithm. This algorithm is:
*
* seed = (seed * const_1 + const_2) % const_3;
*
* According to the documentation the random number is distributed over
* [0..MAXLONG]. Therefore const_3 is MAXLONG + 1:
*
* seed = (seed * const_1 + const_2) % (MAXLONG + 1);
*
* Because MAXLONG is 0x7fffffff (and MAXLONG + 1 is 0x80000000) the
* algorithm can be expressed without division as:
*
* seed = (seed * const_1 + const_2) & MAXLONG;
*
* To find out const_2 we just call RtlUniform with seed set to 0:
*/
seed = 0;
expected = 0x7fffffc3;
result = pRtlUniform(&seed);
ok(result == expected,
"RtlUniform(&seed (seed == 0)) returns %lx, expected %lx\n",
result, expected);
/*
* The algorithm is now:
*
* seed = (seed * const_1 + 0x7fffffc3) & MAXLONG;
*
* To find out const_1 we can use:
*
* const_1 = RtlUniform(1) - 0x7fffffc3;
*
* If that does not work a search loop can try all possible values of
* const_1 and compare to the result to RtlUniform(1).
* This way we find out that const_1 is 0xffffffed.
*
* For seed = 1 the const_2 is 0x7fffffc4:
*/
seed = 1;
expected = seed * 0xffffffed + 0x7fffffc3 + 1;
result = pRtlUniform(&seed);
ok(result == expected,
"RtlUniform(&seed (seed == 1)) returns %lx, expected %lx\n",
result, expected);
/*
* For seed = 2 the const_2 is 0x7fffffc3:
*/
seed = 2;
expected = seed * 0xffffffed + 0x7fffffc3;
result = pRtlUniform(&seed);
ok(result == expected,
"RtlUniform(&seed (seed == 2)) returns %lx, expected %lx\n",
result, expected);
/*
* More tests show that if seed is odd the result must be incremented by 1:
*/
seed = 3;
expected = seed * 0xffffffed + 0x7fffffc3 + (seed & 1);
result = pRtlUniform(&seed);
ok(result == expected,
"RtlUniform(&seed (seed == 2)) returns %lx, expected %lx\n",
result, expected);
seed = 0x6bca1aa;
expected = seed * 0xffffffed + 0x7fffffc3;
result = pRtlUniform(&seed);
ok(result == expected,
"RtlUniform(&seed (seed == 0x6bca1aa)) returns %lx, expected %lx\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",
result, expected);
/*
* When seed is 0x6bca1ac there is an exception:
*/
seed = 0x6bca1ac;
expected = seed * 0xffffffed + 0x7fffffc3 + 2;
result = pRtlUniform(&seed);
ok(result == expected,
"RtlUniform(&seed (seed == 0x6bca1ac)) returns %lx, expected %lx\n",
result, expected);
/*
* Note that up to here const_3 is not used
* (the highest bit of the result is not set).
*
* Starting with 0x6bca1ad: If seed is even the result must be incremented by 1:
*/
seed = 0x6bca1ad;
expected = (seed * 0xffffffed + 0x7fffffc3) & MAXLONG;
result = pRtlUniform(&seed);
ok(result == expected,
"RtlUniform(&seed (seed == 0x6bca1ad)) returns %lx, expected %lx\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",
result, expected);
/*
* There are several ranges where for odd or even seed the result must be
* incremented by 1. You can see this ranges in the following test.
*
* For a full test use one of the following loop heads:
*
* for (num = 0; num <= 0xffffffff; num++) {
* seed = num;
* ...
*
* seed = 0;
* for (num = 0; num <= 0xffffffff; num++) {
* ...
*/
seed = 0;
for (num = 0; num <= 100000; num++) {
expected = seed * 0xffffffed + 0x7fffffc3;
if (seed < 0x6bca1ac) {
expected = expected + (seed & 1);
} else if (seed == 0x6bca1ac) {
expected = (expected + 2) & MAXLONG;
} else if (seed < 0xd79435c) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x1435e50b) {
expected = expected + (seed & 1);
} else if (seed < 0x1af286ba) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x21af2869) {
expected = expected + (seed & 1);
} else if (seed < 0x286bca18) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x2f286bc7) {
expected = expected + (seed & 1);
} else if (seed < 0x35e50d77) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x3ca1af26) {
expected = expected + (seed & 1);
} else if (seed < 0x435e50d5) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x4a1af284) {
expected = expected + (seed & 1);
} else if (seed < 0x50d79433) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x579435e2) {
expected = expected + (seed & 1);
} else if (seed < 0x5e50d792) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x650d7941) {
expected = expected + (seed & 1);
} else if (seed < 0x6bca1af0) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x7286bc9f) {
expected = expected + (seed & 1);
} else if (seed < 0x79435e4e) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x7ffffffd) {
expected = expected + (seed & 1);
} else if (seed < 0x86bca1ac) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed == 0x86bca1ac) {
expected = (expected + 1) & MAXLONG;
} else if (seed < 0x8d79435c) {
expected = expected + (seed & 1);
} else if (seed < 0x9435e50b) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0x9af286ba) {
expected = expected + (seed & 1);
} else if (seed < 0xa1af2869) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0xa86bca18) {
expected = expected + (seed & 1);
} else if (seed < 0xaf286bc7) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed == 0xaf286bc7) {
expected = (expected + 2) & MAXLONG;
} else if (seed < 0xb5e50d77) {
expected = expected + (seed & 1);
} else if (seed < 0xbca1af26) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0xc35e50d5) {
expected = expected + (seed & 1);
} else if (seed < 0xca1af284) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0xd0d79433) {
expected = expected + (seed & 1);
} else if (seed < 0xd79435e2) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0xde50d792) {
expected = expected + (seed & 1);
} else if (seed < 0xe50d7941) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0xebca1af0) {
expected = expected + (seed & 1);
} else if (seed < 0xf286bc9f) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else if (seed < 0xf9435e4e) {
expected = expected + (seed & 1);
} else if (seed < 0xfffffffd) {
expected = (expected + (~seed & 1)) & MAXLONG;
} else {
expected = expected + (seed & 1);
} /* if */
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);
ok(seed == expected,
"test: %llu RtlUniform(&seed (seed == %lx)) sets seed to %lx, expected %lx\n",
num, seed_bak, seed, expected);
} /* for */
/*
* Further investigation shows: In the different regions the highest bit
* is set or cleared when even or odd seeds need an increment by 1.
* This leads to a simplified algorithm:
*
* seed = seed * 0xffffffed + 0x7fffffc3;
* if (seed == 0xffffffff || seed == 0x7ffffffe) {
* seed = (seed + 2) & MAXLONG;
* } else if (seed == 0x7fffffff) {
* seed = 0;
* } else if ((seed & 0x80000000) == 0) {
* seed = seed + (~seed & 1);
* } else {
* seed = (seed + (seed & 1)) & MAXLONG;
* }
*
* This is also the algorithm used for RtlUniform of wine (see dlls/ntdll/rtl.c).
*
* Now comes the funny part:
* It took me one weekend, to find the complicated algorithm and one day more,
* to find the simplified algorithm. Several weeks later I found out: The value
* MAXLONG (=0x7fffffff) is never returned, neither with the native function
* nor with the simplified algorithm. In reality the native function and our
* function return a random number distributed over [0..MAXLONG-1]. Note
* that this is different from what native documentation states [0..MAXLONG].
* Expressed with D.H. Lehmer's 1948 algorithm it looks like:
*
* seed = (seed * const_1 + const_2) % MAXLONG;
*
* Further investigations show that the real algorithm is:
*
* seed = (seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
*
* This is checked with the test below:
*/
seed = 0;
for (num = 0; num <= 100000; num++) {
expected = (seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
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);
ok(seed == expected,
"test: %llu RtlUniform(&seed (seed == %lx)) sets seed to %lx, expected %lx\n",
num, seed_bak, seed, expected);
} /* for */
/*
* More tests show that RtlUniform does not return 0x7ffffffd for seed values
* in the range [0..MAXLONG-1]. Additionally 2 is returned twice. This shows
* that there is more than one cycle of generated randon numbers ...
*/
}
static ULONG WINAPI my_RtlRandom(PULONG seed)
{
static ULONG saved_value[128] =
{ /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
/* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
/* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
/* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
/* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
/* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
/* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
/* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
/* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
/* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
/* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
/* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
/* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
/* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
/* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
/* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
ULONG rand;
int pos;
ULONG result;
rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
*seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
pos = *seed & 0x7f;
result = saved_value[pos];
saved_value[pos] = rand;
return(result);
}
static void test_RtlRandom(void)
{
ULONGLONG num;
ULONG seed;
ULONG seed_bak;
ULONG seed_expected;
ULONG result;
ULONG result_expected;
/*
* Unlike RtlUniform, RtlRandom is not documented. We guess that for
* RtlRandom D.H. Lehmer's 1948 algorithm is used like stated in
* the documentation of the RtlUniform function. This algorithm is:
*
* seed = (seed * const_1 + const_2) % const_3;
*
* According to the RtlUniform documentation the random number is
* distributed over [0..MAXLONG], but in reality it is distributed
* over [0..MAXLONG-1]. Therefore const_3 might be MAXLONG + 1 or
* MAXLONG:
*
* seed = (seed * const_1 + const_2) % (MAXLONG + 1);
*
* or
*
* seed = (seed * const_1 + const_2) % MAXLONG;
*
* To find out const_2 we just call RtlRandom with seed set to 0:
*/
seed = 0;
result_expected = 0x320a1743;
seed_expected =0x44b;
result = pRtlRandom(&seed);
ok(result == result_expected,
"pRtlRandom(&seed (seed == 0)) returns %lx, expected %lx\n",
result, result_expected);
ok(seed == seed_expected,
"pRtlRandom(&seed (seed == 0)) sets seed to %lx, expected %lx\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:
*/
seed = 0;
result_expected = 0x7fffffc3;
seed_expected =0x44b;
result = pRtlRandom(&seed);
ok(result == result_expected,
"RtlRandom(&seed (seed == 0)) returns %lx, expected %lx\n",
result, result_expected);
ok(seed == seed_expected,
"RtlRandom(&seed (seed == 0)) sets seed to %lx, expected %lx\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:
*/
seed = 0;
result_expected = 0x7fffffc3;
seed_expected =0x44b;
result = pRtlRandom(&seed);
ok(result == result_expected,
"RtlRandom(&seed (seed == 0)) returns %lx, expected %lx\n",
result, result_expected);
ok(seed == seed_expected,
"RtlRandom(&seed (seed == 0)) sets seed to %lx, expected %lx\n",
seed, seed_expected);
/*
* Seed is aggain 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
*
* seed = 0;
* result = RtlUniform(&seed);
*
* we get the same result (0x7fffffc3) as with
*
* seed = 0;
* RtlRandom(&seed);
* seed = 0;
* result = RtlRandom(&seed);
*
* And there is another interesting thing. If we do
*
* seed = 0;
* RtlUniform(&seed);
* RtlUniform(&seed);
*
* seed is set to the value 0x44b which ist the same value that
*
* seed = 0;
* RtlRandom(&seed);
*
* assigns to seed. Putting these two findings together leads to
* the concluson that RtlRandom saves the value in some variable,
* like in the following algorithm:
*
* result = saved_value;
* saved_value = RtlUniform(&seed);
* RtlUniform(&seed);
* return(result);
*
* Now we do further tests with seed set to 1:
*/
seed = 1;
result_expected = 0x7a50bbc6;
seed_expected =0x5a1;
result = pRtlRandom(&seed);
ok(result == result_expected,
"RtlRandom(&seed (seed == 1)) returns %lx, expected %lx\n",
result, result_expected);
ok(seed == seed_expected,
"RtlRandom(&seed (seed == 1)) sets seed to %lx, expected %lx\n",
seed, seed_expected);
/*
* If there is just one saved_value the result now would be
* 0x7fffffc3. From this test we can see that there is more than
* one saved_value, like with this algorithm:
*
* result = saved_value[pos];
* saved_value[pos] = RtlUniform(&seed);
* RtlUniform(&seed);
* return(result);
*
* But how is the value of pos determined? The calls to RtlUniform
* create a sequence of random numbers. Every second random number
* is put into the saved_value array and is used in some later call
* of RtlRandom as result. The only reasonable source to determine
* pos are the random numbers generated by RtlUniform which are not
* put into the saved_value array. This are the values of seed
* between the two calls of RtlUniform as in this algorithm:
*
* rand = RtlUniform(&seed);
* RtlUniform(&seed);
* pos = position(seed);
* result = saved_value[pos];
* saved_value[pos] = rand;
* return(result);
*
* 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.
* 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).
*
* For a full test of RtlRandom use one of the following loop heads:
*
* for (num = 0; num <= 0xffffffff; num++) {
* seed = num;
* ...
*
* seed = 0;
* for (num = 0; num <= 0xffffffff; num++) {
* ...
*/
seed = 0;
for (num = 0; num <= 100000; num++) {
seed_bak = seed;
seed_expected = seed;
result_expected = my_RtlRandom(&seed_expected);
/* The following corrections are necessary because the */
/* previous tests changed the saved_value array */
if (num == 0) {
result_expected = 0x7fffffc3;
} else if (num == 81) {
result_expected = 0x7fffffb1;
} /* 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);
ok(seed == seed_expected,
"test: %llu RtlUniform(&seed (seed == %lx)) sets seed to %lx, expected %lx\n",
num, seed_bak, seed, seed_expected);
} /* for */
}
typedef struct {
ACCESS_MASK GrantedAccess;
ACCESS_MASK DesiredAccess;
BOOLEAN result;
} all_accesses_t;
static const all_accesses_t all_accesses[] = {
{0xFEDCBA76, 0xFEDCBA76, 1},
{0x00000000, 0xFEDCBA76, 0},
{0xFEDCBA76, 0x00000000, 1},
{0x00000000, 0x00000000, 1},
{0xFEDCBA76, 0xFEDCBA70, 1},
{0xFEDCBA70, 0xFEDCBA76, 0},
{0xFEDCBA76, 0xFEDC8A76, 1},
{0xFEDC8A76, 0xFEDCBA76, 0},
{0xFEDCBA76, 0xC8C4B242, 1},
{0xC8C4B242, 0xFEDCBA76, 0},
};
#define NB_ALL_ACCESSES (sizeof(all_accesses)/sizeof(*all_accesses))
static void test_RtlAreAllAccessesGranted(void)
{
size_t 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_num, all_accesses[test_num].GrantedAccess,
all_accesses[test_num].DesiredAccess,
result, all_accesses[test_num].result);
} /* for */
}
typedef struct {
ACCESS_MASK GrantedAccess;
ACCESS_MASK DesiredAccess;
BOOLEAN result;
} any_accesses_t;
static const any_accesses_t any_accesses[] = {
{0xFEDCBA76, 0xFEDCBA76, 1},
{0x00000000, 0xFEDCBA76, 0},
{0xFEDCBA76, 0x00000000, 0},
{0x00000000, 0x00000000, 0},
{0xFEDCBA76, 0x01234589, 0},
{0x00040000, 0xFEDCBA76, 1},
{0x00040000, 0xFED8BA76, 0},
{0xFEDCBA76, 0x00040000, 1},
{0xFED8BA76, 0x00040000, 0},
};
#define NB_ANY_ACCESSES (sizeof(any_accesses)/sizeof(*any_accesses))
static void test_RtlAreAnyAccessesGranted(void)
{
size_t 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_num, any_accesses[test_num].GrantedAccess,
any_accesses[test_num].DesiredAccess,
result, any_accesses[test_num].result);
} /* for */
}
static void test_RtlComputeCrc32(void)
{
DWORD crc = 0;
if (!pRtlComputeCrc32)
return;
crc = pRtlComputeCrc32(crc, src, LEN);
ok(crc == 0x40861dc2,"Expected 0x40861dc2, got %8lx\n", crc);
}
typedef struct MY_HANDLE
{
RTL_HANDLE RtlHandle;
void * MyValue;
} MY_HANDLE;
static inline void RtlpMakeHandleAllocated(RTL_HANDLE * Handle)
{
ULONG_PTR *AllocatedBit = (ULONG_PTR *)(&Handle->Next);
*AllocatedBit = *AllocatedBit | 1;
}
static void test_HandleTables(void)
{
BOOLEAN result;
NTSTATUS status;
ULONG Index;
MY_HANDLE * MyHandle;
RTL_HANDLE_TABLE HandleTable;
pRtlInitializeHandleTable(0x3FFF, sizeof(MY_HANDLE), &HandleTable);
MyHandle = (MY_HANDLE *)pRtlAllocateHandle(&HandleTable, &Index);
ok(MyHandle != NULL, "RtlAllocateHandle failed\n");
RtlpMakeHandleAllocated(&MyHandle->RtlHandle);
MyHandle = NULL;
result = pRtlIsValidIndexHandle(&HandleTable, Index, (RTL_HANDLE **)&MyHandle);
ok(result, "Handle %p wasn't valid\n", MyHandle);
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);
}
START_TEST(rtl)
{
InitFunctionPtrs();
if (pRtlCompareMemory)
test_RtlCompareMemory();
if (pRtlCompareMemoryUlong)
test_RtlCompareMemoryUlong();
if (pRtlMoveMemory)
test_RtlMoveMemory();
if (pRtlFillMemory)
test_RtlFillMemory();
if (pRtlFillMemoryUlong)
test_RtlFillMemoryUlong();
if (pRtlZeroMemory)
test_RtlZeroMemory();
if (pRtlUlonglongByteSwap)
test_RtlUlonglongByteSwap();
if (pRtlUniform)
test_RtlUniform();
if (pRtlRandom)
test_RtlRandom();
if (pRtlAreAllAccessesGranted)
test_RtlAreAllAccessesGranted();
if (pRtlAreAnyAccessesGranted)
test_RtlAreAnyAccessesGranted();
if (pRtlComputeCrc32)
test_RtlComputeCrc32();
if (pRtlInitializeHandleTable)
test_HandleTables();
}

View file

@ -0,0 +1,640 @@
/* Unit test suite for Rtl bitmap functions
*
* Copyright 2002 Jon Griffiths
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* We use function pointers here as some of the bitmap functions exist only
* in later versions of ntdll.
*/
#include "ntdll_test.h"
#ifdef __WINE_WINTERNL_H
/* Function ptrs for ordinal calls */
static HMODULE hntdll = 0;
static VOID (WINAPI *pRtlInitializeBitMap)(PRTL_BITMAP,LPBYTE,ULONG);
static VOID (WINAPI *pRtlSetAllBits)(PRTL_BITMAP);
static VOID (WINAPI *pRtlClearAllBits)(PRTL_BITMAP);
static VOID (WINAPI *pRtlSetBits)(PRTL_BITMAP,ULONG,ULONG);
static VOID (WINAPI *pRtlClearBits)(PRTL_BITMAP,ULONG,ULONG);
static BOOLEAN (WINAPI *pRtlAreBitsSet)(PRTL_BITMAP,ULONG,ULONG);
static BOOLEAN (WINAPI *pRtlAreBitsClear)(PRTL_BITMAP,ULONG,ULONG);
static ULONG (WINAPI *pRtlFindSetBitsAndClear)(PRTL_BITMAP,ULONG,ULONG);
static ULONG (WINAPI *pRtlFindClearBitsAndSet)(PRTL_BITMAP,ULONG,ULONG);
static CCHAR (WINAPI *pRtlFindMostSignificantBit)(ULONGLONG);
static CCHAR (WINAPI *pRtlFindLeastSignificantBit)(ULONGLONG);
static ULONG (WINAPI *pRtlFindSetRuns)(PRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN);
static ULONG (WINAPI *pRtlFindClearRuns)(PRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN);
static ULONG (WINAPI *pRtlNumberOfSetBits)(PRTL_BITMAP);
static ULONG (WINAPI *pRtlNumberOfClearBits)(PRTL_BITMAP);
static ULONG (WINAPI *pRtlFindLongestRunSet)(PRTL_BITMAP,PULONG);
static ULONG (WINAPI *pRtlFindLongestRunClear)(PRTL_BITMAP,PULONG);
static BYTE buff[256];
static RTL_BITMAP bm;
static void InitFunctionPtrs(void)
{
hntdll = LoadLibraryA("ntdll.dll");
ok(hntdll != 0, "LoadLibrary failed\n");
if (hntdll)
{
pRtlInitializeBitMap = (void *)GetProcAddress(hntdll, "RtlInitializeBitMap");
pRtlSetAllBits = (void *)GetProcAddress(hntdll, "RtlSetAllBits");
pRtlClearAllBits = (void *)GetProcAddress(hntdll, "RtlClearAllBits");
pRtlSetBits = (void *)GetProcAddress(hntdll, "RtlSetBits");
pRtlClearBits = (void *)GetProcAddress(hntdll, "RtlClearBits");
pRtlAreBitsSet = (void *)GetProcAddress(hntdll, "RtlAreBitsSet");
pRtlAreBitsClear = (void *)GetProcAddress(hntdll, "RtlAreBitsClear");
pRtlNumberOfSetBits = (void *)GetProcAddress(hntdll, "RtlNumberOfSetBits");
pRtlNumberOfClearBits = (void *)GetProcAddress(hntdll, "RtlNumberOfClearBits");
pRtlFindSetBitsAndClear = (void *)GetProcAddress(hntdll, "RtlFindSetBitsAndClear");
pRtlFindClearBitsAndSet = (void *)GetProcAddress(hntdll, "RtlFindClearBitsAndSet");
pRtlFindMostSignificantBit = (void *)GetProcAddress(hntdll, "RtlFindMostSignificantBit");
pRtlFindLeastSignificantBit = (void *)GetProcAddress(hntdll, "RtlFindLeastSignificantBit");
pRtlFindSetRuns = (void *)GetProcAddress(hntdll, "RtlFindSetRuns");
pRtlFindClearRuns = (void *)GetProcAddress(hntdll, "RtlFindClearRuns");
pRtlFindLongestRunSet = (void *)GetProcAddress(hntdll, "RtlFindLongestRunSet");
pRtlFindLongestRunClear = (void *)GetProcAddress(hntdll, "RtlFindLongestRunClear");
}
}
static void test_RtlInitializeBitMap(void)
{
bm.SizeOfBitMap = 0;
bm.Buffer = 0;
memset(buff, 0, sizeof(buff));
buff[0] = 77; /* Check buffer is not written to during init */
buff[79] = 77;
pRtlInitializeBitMap(&bm, buff, 800);
ok(bm.SizeOfBitMap == 800, "size uninitialised\n");
ok(bm.Buffer == (PULONG)buff,"buffer uninitialised\n");
ok(buff[0] == 77 && buff[79] == 77, "wrote to buffer\n");
}
static void test_RtlSetAllBits(void)
{
if (!pRtlSetAllBits)
return;
memset(buff, 0 , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, 1);
pRtlSetAllBits(&bm);
ok(buff[0] == 0xff && buff[1] == 0xff && buff[2] == 0xff &&
buff[3] == 0xff, "didn't round up size\n");
ok(buff[4] == 0, "set more than rounded size\n");
}
static void test_RtlClearAllBits(void)
{
if (!pRtlClearAllBits)
return;
memset(buff, 0xff , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, 1);
pRtlClearAllBits(&bm);
ok(!buff[0] && !buff[1] && !buff[2] && !buff[3], "didn't round up size\n");
ok(buff[4] == 0xff, "cleared more than rounded size\n");
}
static void test_RtlSetBits(void)
{
if (!pRtlSetBits)
return;
memset(buff, 0 , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
pRtlSetBits(&bm, 0, 1);
ok(buff[0] == 1, "didn't set 1st bit\n");
buff[0] = 0;
pRtlSetBits(&bm, 7, 2);
ok(buff[0] == 0x80 && buff[1] == 1, "didn't span w/len < 8\n");
buff[0] = buff[1] = 0;
pRtlSetBits(&bm, 7, 10);
ok(buff[0] == 0x80 && buff[1] == 0xff && buff[2] == 1, "didn't span w/len > 8\n");
buff[0] = buff[1] = buff[2] = 0;
pRtlSetBits(&bm, 0, 8); /* 1st byte */
ok(buff[0] == 0xff, "didn't set all bits\n");
ok(!buff[1], "set too many bits\n");
pRtlSetBits(&bm, sizeof(buff)*8-1, 1); /* last bit */
ok(buff[sizeof(buff)-1] == 0x80, "didn't set last bit\n");
}
static void test_RtlClearBits(void)
{
if (!pRtlClearBits)
return;
memset(buff, 0xff , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
pRtlClearBits(&bm, 0, 1);
ok(buff[0] == 0xfe, "didn't clear 1st bit\n");
buff[0] = 0xff;
pRtlClearBits(&bm, 7, 2);
ok(buff[0] == 0x7f && buff[1] == 0xfe, "didn't span w/len < 8\n");
buff[0] = buff[1] = 0xff;
pRtlClearBits(&bm, 7, 10);
ok(buff[0] == 0x7f && buff[1] == 0 && buff[2] == 0xfe, "didn't span w/len > 8\n");
buff[0] = buff[1] = buff[2] = 0xff;
pRtlClearBits(&bm, 0, 8); /* 1st byte */
ok(!buff[0], "didn't clear all bits\n");
ok(buff[1] == 0xff, "cleared too many bits\n");
pRtlClearBits(&bm, sizeof(buff)*8-1, 1);
ok(buff[sizeof(buff)-1] == 0x7f, "didn't set last bit\n");
}
static void test_RtlCheckBit(void)
{
BOOLEAN bRet;
memset(buff, 0 , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
pRtlSetBits(&bm, 0, 1);
pRtlSetBits(&bm, 7, 2);
pRtlSetBits(&bm, sizeof(buff)*8-1, 1);
bRet = RtlCheckBit(&bm, 0);
ok (bRet, "didn't find set bit\n");
bRet = RtlCheckBit(&bm, 7);
ok (bRet, "didn't find set bit\n");
bRet = RtlCheckBit(&bm, 8);
ok (bRet, "didn't find set bit\n");
bRet = RtlCheckBit(&bm, sizeof(buff)*8-1);
ok (bRet, "didn't find set bit\n");
bRet = RtlCheckBit(&bm, 1);
ok (!bRet, "found non set bit\n");
bRet = RtlCheckBit(&bm, sizeof(buff)*8-2);
ok (!bRet, "found non set bit\n");
}
static void test_RtlAreBitsSet(void)
{
BOOLEAN bRet;
if (!pRtlAreBitsSet)
return;
memset(buff, 0 , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
bRet = pRtlAreBitsSet(&bm, 0, 1);
ok (!bRet, "found set bits after init\n");
pRtlSetBits(&bm, 0, 1);
bRet = pRtlAreBitsSet(&bm, 0, 1);
ok (bRet, "didn't find set bits\n");
buff[0] = 0;
pRtlSetBits(&bm, 7, 2);
bRet = pRtlAreBitsSet(&bm, 7, 2);
ok(bRet, "didn't find w/len < 8\n");
bRet = pRtlAreBitsSet(&bm, 6, 3);
ok(!bRet, "found non set bit\n");
bRet = pRtlAreBitsSet(&bm, 7, 3);
ok(!bRet, "found non set bit\n");
buff[0] = buff[1] = 0;
pRtlSetBits(&bm, 7, 10);
bRet = pRtlAreBitsSet(&bm, 7, 10);
ok(bRet, "didn't find w/len < 8\n");
bRet = pRtlAreBitsSet(&bm, 6, 11);
ok(!bRet, "found non set bit\n");
bRet = pRtlAreBitsSet(&bm, 7, 11);
ok(!bRet, "found non set bit\n");
buff[0] = buff[1] = buff[2] = 0;
pRtlSetBits(&bm, 0, 8); /* 1st byte */
bRet = pRtlAreBitsSet(&bm, 0, 8);
ok(bRet, "didn't find whole byte\n");
pRtlSetBits(&bm, sizeof(buff)*8-1, 1);
bRet = pRtlAreBitsSet(&bm, sizeof(buff)*8-1, 1);
ok(bRet, "didn't find last bit\n");
}
static void test_RtlAreBitsClear(void)
{
BOOLEAN bRet;
if (!pRtlAreBitsClear)
return;
memset(buff, 0xff , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
bRet = pRtlAreBitsClear(&bm, 0, 1);
ok (!bRet, "found clear bits after init\n");
pRtlClearBits(&bm, 0, 1);
bRet = pRtlAreBitsClear(&bm, 0, 1);
ok (bRet, "didn't find set bits\n");
buff[0] = 0xff;
pRtlClearBits(&bm, 7, 2);
bRet = pRtlAreBitsClear(&bm, 7, 2);
ok(bRet, "didn't find w/len < 8\n");
bRet = pRtlAreBitsClear(&bm, 6, 3);
ok(!bRet, "found non clear bit\n");
bRet = pRtlAreBitsClear(&bm, 7, 3);
ok(!bRet, "found non clear bit\n");
buff[0] = buff[1] = 0xff;
pRtlClearBits(&bm, 7, 10);
bRet = pRtlAreBitsClear(&bm, 7, 10);
ok(bRet, "didn't find w/len < 8\n");
bRet = pRtlAreBitsClear(&bm, 6, 11);
ok(!bRet, "found non clear bit\n");
bRet = pRtlAreBitsClear(&bm, 7, 11);
ok(!bRet, "found non clear bit\n");
buff[0] = buff[1] = buff[2] = 0xff;
pRtlClearBits(&bm, 0, 8); /* 1st byte */
bRet = pRtlAreBitsClear(&bm, 0, 8);
ok(bRet, "didn't find whole byte\n");
pRtlClearBits(&bm, sizeof(buff)*8-1, 1);
bRet = pRtlAreBitsClear(&bm, sizeof(buff)*8-1, 1);
ok(bRet, "didn't find last bit\n");
}
static void test_RtlNumberOfSetBits(void)
{
ULONG ulCount;
if (!pRtlNumberOfSetBits)
return;
memset(buff, 0 , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
ulCount = pRtlNumberOfSetBits(&bm);
ok(ulCount == 0, "set bits after init\n");
pRtlSetBits(&bm, 0, 1); /* Set 1st bit */
ulCount = pRtlNumberOfSetBits(&bm);
ok(ulCount == 1, "count wrong\n");
pRtlSetBits(&bm, 7, 8); /* 8 more, spanning bytes 1-2 */
ulCount = pRtlNumberOfSetBits(&bm);
ok(ulCount == 8+1, "count wrong\n");
pRtlSetBits(&bm, 17, 33); /* 33 more crossing ULONG boundary */
ulCount = pRtlNumberOfSetBits(&bm);
ok(ulCount == 8+1+33, "count wrong\n");
pRtlSetBits(&bm, sizeof(buff)*8-1, 1); /* Set last bit */
ulCount = pRtlNumberOfSetBits(&bm);
ok(ulCount == 8+1+33+1, "count wrong\n");
}
static void test_RtlNumberOfClearBits(void)
{
ULONG ulCount;
if (!pRtlNumberOfClearBits)
return;
memset(buff, 0xff , sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
ulCount = pRtlNumberOfClearBits(&bm);
ok(ulCount == 0, "cleared bits after init\n");
pRtlClearBits(&bm, 0, 1); /* Set 1st bit */
ulCount = pRtlNumberOfClearBits(&bm);
ok(ulCount == 1, "count wrong\n");
pRtlClearBits(&bm, 7, 8); /* 8 more, spanning bytes 1-2 */
ulCount = pRtlNumberOfClearBits(&bm);
ok(ulCount == 8+1, "count wrong\n");
pRtlClearBits(&bm, 17, 33); /* 33 more crossing ULONG boundary */
ulCount = pRtlNumberOfClearBits(&bm);
ok(ulCount == 8+1+33, "count wrong\n");
pRtlClearBits(&bm, sizeof(buff)*8-1, 1); /* Set last bit */
ulCount = pRtlNumberOfClearBits(&bm);
ok(ulCount == 8+1+33+1, "count wrong\n");
}
/* Note: this tests RtlFindSetBits also */
static void test_RtlFindSetBitsAndClear(void)
{
BOOLEAN bRet;
ULONG ulPos;
if (!pRtlFindSetBitsAndClear)
return;
memset(buff, 0, sizeof(buff));
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
pRtlSetBits(&bm, 0, 32);
ulPos = pRtlFindSetBitsAndClear(&bm, 32, 0);
ok (ulPos == 0, "didn't find bits\n");
if(ulPos == 0)
{
bRet = pRtlAreBitsClear(&bm, 0, 32);
ok (bRet, "found but didn't clear\n");
}
memset(buff, 0 , sizeof(buff));
pRtlSetBits(&bm, 40, 77);
ulPos = pRtlFindSetBitsAndClear(&bm, 77, 0);
ok (ulPos == 40, "didn't find bits\n");
if(ulPos == 40)
{
bRet = pRtlAreBitsClear(&bm, 40, 77);
ok (bRet, "found but didn't clear\n");
}
}
/* Note: this tests RtlFindClearBits also */
static void test_RtlFindClearBitsAndSet(void)
{
BOOLEAN bRet;
ULONG ulPos;
if (!pRtlFindClearBitsAndSet)
return;
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
memset(buff, 0xff, sizeof(buff));
pRtlSetBits(&bm, 0, 32);
ulPos = pRtlFindSetBitsAndClear(&bm, 32, 0);
ok (ulPos == 0, "didn't find bits\n");
if(ulPos == 0)
{
bRet = pRtlAreBitsClear(&bm, 0, 32);
ok (bRet, "found but didn't clear\n");
}
memset(buff, 0xff , sizeof(buff));
pRtlClearBits(&bm, 40, 77);
ulPos = pRtlFindClearBitsAndSet(&bm, 77, 50);
ok (ulPos == 40, "didn't find bits\n");
if(ulPos == 40)
{
bRet = pRtlAreBitsSet(&bm, 40, 77);
ok (bRet, "found but didn't set\n");
}
}
static void test_RtlFindMostSignificantBit(void)
{
int i;
CCHAR cPos;
ULONGLONG ulLong;
if (!pRtlFindMostSignificantBit)
return;
for (i = 0; i < 64; i++)
{
ulLong = 1ul;
ulLong <<= i;
cPos = pRtlFindMostSignificantBit(ulLong);
ok (cPos == i, "didn't find MSB %llx %d %d\n", 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);
}
cPos = pRtlFindMostSignificantBit(0);
ok (cPos == -1, "found bit when not set\n");
}
static void test_RtlFindLeastSignificantBit(void)
{
int i;
CCHAR cPos;
ULONGLONG ulLong;
if (!pRtlFindLeastSignificantBit)
return;
for (i = 0; i < 64; i++)
{
ulLong = (ULONGLONG)1 << i;
cPos = pRtlFindLeastSignificantBit(ulLong);
ok (cPos == i, "didn't find LSB %llx %d %d\n", ulLong, i, cPos);
ulLong = ~((ULONGLONG)0) << i;
cPos = pRtlFindLeastSignificantBit(ulLong);
ok (cPos == i, "didn't find LSB %llx %d %d\n", ulLong, i, cPos);
}
cPos = pRtlFindLeastSignificantBit(0);
ok (cPos == -1, "found bit when not set\n");
}
/* Note: Also tests RtlFindLongestRunSet() */
static void test_RtlFindSetRuns(void)
{
RTL_BITMAP_RUN runs[16];
ULONG ulCount;
if (!pRtlFindSetRuns)
return;
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
memset(buff, 0, sizeof(buff));
ulCount = pRtlFindSetRuns(&bm, runs, 16, TRUE);
ok (ulCount == 0, "found set bits in empty bitmap\n");
memset(runs, 0, sizeof(runs));
memset(buff, 0xff, sizeof(buff));
ulCount = pRtlFindSetRuns(&bm, runs, 16, TRUE);
ok (ulCount == 1, "didn't find set bits\n");
ok (runs[0].StartingIndex == 0,"bad start\n");
ok (runs[0].NumberOfBits == sizeof(buff)*8,"bad size\n");
/* Set up 3 runs */
memset(runs, 0, sizeof(runs));
memset(buff, 0, sizeof(buff));
pRtlSetBits(&bm, 7, 19);
pRtlSetBits(&bm, 101, 3);
pRtlSetBits(&bm, 1877, 33);
/* Get first 2 */
ulCount = pRtlFindSetRuns(&bm, runs, 2, FALSE);
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101,"bad find\n");
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101,"bad find\n");
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 19 + 3,"bad size\n");
ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
ok (runs[2].StartingIndex == 0,"found extra run\n");
/* Get longest 3 */
memset(runs, 0, sizeof(runs));
ulCount = pRtlFindSetRuns(&bm, runs, 2, TRUE);
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 1877,"bad find\n");
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 1877,"bad find\n");
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 33 + 19,"bad size\n");
ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
ok (runs[2].StartingIndex == 0,"found extra run\n");
/* Get all 3 */
memset(runs, 0, sizeof(runs));
ulCount = pRtlFindSetRuns(&bm, runs, 3, TRUE);
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101 ||
runs[0].StartingIndex == 1877,"bad find\n");
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101 ||
runs[1].StartingIndex == 1877,"bad find\n");
ok (runs[2].StartingIndex == 7 || runs[2].StartingIndex == 101 ||
runs[2].StartingIndex == 1877,"bad find\n");
ok (runs[0].NumberOfBits + runs[1].NumberOfBits
+ runs[2].NumberOfBits == 19 + 3 + 33,"bad size\n");
ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
ok (runs[1].StartingIndex != runs[2].StartingIndex,"found run twice\n");
ok (runs[3].StartingIndex == 0,"found extra run\n");
if (pRtlFindLongestRunSet)
{
ULONG ulStart = 0;
ulCount = pRtlFindLongestRunSet(&bm, &ulStart);
ok(ulCount == 33 && ulStart == 1877,"didn't find longest %ld %ld\n",ulCount,ulStart);
memset(buff, 0, sizeof(buff));
ulCount = pRtlFindLongestRunSet(&bm, &ulStart);
ok(ulCount == 0,"found longest when none set\n");
}
}
/* Note: Also tests RtlFindLongestRunClear() */
static void test_RtlFindClearRuns(void)
{
RTL_BITMAP_RUN runs[16];
ULONG ulCount;
if (!pRtlFindClearRuns)
return;
pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
memset(buff, 0xff, sizeof(buff));
ulCount = pRtlFindClearRuns(&bm, runs, 16, TRUE);
ok (ulCount == 0, "found clear bits in full bitmap\n");
memset(runs, 0, sizeof(runs));
memset(buff, 0, sizeof(buff));
ulCount = pRtlFindClearRuns(&bm, runs, 16, TRUE);
ok (ulCount == 1, "didn't find clear bits\n");
ok (runs[0].StartingIndex == 0,"bad start\n");
ok (runs[0].NumberOfBits == sizeof(buff)*8,"bad size\n");
/* Set up 3 runs */
memset(runs, 0, sizeof(runs));
memset(buff, 0xff, sizeof(buff));
pRtlClearBits(&bm, 7, 19);
pRtlClearBits(&bm, 101, 3);
pRtlClearBits(&bm, 1877, 33);
/* Get first 2 */
ulCount = pRtlFindClearRuns(&bm, runs, 2, FALSE);
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101,"bad find\n");
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101,"bad find\n");
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 19 + 3,"bad size\n");
ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
ok (runs[2].StartingIndex == 0,"found extra run\n");
/* Get longest 3 */
memset(runs, 0, sizeof(runs));
ulCount = pRtlFindClearRuns(&bm, runs, 2, TRUE);
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 1877,"bad find\n");
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 1877,"bad find\n");
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 33 + 19,"bad size\n");
ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
ok (runs[2].StartingIndex == 0,"found extra run\n");
/* Get all 3 */
memset(runs, 0, sizeof(runs));
ulCount = pRtlFindClearRuns(&bm, runs, 3, TRUE);
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101 ||
runs[0].StartingIndex == 1877,"bad find\n");
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101 ||
runs[1].StartingIndex == 1877,"bad find\n");
ok (runs[2].StartingIndex == 7 || runs[2].StartingIndex == 101 ||
runs[2].StartingIndex == 1877,"bad find\n");
ok (runs[0].NumberOfBits + runs[1].NumberOfBits
+ runs[2].NumberOfBits == 19 + 3 + 33,"bad size\n");
ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
ok (runs[1].StartingIndex != runs[2].StartingIndex,"found run twice\n");
ok (runs[3].StartingIndex == 0,"found extra run\n");
if (pRtlFindLongestRunClear)
{
ULONG ulStart = 0;
ulCount = pRtlFindLongestRunClear(&bm, &ulStart);
ok(ulCount == 33 && ulStart == 1877,"didn't find longest\n");
memset(buff, 0xff, sizeof(buff));
ulCount = pRtlFindLongestRunClear(&bm, &ulStart);
ok(ulCount == 0,"found longest when none clear\n");
}
}
#endif
START_TEST(rtlbitmap)
{
#ifdef __WINE_WINTERNL_H
InitFunctionPtrs();
if (pRtlInitializeBitMap)
{
test_RtlInitializeBitMap();
test_RtlSetAllBits();
test_RtlClearAllBits();
test_RtlSetBits();
test_RtlClearBits();
test_RtlCheckBit();
test_RtlAreBitsSet();
test_RtlAreBitsClear();
test_RtlNumberOfSetBits();
test_RtlNumberOfClearBits();
test_RtlFindSetBitsAndClear();
test_RtlFindClearBitsAndSet();
test_RtlFindMostSignificantBit();
test_RtlFindLeastSignificantBit();
test_RtlFindSetRuns();
test_RtlFindClearRuns();
}
#endif
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
/* Automatically generated file; DO NOT EDIT!! */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include <windows.h>
extern void func_atom(void);
extern void func_env(void);
extern void func_error(void);
extern void func_info(void);
extern void func_large_int(void);
extern void func_path(void);
extern void func_reg(void);
extern void func_rtl(void);
extern void func_rtlbitmap(void);
extern void func_rtlstr(void);
extern void func_string(void);
extern void func_time(void);
struct test
{
const char *name;
void (*func)(void);
};
const struct test winetest_testlist[] =
{
{ "atom", func_atom },
{ "env", func_env },
{ "error", func_error },
{ "info", func_info },
{ "large_int", func_large_int },
{ "path", func_path },
{ "reg", func_reg },
{ "rtl", func_rtl },
{ "rtlbitmap", func_rtlbitmap },
{ "rtlstr", func_rtlstr },
{ "string", func_string },
{ "time", func_time },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -0,0 +1,109 @@
/*
* Unit test suite for ntdll time functions
*
* Copyright 2004 Rein Klazes
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ntdll_test.h"
#ifdef __WINE_WINTERNL_H
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
#define SECSPERDAY 86400
static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
static const int MonthLengths[2][12] =
{
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
static inline int IsLeapYear(int Year)
{
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
}
/* start time of the tests */
TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0};
static void test_pRtlTimeToTimeFields()
{
LARGE_INTEGER litime , liresult;
TIME_FIELDS tfresult;
int i=0;
litime.QuadPart = ((ULONGLONG)0x0144017a << 32) | 0xf0b0a980;
while( tftest.Year < 2110 ) {
/* 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.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,
tftest.Hour, tftest.Minute,tftest.Second,
tfresult.Year, tfresult.Month, tfresult.Day,
tfresult.Hour, tfresult.Minute, tfresult.Second);
/* test the inverse */
pRtlTimeFieldsToTime( &tfresult, &liresult);
ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
tfresult.Year, tfresult.Month, tfresult.Day,
tfresult.Hour, tfresult.Minute, tfresult.Second,
(int) (liresult.QuadPart - litime.QuadPart) );
/* one second later is beginning of next month */
litime.QuadPart += TICKSPERSEC ;
pRtlTimeToTimeFields( &litime, &tfresult);
ok( tfresult.Year == tftest.Year + (tftest.Month ==12) &&
tfresult.Month == tftest.Month % 12 + 1 &&
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),
tftest.Month % 12 + 1, 1, 0, 0, 0,
tfresult.Year, tfresult.Month, tfresult.Day,
tfresult.Hour, tfresult.Minute, tfresult.Second);
/* test the inverse */
pRtlTimeFieldsToTime( &tfresult, &liresult);
ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
tfresult.Year, tfresult.Month, tfresult.Day,
tfresult.Hour, tfresult.Minute, tfresult.Second,
(int) (liresult.QuadPart - litime.QuadPart) );
/* advance to the end of the month */
litime.QuadPart -= TICKSPERSEC ;
if( tftest.Month == 12) {
tftest.Month = 1;
tftest.Year += 1;
} else
tftest.Month += 1;
tftest.Day = MonthLengths[IsLeapYear(tftest.Year)][tftest.Month - 1];
litime.QuadPart += (LONGLONG) tftest.Day * TICKSPERSEC * SECSPERDAY;
}
}
#endif
START_TEST(time)
{
#ifdef __WINE_WINTERNL_H
HMODULE mod = GetModuleHandleA("ntdll.dll");
pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
test_pRtlTimeToTimeFields();
#endif
}