windows-nt/Source/XPSP1/NT/base/ntos/config/test/rtmisc1.c

845 lines
20 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
rtmisc1.c
Abstract:
NT level registry api test program #1, basic non-error paths.
Test open, create, setvalue, queryvalue, enumeratekey, enumeratevalue,
querykey.
Author:
Bryan Willman (bryanwi) 19-Nov-91
Revision History:
--*/
#include "cmp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//
// NOTE: This version of the test operations on \REGISTRY\MACHINE\TEST\*,
// which is the TEST hive. This hive will not exist in production
// systems, so the test will have to change.
//
void __cdecl main(int, char *);
VOID
NameClassAndTitle(
KEY_NODE_INFORMATION *NodeInformation,
UNICODE_STRING ClassName,
ULONG TitleIndex,
UNICODE_STRING KeyName,
LARGE_INTEGER CompTime,
BOOLEAN Strong, // time must be >= CompTime
PUCHAR TestName
);
VOID
expectstring(
PWSTR expected,
ULONG expectedlength,
PWSTR actual,
ULONG actuallength
);
VOID
expecttime(
LARGE_INTEGER ExpectTime,
LARGE_INTEGER ActualTime
);
#define TITLE_INDEX_1 122259
#define TITLE_INDEX_2 120858
#define TITLE_INDEX_3 120159
#define TYPE_1 666
#define TYPE_2 1066
ULONG failure = 0;
void
__cdecl main(int, char *)
{
NTSTATUS status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
UNICODE_STRING KeyName2;
UNICODE_STRING ClassName;
UNICODE_STRING ClassName2;
UNICODE_STRING ValueName;
UNICODE_STRING ValueName2;
HANDLE BaseHandle;
HANDLE Testhand1;
ULONG Disposition;
LARGE_INTEGER CompTime;
ULONG buffer[100];
ULONG bufsize = sizeof(ULONG) * 100;
PKEY_NODE_INFORMATION NodeInformation;
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
PKEY_VALUE_BASIC_INFORMATION KeyValueBasic;
ULONG ResultLength;
PUCHAR datastring = "Some simple ascii data for use as a value";
PUCHAR datastring2 = "Some more not so simple data $#";
ULONG expected;
PVOID tp;
printf("rtmisc1: starting\n");
NodeInformation = (PKEY_NODE_INFORMATION)&(buffer[0]);
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)&(buffer[0]);
KeyValueBasic = (PKEY_VALUE_BASIC_INFORMATION)&(buffer[0]);
//
// t0: Perform all operations against a base node, open it here.
//
RtlInitUnicodeString(
&KeyName,
L"\\REGISTRY\\MACHINE\\TEST"
);
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
0,
(HANDLE)NULL,
NULL
);
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
status = NtOpenKey(
&BaseHandle,
MAXIMUM_ALLOWED,
&ObjectAttributes
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t0: %08lx\n", status);
goto punt;
}
//
// t1: Create a key with class and title index
//
RtlInitUnicodeString(
&ClassName,
L"t1 Class Name"
);
RtlInitUnicodeString(
&KeyName,
L"first_test_node"
);
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
0,
BaseHandle,
NULL
);
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
NtQuerySystemTime(&CompTime);
// printf("ClassName@%08lx KeyName@%08lx\n",
// ClassName.Buffer, KeyName.Buffer);
status = NtCreateKey(
&Testhand1,
MAXIMUM_ALLOWED,
&ObjectAttributes,
TITLE_INDEX_1,
&ClassName,
0,
&Disposition
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t1: %08lx\n", status);
goto punt;
}
if (Disposition != REG_CREATED_NEW_KEY) {
printf("rtmisc1: t1a: got old key, expected to create new one\n");
failure++;
}
//
// t2: See if we can get data back, and if it makes sense
//
RtlZeroMemory(NodeInformation, bufsize);
status = NtQueryKey(
Testhand1,
KeyNodeInformation,
NodeInformation,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t2a: %08lx\n", status);
goto punt;
}
if (ResultLength != 80) {
printf("rtmisc1: t2i: expect 80, ResultLength = %d\n", ResultLength);
failure++;
}
NameClassAndTitle(
NodeInformation,
ClassName,
TITLE_INDEX_1,
KeyName,
CompTime,
FALSE, // time must be >= CompTime
"rtmisc1: t2b: "
);
CompTime = NodeInformation->LastWriteTime;
status = NtClose(Testhand1);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t2c: %08lx\n");
goto punt;
}
//
// t3: Reopen the key with create, see if data still there.
//
status = NtCreateKey(
&Testhand1,
MAXIMUM_ALLOWED,
&ObjectAttributes,
TITLE_INDEX_1,
&ClassName,
0,
&Disposition
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t3: %08lx\n", status);
goto punt;
}
if (Disposition != REG_OPENED_EXISTING_KEY) {
printf("rtmisc1: t3a failure\n");
failure++;
}
RtlZeroMemory(NodeInformation, bufsize);
status = NtQueryKey(
Testhand1,
KeyNodeInformation,
NodeInformation,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t3b: %08lx\n", status);
goto punt;
}
NameClassAndTitle(
NodeInformation,
ClassName,
TITLE_INDEX_1,
KeyName,
CompTime,
FALSE, // time must be >= CompTime
"rtmisc1: t3c: "
);
status = NtClose(Testhand1);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t3d: %08lx\n");
goto punt;
}
//
// t4: Reopen the key with open, see if data still there.
//
status = NtOpenKey(
&Testhand1,
MAXIMUM_ALLOWED,
&ObjectAttributes
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t4: %08lx\n", status);
goto punt;
}
RtlZeroMemory(NodeInformation, bufsize);
status = NtQueryKey(
Testhand1,
KeyNodeInformation,
NodeInformation,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t4a: %08lx\n", status);
goto punt;
}
NameClassAndTitle(
NodeInformation,
ClassName,
TITLE_INDEX_1,
KeyName,
CompTime,
FALSE, // time must be >= CompTime
"rtmisc1: t4b: "
);
// status = NtClose(Testhand1);
// if (!NT_SUCCESS(status)) {
// printf("rtmisc1: t4c: %08lx\n");
// exit(1);
// }
//
// t5: Create a value
//
RtlInitUnicodeString(
&ValueName,
L"the very first value stored in the registry"
);
status = NtSetValueKey(
Testhand1,
&ValueName,
TITLE_INDEX_2,
TYPE_1,
datastring,
strlen(datastring)+1
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t5: %08lx\n", status);
failure++;
}
//
// t6: Read the value back
//
RtlZeroMemory(KeyValueInformation, bufsize);
status = NtQueryValueKey(
Testhand1,
&ValueName,
KeyValueFullInformation,
KeyValueInformation,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t6: %08lx\n", status);
goto punt;
}
expected = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) +
ValueName.Length + strlen(datastring) + 1;
if (ResultLength != expected) {
printf("rtmisc1: t6a: expected = %08lx actual = %08lx",
expected, ResultLength);
failure++;
}
if ( (KeyValueInformation->TitleIndex != TITLE_INDEX_2) ||
(KeyValueInformation->Type != TYPE_1) ||
(KeyValueInformation->NameLength != ValueName.Length) ||
(KeyValueInformation->DataLength != strlen(datastring)+1))
{
printf("rtmisc1: t6b: wrong description data\n");
failure++;
}
tp = (PWSTR)&(KeyValueInformation->Name[0]);
if (wcsncmp(ValueName.Buffer, tp, (ValueName.Length/sizeof(WCHAR))) != 0) {
printf("rtmisc1: t6c: wrong name\n");
expectstring(
ValueName.Buffer,
(ValueName.Length/sizeof(WCHAR)),
(PWSTR)&(KeyValueInformation->Name[0]),
(KeyValueInformation->NameLength/sizeof(WCHAR))
);
failure++;
}
tp = (PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset;
if (strcmp(tp, datastring) != 0) {
printf("rtmisc1: t6d: wrong data\n");
printf("expected '%s', got '%s'\n", datastring, tp);
failure++;
}
//
// t7: Create a second value
//
RtlInitUnicodeString(
&ValueName2,
L"the second value stored in the registry"
);
status = NtSetValueKey(
Testhand1,
&ValueName2,
TITLE_INDEX_3,
TYPE_2,
datastring2,
strlen(datastring2)+1
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t7: %08lx\n", status);
failure++;
}
//
// t8: Read the second value back (short form)
//
RtlZeroMemory(KeyValueBasic, bufsize);
status = NtQueryValueKey(
Testhand1,
&ValueName2,
KeyValueBasicInformation,
KeyValueBasic,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t8: %08lx\n", status);
goto punt;
}
expected = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
ValueName2.Length;
if (ResultLength != expected) {
printf("rtmisc1: t8a: expected = %08lx actual = %08lx",
expected, ResultLength);
failure++;
}
if ( (KeyValueBasic->TitleIndex != TITLE_INDEX_3) ||
(KeyValueBasic->Type != TYPE_2) ||
(KeyValueBasic->NameLength != ValueName2.Length))
{
printf("rtmisc1: t8b: wrong description data\n");
failure++;
}
tp = (PWSTR)&(KeyValueBasic->Name[0]);
if (wcsncmp(ValueName2.Buffer, tp, (ValueName2.Length/sizeof(WCHAR))) != 0) {
printf("rtmisc1: t8c: wrong name\n");
expectstring(
ValueName2.Buffer,
(ValueName2.Length/sizeof(WCHAR)),
(PWSTR)&(KeyValueBasic->Name[0]),
(KeyValueBasic->NameLength/sizeof(WCHAR))
);
failure++;
}
//
// t9: Enumerate the values (short form)
//
RtlZeroMemory(KeyValueBasic, bufsize);
status = NtEnumerateValueKey(
Testhand1,
0, // Index
KeyValueBasicInformation,
KeyValueBasic,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t9: %08lx\n", status);
goto punt;
}
expected = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
ValueName.Length;
if (ResultLength != expected) {
printf("rtmisc1: t9a: expected = %08lx actual = %08lx",
expected, ResultLength);
failure++;
}
if (KeyValueBasic->NameLength != ValueName.Length)
{
printf("rtmisc1: t9b: wrong description data\n");
failure++;
}
tp = (PWSTR)&(KeyValueBasic->Name[0]);
if (wcsncmp(ValueName.Buffer, tp, (ValueName.Length/sizeof(WCHAR))) != 0) {
printf("rtmisc1: t9c: wrong name\n");
expectstring(
ValueName.Buffer,
(ValueName.Length/sizeof(WCHAR)),
(PWSTR)&(KeyValueBasic->Name[0]),
(KeyValueBasic->NameLength/sizeof(WCHAR))
);
failure++;
}
RtlZeroMemory(KeyValueBasic, bufsize);
status = NtEnumerateValueKey(
Testhand1,
1, // Index
KeyValueBasicInformation,
KeyValueBasic,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t9d: %08lx\n", status);
goto punt;
}
expected = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
ValueName2.Length;
if (ResultLength != expected) {
printf("rtmisc1: t9e: expected = %08lx actual = %08lx",
expected, ResultLength);
failure++;
}
if (KeyValueBasic->NameLength != ValueName2.Length)
{
printf("rtmisc1: t9f: wrong description data\n");
failure++;
}
tp = (PWSTR)&(KeyValueBasic->Name[0]);
if (wcsncmp(ValueName2.Buffer, tp, (ValueName2.Length/sizeof(WCHAR))) != 0) {
printf("rtmisc1: t9g: wrong name\n");
expectstring(
ValueName2.Buffer,
(ValueName2.Length/sizeof(WCHAR)),
(PWSTR)&(KeyValueBasic->Name[0]),
(KeyValueBasic->NameLength/sizeof(WCHAR))
);
failure++;
}
status = NtEnumerateValueKey(
Testhand1,
2, // Index
KeyValueBasicInformation,
KeyValueBasic,
bufsize,
&ResultLength
);
if (status != STATUS_NO_MORE_ENTRIES) {
printf("rtmisc1: t9h: %08lx\n", status);
goto punt;
}
//
// t10: create a second subkey and ennumerate the subkeys
//
status = NtClose(Testhand1);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t10a: %08lx\n", status);
failure++;
}
RtlInitUnicodeString(
&ClassName2,
L"t2 Class Name"
);
RtlInitUnicodeString(
&KeyName2,
L"second_test_node"
);
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName2,
0,
BaseHandle,
NULL
);
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
status = NtCreateKey(
&Testhand1,
MAXIMUM_ALLOWED,
&ObjectAttributes,
TITLE_INDEX_2,
&ClassName2,
0,
&Disposition
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t10b: %08lx\n", status);
goto punt;
}
if (Disposition != REG_CREATED_NEW_KEY) {
printf("rtmisc1: t10c: got old key, expected to create new one\n");
failure++;
}
//
// See if we can get data back, and if it makes sense
//
RtlZeroMemory(NodeInformation, bufsize);
status = NtQueryKey(
Testhand1,
KeyNodeInformation,
NodeInformation,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t10d: %08lx\n", status);
goto punt;
}
CompTime = NodeInformation->LastWriteTime;
NameClassAndTitle(
NodeInformation,
ClassName2,
TITLE_INDEX_2,
KeyName2,
CompTime,
TRUE,
"rtmisc1: t10e: "
);
status = NtClose(Testhand1);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t10f: %08lx\n");
goto punt;
}
RtlZeroMemory(NodeInformation, bufsize);
status = NtEnumerateKey(
BaseHandle,
0,
KeyNodeInformation,
NodeInformation,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t10g: %08lx\n", status);
failure++;
}
CompTime = NodeInformation->LastWriteTime;
NameClassAndTitle(
NodeInformation,
ClassName,
TITLE_INDEX_1,
KeyName,
CompTime,
TRUE,
"rtmisc1: t10h: "
);
RtlZeroMemory(NodeInformation, bufsize);
status = NtEnumerateKey(
BaseHandle,
1,
KeyNodeInformation,
NodeInformation,
bufsize,
&ResultLength
);
if (!NT_SUCCESS(status)) {
printf("rtmisc1: t10i: %08lx\n", status);
failure++;
}
CompTime = NodeInformation->LastWriteTime;
NameClassAndTitle(
NodeInformation,
ClassName2,
TITLE_INDEX_2,
KeyName2,
CompTime,
TRUE,
"rtmisc1: t10j: "
);
status = NtEnumerateKey(
BaseHandle,
2,
KeyNodeInformation,
NodeInformation,
bufsize,
&ResultLength
);
if (status != STATUS_NO_MORE_ENTRIES) {
printf("rtmisc1: t10k: %08lx\n", status);
failure++;
}
//
// Summary report
//
if (!failure) {
printf("rtmisc1: success");
exit(0);
} else {
printf("rtmisc1: failed, %d failures\n", failure);
exit(1);
}
punt:
failure++;
printf("rtmisc1: failed, %d failures\n", failure);
exit(1);
}
VOID
NameClassAndTitle(
KEY_NODE_INFORMATION *NodeInformation,
UNICODE_STRING ClassName,
ULONG TitleIndex,
UNICODE_STRING KeyName,
LARGE_INTEGER CompTime,
BOOLEAN Strong, // time must be >= CompTime
PUCHAR TestName
)
{
PWSTR p;
if (Strong) {
//
// require exact match
//
if ((CompTime.HighPart != NodeInformation->LastWriteTime.HighPart) ||
(CompTime.LowPart != NodeInformation->LastWriteTime.LowPart))
{
printf("%s Wrong time (a)\n", TestName);
expecttime(CompTime, NodeInformation->LastWriteTime);
failure++;
}
} else {
//
// >= will do
//
if ( (CompTime.HighPart > NodeInformation->LastWriteTime.HighPart) ||
((CompTime.HighPart == NodeInformation->LastWriteTime.HighPart) &&
(CompTime.LowPart > NodeInformation->LastWriteTime.LowPart)) )
{
printf("%s Wrong time (b)\n", TestName);
expecttime(CompTime, NodeInformation->LastWriteTime);
failure++;
}
}
p = (PWSTR)((PUCHAR)NodeInformation + NodeInformation->ClassOffset);
if ( (NodeInformation->ClassLength != ClassName.Length) ||
(wcsncmp(ClassName.Buffer, p, (ClassName.Length/sizeof(WCHAR))) != 0))
{
printf("%s wrong class name\n", TestName);
failure++;
}
if (NodeInformation->TitleIndex != TitleIndex) {
printf("%s wrong title index\n", TestName);
failure++;
}
p = (PWSTR)(&(NodeInformation->Name[0]));
if ( (NodeInformation->NameLength != KeyName.Length) ||
(wcsncmp(KeyName.Buffer, p, (KeyName.Length/sizeof(WCHAR))) != 0))
{
printf("%s wrong name\n", TestName);
expectstring(
KeyName.Buffer,
(KeyName.Length/sizeof(WCHAR)),
(PWSTR)&(NodeInformation->Name[0]),
(NodeInformation->NameLength/sizeof(WCHAR))
);
failure++;
}
}
VOID
expecttime(
LARGE_INTEGER ExpectTime,
LARGE_INTEGER ActualTime
)
{
printf("Expected %08lx%08lx\n", ExpectTime.HighPart, ExpectTime.LowPart);
printf("Got %08lx%08lx\n", ActualTime.HighPart, ActualTime.LowPart);
return;
}
VOID
expectstring(
PWSTR expected,
ULONG expectedlength,
PWSTR actual,
ULONG actuallength
)
{
ULONG i;
printf("Expected Len %d Str = '", expectedlength);
for (i = 0; i < expectedlength; i++) {
printf("%c", (UCHAR)(expected[i]));
}
printf("'\n");
printf("Got Len %d Str = '", actuallength);
for (i = 0; i < actuallength; i++) {
printf("%c", (UCHAR)(actual[i]));
}
printf("'\n");
return;
}